T09 · Insecure Skill Coding Practices
- Location
scripts/render_preview.js:94- Finding
Executable JavaScript Injection in Generated Preview Documents
- Content
View full analysis
const MOVIE = ${JSON.stringify(movie)}; const TIMELINE = ${JSON.stringify(timeline)}; const STAGE_WIDTH = ${PREVIEW_WIDTH}; const STAGE_HEIGHT = ${PREVIEW_HEIGHT}; const DEFAULT_FONT_DISPLAY = ${JSON.stringify(theme.fontDisplay)}; const DEFAULT_FONT_BODY = ${JSON.stringify(theme.fontBody)}; ``` The generated document is subsequently loaded and executed by Playwright: ```javascript writeText(previewPath, buildPreviewHtml(movie, moviePath)); const browser = await chromium.launch({ headless: true }); const page = await browser.newPage({ viewport: { width: 1440, height: 980 }, deviceScaleFactor: 1 }); await page.goto(pathToFileURL(previewPath).href); await page.waitForFunction(() => window.__MOVIE_READY === true); ``` ### Technical Analysis The movie model and timeline are serialized directly into an executable inline `` sequence, which the HTML parser interprets as the end of the enclosing script regardless of its JavaScript string context. For example, a movie text field containing a payload structurally equivalent to: ```html ``` can terminate the intended script and introduce a new executable script element. The movie schema validates field types but does not sanitize this HTML parser boundary. The issue affects both manually opened `preview.html` files and the automated export path in `scripts/export_video.js`, where Playwright navigates to the generated local HTML file and executes its scripts. ### Attack Path 1. An attack ...[truncated 1294 chars]- Remediation
View remediation
` as `\u003e` - `&` as `\u0026` - U+2028 as `\u2028` - U+2029 as `\u2029` 3. Prefer placing the serialized model in a non-executable element: ```html ``` Then parse it with: ```javascript const MOVIE = JSON.parse(document.getElementById("movie-data").textContent); ``` The JSON must still escape `<` to prevent an injected closing `` sequence. 4. Add a restrictive Content Security Policy that blocks unexpected script and network execution. Where practical, move preview logic into a fixed external script and avoid `unsafe-inline`. 5. Add regression tests using fields containing ``, HTML tags, quotes, U+2028, and U+2029. 6. Treat all movie content as untrusted even when generated through an Agent workflow. ]]>
