feat: add validateClipboardCmd with whitelist-based input validation
Prevents shell injection by only allowing known-safe clipboard commands (dms cl copy, wl-copy, clipmanctl copy, none).
This commit is contained in:
parent
7c12793b98
commit
a86d5e279d
2 changed files with 30 additions and 2 deletions
|
|
@ -26,6 +26,12 @@ function findActiveExitNode(peerMap) {
|
|||
return ""
|
||||
}
|
||||
|
||||
var safeClipboardCmds = ["dms cl copy", "wl-copy", "clipmanctl copy", "none"]
|
||||
|
||||
function validateClipboardCmd(cmd) {
|
||||
return typeof cmd === "string" && safeClipboardCmds.includes(cmd)
|
||||
}
|
||||
|
||||
function errorMessage(cmd) {
|
||||
var messages = {
|
||||
"up": "Failed to connect to Tailscale",
|
||||
|
|
@ -40,5 +46,5 @@ function errorMessage(cmd) {
|
|||
|
||||
// CommonJS export for Node.js tests (ignored by QML)
|
||||
if (typeof module !== "undefined" && module.exports) {
|
||||
module.exports = { parsePeers, makeExitNodeCommand, findActiveExitNode, errorMessage }
|
||||
module.exports = { parsePeers, makeExitNodeCommand, findActiveExitNode, errorMessage, validateClipboardCmd }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { test } from "node:test"
|
||||
import assert from "node:assert"
|
||||
import lib from "../tailscalectl/lib.js"
|
||||
const { parsePeers, makeExitNodeCommand, findActiveExitNode, errorMessage } = lib
|
||||
const { parsePeers, makeExitNodeCommand, findActiveExitNode, errorMessage, validateClipboardCmd } = lib
|
||||
|
||||
test("parsePeers extracts exitNode from ExitNodeOption", () => {
|
||||
const peerMap = {
|
||||
|
|
@ -74,3 +74,25 @@ test("errorMessage returns generic message for unknown command", () => {
|
|||
const msg = errorMessage("unknown", 1)
|
||||
assert.strictEqual(msg, "Tailscale command failed")
|
||||
})
|
||||
|
||||
// --- validateClipboardCmd ---
|
||||
|
||||
test("validateClipboardCmd accepts whitelisted values", () => {
|
||||
assert.strictEqual(validateClipboardCmd("dms cl copy"), true)
|
||||
assert.strictEqual(validateClipboardCmd("wl-copy"), true)
|
||||
assert.strictEqual(validateClipboardCmd("clipmanctl copy"), true)
|
||||
assert.strictEqual(validateClipboardCmd("none"), true)
|
||||
})
|
||||
|
||||
test("validateClipboardCmd rejects malicious inputs", () => {
|
||||
assert.strictEqual(validateClipboardCmd("rm -rf /"), false)
|
||||
assert.strictEqual(validateClipboardCmd("echo hi; malicious"), false)
|
||||
assert.strictEqual(validateClipboardCmd("$(whoami)"), false)
|
||||
assert.strictEqual(validateClipboardCmd("wl-copy || rm -rf /"), false)
|
||||
})
|
||||
|
||||
test("validateClipboardCmd rejects empty and falsy inputs", () => {
|
||||
assert.strictEqual(validateClipboardCmd(""), false)
|
||||
assert.strictEqual(validateClipboardCmd(null), false)
|
||||
assert.strictEqual(validateClipboardCmd(undefined), false)
|
||||
})
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue