The input is an owned local Node.js fixture. The demo reads source, sends no network request and
does not execute project dependencies. A source match remains a suspected lead.
| Input | Finding | Evidence state | Proposal | Security retest | Functional retest |
|---|---|---|---|---|---|
examples/insecure-demo/src/export-report.mjs |
OS command injection lead (CWE-78) | suspected |
Trace command inputs, prefer execFile/spawn with shell disabled and pass each validated argument separately. | fixed |
passed |
The server starts a command through a shell. A shell treats special characters as instructions, so unsafe input can change what runs.
Possible consequence: If request or job input reaches the command string, an attacker may read files, change data or run programs with the application permissions.
Evidence boundary: The rule resolves direct child_process imports/requires and finds exec/execSync or process calls with shell: true. It does not trace arguments or prove reachability.
Possible side effect: Command quoting and platform behavior may change; existing automation can require explicit argument handling.
--- a/src/export-report.mjs
+++ b/src/export-report.mjs
@@
-import { exec } from 'node:child_process';
+import { execFile } from 'node:child_process';
@@
- exec(`printf '%s\\n' "${title}"`, (error, stdout) => {
+ execFile('printf', ['%s\\n', title], (error, stdout) => {The patch is not proof of a fix. The compatible source retest records the original finding as
fixed; the separate fixed-input product test records:
functional retest passed: ordinary report export still works.
Run npm run demo -- --out ./demo-output for the v3 JSON/Markdown before and after reports,
patch, structured facts and functional-test evidence.