T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/render_x_longshot.js:126
- Finding
- Arbitrary Python Code Execution Through Unsafely Interpolated Output Paths## Vulnerability Details **File Location**: `scripts/render_x_longshot.js`, lines 126-150 **Vulnerability Type**: Python source-code injection **Risk Level**: High ### Vulnerable Code ```javascript const py = ` from PIL import Image raw = Image.open(r'''${rawPng}''').convert('RGB') top = Image.open(r'''${topPng}''').convert('RGB') out = raw.copy() crop_h = min(${args.topFixPx}, top.size[1], out.size[1]) out.paste(top.crop((0,0,top.size[0],crop_h)), (0,0)) out.save(r'''${args.outPng}''') print(r'''${args.outPng}''') `; runPython(py); if (!args.noPdf) { const pyPdf = ` from PIL import Image img = Image.open(r'''${args.outPng}''').convert('RGB') img.save(r'''${args.outPdf}''', 'PDF', resolution=144.0) print(r'''${args.outPdf}''') `; runPython(pyPdf); } ``` The generated programs are executed by the following helper: ```javascript function runPython(code) { const r = spawnSync('python3', ['-c', code], { encoding: 'utf8' }); if (r.status !== 0) { throw new Error(r.stderr || r.stdout || 'python3 failed'); } return r.stdout.trim(); } ``` ### Technical Analysis The values supplied through `--out-png` and `--out-pdf` are interpolated directly into Python source code enclosed by raw triple-quoted string literals. They are then passed to `python3 -c`. Although `spawnSync` is invoked without a shell, this only prevents shell metacharacter expansion. It does not prevent injection into the Python program itself. A path containing a terminating `'''` sequence can close the intended string literal and append arbitrary Python statements. The PDF path is a direct exploitation point because the attacker can terminate the path passed to `img.save`, append a Python expression such as an `os` or `subprocess` invocation, and comment out the remaining generated source. The earlier image processing succeeds using a legitimate PNG path before the malicious PDF- ...[truncated 1591 chars]
- Remediation
- ## Remediation Suggestions Do not embed caller-controlled values in executable Python source. 1. Move the Pillow operations into a fixed Python helper script and pass all paths as ordinary command-line arguments: ```javascript spawnSync('python3', [ helperScript, '--raw', rawPng, '--top', topPng, '--output', args.outPng, '--top-fix-px', String(args.topFixPx) ]); ``` The helper should retrieve these values through `argparse` or `sys.argv`, where they remain data rather than Python syntax. 2. Alternatively, send a JSON object to a fixed Python program through standard input and parse it with `json.load(sys.stdin)`. 3. Validate and normalize output paths before use. Require a conservative filename policy and constrain resolved paths to an approved output directory. 4. Reject null bytes, control characters, newline characters, and unexpected path components. This validation should be defense in depth rather than the primary injection mitigation. 5. Add regression tests using filenames containing quotes, triple quotes, backslashes, newlines, Unicode characters, and Python metacharacters. Verify that these values are either safely handled as filenames or explicitly rejected and never interpreted as code.
