T09 · Insecure Skill Coding Practices
- Location
scripts/render_issue.mjs:27- Finding
Unrestricted Active Content and Network Access During HTML Rendering
- Content
View full analysis
Vulnerability Details
File Location:
scripts/render_issue.mjs, lines 27–30
Vulnerability Type: Browser-based active-content execution with unrestricted outbound requests
Risk Level: Mediumjavascript const browser = await chromium.launch({ headless: true }); const page = await browser.newPage({ viewport: { width: 794, height: 1123 }, deviceScaleFactor: 1 }); await page.goto('file://' + input, { waitUntil: 'networkidle' }); const pdfPath = path.join(outDir, `${base}.pdf`);Technical Analysis
The renderer opens a caller-selected local HTML file in Playwright Chromium with JavaScript enabled by default. It does not create a restricted browser context, intercept requests, enforce an outbound-domain allowlist, or reject active elements such as scripts and iframes.
Consequently, HTML supplied to the renderer can execute JavaScript and initiate requests to arbitrary external origins. Remote stylesheets, images, fonts, scripts, frames, and other resources can also be loaded automatically. This network capability is not necessary for rendering a self-contained local document and therefore exceeds least privilege.
Chromium's browser sandbox and same-origin policy reduce direct host-file access, so this does not by itself establish arbitrary host compromise or access to unrelated local files. Nevertheless, malicious HTML can transmit information already embedded in or exposed to the rendered document, contact tracking endpoints, consume network or processing resources, and manipulate the generated PDF and screenshots at render time.
Attack Path
- An attacker-controlled article, template, imported file, or generated issue introduces a script or remote resource into an issue HTML file.
- The user or agent invokes
scripts/render_issue.mjswith that file as the input. - Playwright starts Chromium and navigates to the local HTML document.
- Embedded JavaScript executes, or the browser automatica ...[truncated 978 chars]
- Remediation
View remediation
Remediation Suggestions
- Create an isolated browser context with JavaScript disabled by default:
javascript const context = await browser.newContext({ javaScriptEnabled: false }); const page = await context.newPage(); - Intercept every request and permit only resources required for local rendering, such as approved
file:anddata:URLs:javascript await page.route('**/*', async route => { const url = new URL(route.request().url()); if (url.protocol === 'file:' || url.protocol === 'data:') { await route.continue(); } else { await route.abort(); } }); - Sanitize HTML before rendering. Reject or remove scripts, iframes, event-handler attributes, form submissions, and remote resource URLs.
- Make network-enabled rendering an explicit opt-in and require a user-approved host allowlist.
- Prefer self-contained documents with local CSS, embedded fonts, and validated local images.
- Apply rendering timeouts and resource limits to reduce denial-of-service risk.
- Document that only trusted or sanitized HTML may be passed to the renderer.
- Create an isolated browser context with JavaScript disabled by default:
