T09 · Insecure Skill Coding Practices
- Location
scripts/convert-ap-report.mjs:142- Finding
Shell Command Injection Through the PDF Output Path
- Content
View full analysis
&1 || true`, { stdio: 'pipe', timeout: 30000 }); const generated = tmpHtml.replace(/\.html$/, '.pdf'); if (existsSync(generated)) { renameSync(generated, resolve(outputPdf)); console.log('OK'); } else { // Fallback: try node with puppeteer directly console.log('Fallback: trying direct puppeteer render...'); execSync(`node -e " const puppeteer = require('puppeteer'); (async () => { const browser = await puppeteer.launch({headless:'new'}); const page = await browser.newPage(); await page.goto('file://${tmpHtml}', {waitUntil:'networkidle0'}); await page.pdf({path:'${resolve(outputPdf)}', format:'A4', margin:{top:'18mm',bottom:'18mm',left:'18mm',right:'18mm'}, printBackground:true}); await browser.close(); console.log('OK'); })(); "`, { stdio: 'inherit', timeout: 30000 }); } } catch (e) { ``` ### Technical Analysis The script accepts `outputPdf` from `process.argv` and derives `tmpHtml` from it. These path values are interpolated directly into command strings passed to `execSync`, which invokes a system shell. Placing `tmpHtml` inside double quotes does not make it safe. POSIX shells still process command substitution with `$()` and backticks inside double-quoted strings. The fallback is additionally vulnerable because the paths are embedded in JavaScript source that is itself embedded in a shell command. No shell escaping, JavaScript string escaping, path allowlisting, or output-directory restriction is applied. Consequently, a caller who can influence the output filename can cause the shell to interpret attacker-supplied synta ...[truncated 1296 chars]- Remediation
View remediation
