T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/dsh-api-probe.sh:71
- Finding
- User-Controlled Repository Path Enables JavaScript Injection in the Bash Probe<![CDATA[ ## Vulnerability Details **File Location**: `scripts/dsh-api-probe.sh:71` **Vulnerability Type**: JavaScript injection through unsafe string interpolation **Risk Level**: High ### Vulnerable Code ```bash REPO="" QUIET=0 for a in "$@"; do case "$a" in --quiet) QUIET=1 ;; *) REPO="$a" ;; esac done # ... LIVE_VER="$(node -e "try{console.log(require('$REPO/package.json').version||'unknown')}catch(e){console.log('unknown')}" 2>/dev/null || echo unknown)" ``` ### Technical Analysis The repository path originates from a command-line argument or the `DSH_REPO` environment variable. It is then interpolated directly into JavaScript source passed to `node -e`. Shell quoting does not make this safe at the JavaScript layer. A single quote in the repository path can terminate the JavaScript string passed to `require()`. Additional JavaScript statements embedded in the path can then be evaluated by Node.js. The preceding repository checks only verify that expected directories exist. They do not reject JavaScript metacharacters or otherwise prevent the path from changing the syntax of the generated program. The Python probe does not have this flaw because it passes values as subprocess argument-array elements instead of constructing executable source from them. ### Attack Path 1. An attacker creates or supplies a repository directory whose name contains a JavaScript payload. 2. The attacker creates the minimum expected directory structure, such as `packages/` and `vendor/loader/`, so the repository guard accepts it. 3. The victim or Agent runs the recommended Bash probe against that path: ```bash bash scripts/dsh-api-probe.sh "<attacker-controlled-path>" ``` 4. The path is inserted into the source string passed to `node -e`. 5. Embedded JavaScript breaks out of the `require()` path and invokes functionality such as `node:child_process`. 6. The injected code executes with the same operating-system privileges as the user or Agent running ...[truncated 487 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions Do not interpolate filesystem paths into JavaScript source. Pass the package path as a separate argument: ```bash LIVE_VER="$( node -e ' try { console.log(require(process.argv[1]).version || "unknown") } catch { console.log("unknown") } ' "$REPO/package.json" 2>/dev/null || echo unknown )" ``` Additional hardening measures: 1. Make the Python probe the only recommended implementation unless Bash compatibility is essential. 2. Add a regression test using repository paths containing single quotes, spaces, parentheses, semicolons, and newline characters. 3. Avoid `node -e` whenever structured data can be read with a parser that accepts a filename argument. 4. Canonicalize the repository path before use, while recognizing that canonicalization alone does not replace safe argument passing. ]]>
