T09 · Insecure Skill Coding Practices
- Location
scripts/shopify-markets-localization-auditor.mjs:1688- Finding
Executable Script Injection in Generated HTML Reports
- Content
View full analysis
const report = {{REPORT_DATA_JSON}}; const isZh = String(report.lang || "").toLowerCase().startsWith("zh"); ``` The report command accepts its source data from a caller-controlled JSON file: ```javascript async function cmdReport(args) { if (!args.input) throw new Error("--input is required"); if (!args.output) throw new Error("--output is required"); const audit = JSON.parse(await readFile(args.input, "utf8")); audit.reportLang = resolveReportLang(args.lang, audit.reportLang); await renderReport(audit, args.output); console.log(JSON.stringify({ ok: true, output: args.output }, null, 2)); } ``` ### Technical Analysis `JSON.stringify()` produces valid JavaScript data syntax, but it does not make data safe for direct embedding in an HTML ``. A string in the report model containing a payload such as: ```html ``` terminates the original script element before JavaScr ...[truncated 2096 chars]- Remediation
View remediation
{{REPORT_DATA_JSON}} ``` 3. Before embedding JSON in HTML, escape characters that are significant to the HTML parser: ```javascript function serializeForHtml(value) { return JSON.stringify(value) .replace(/&/g, "\\u0026") .replace(//g, "\\u003e") .replace(/\u2028/g, "\\u2028") .replace(/\u2029/g, "\\u2029"); } ``` 4. Use the safe serializer for `{{REPORT_DATA_JSON}}`. 5. Continue applying contextual HTML escaping to every value used in `innerHTML`. 6. Add a restrictive Content Security Policy. Prefer moving report-rendering JavaScript to a static local file so inline scripts can be disabled. 7. Add regression tests using values containing: - `` - HTML tags and event handlers - Ampersands and encoded entities - U+2028 and U+2029 8. Treat both user-supplied audit files and Shopify-provided strings as untrusted input. ]]>
