T09 · Insecure Skill Coding Practices
Error
- Location
- bin/publishmd-cf.js:41
- Finding
- Shell Command Injection Through Untrusted Configuration Values<![CDATA[ ## Vulnerability Details **File Location**: `bin/publishmd-cf.js:41-55, 301-307, 511-523` **Vulnerability Type**: OS command injection **Risk Level**: High ### Complete Code Snippet ```javascript function sh(command, cwd, quiet = false) { if (DRY_RUN && !quiet) { const redacted = command .replace(/CLOUDFLARE_API_TOKEN="[^"]*"/g, 'CLOUDFLARE_API_TOKEN="***"') .replace(/BASIC_AUTH_PASSWORD="[^"]*"/g, 'BASIC_AUTH_PASSWORD="***"'); console.log(`[dry-run] ${redacted}`); return ''; } if (quiet) return execSync(command, { stdio: ['ignore', 'pipe', 'pipe'], cwd: cwd || process.cwd() }).toString(); execSync(command, { stdio: 'inherit', cwd: cwd || process.cwd() }); } ``` ```javascript const excludes = (cfg.source.excludeFolders || []) .map((f) => `--exclude '${f}/'`) .join(' '); sh(`rsync -av --exclude '.obsidian/' --exclude '*.canvas' ${excludes} "${src}/" "${dest}/${folder}/"`); ``` ```javascript const envPrefix = [ `CLOUDFLARE_API_TOKEN="${token.replace(/"/g, '\\"')}"`, accountId ? `CLOUDFLARE_ACCOUNT_ID="${accountId.replace(/"/g, '\\"')}"` : '' ].filter(Boolean).join(' '); sh(`${envPrefix} npx wrangler pages deploy public --project-name "${project}" --branch "${branch}"`, workspaceDir); ``` ### Technical Analysis The `sh()` helper passes dynamically constructed strings to `execSync()`, which invokes a shell. Multiple values originating from `config.json`, `.env`, or wizard input are interpolated into these strings. Quoting does not provide adequate protection. Values placed inside double quotes can still contain shell substitutions such as `$(command)` or backticks. The Cloudflare token handling escapes only double-quote characters and does not neutralize command substitutions, backslashes, newlines, or other shell syntax. The single-quoted `rsync` exclusion values can escape their quoting context by containing a single quote. Affected values include source and exclusion folder names, workspace paths, Cloudfl ...[truncated 1175 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Replace shell-string execution with `execFileSync()` or `spawnSync()` and explicit argument arrays. 2. Invoke `rsync`, `git`, `npm`, `npx`, and `wrangler` directly without `shell: true`. 3. Supply Cloudflare credentials using the child process `env` option rather than embedding them in a command prefix. 4. Validate folder names, project names, and branch names against strict expected formats. 5. Reject control characters, newlines, traversal segments, and unexpected absolute paths. 6. Do not attempt to implement shell escaping manually; argument-array APIs avoid shell interpretation entirely. 7. Add tests containing quotes, command substitutions, semicolons, newlines, and backticks to verify that values are treated only as literal arguments. ]]>
