T09 · Insecure Skill Coding Practices
Warning
- Location
- skill.js:161
- Finding
- Stored Cross-Site Scripting Through Unescaped HTML Generation## Vulnerability Details **File Location**: `skill.js`, lines 161–165 **Vulnerability Type**: Unescaped user-controlled data in generated HTML **Risk Level**: Medium ### Vulnerable Code ```js <title>${input.appName}</title> </head> <body> <h1>${input.appName}</h1> <p>Privacy Policy and Terms placeholder.</p> <p>Contact: ${input.contactEmail}</p> ``` ### Technical Analysis The active handler directly interpolates the user-controlled `input.appName` and `input.contactEmail` values into an HTML document. The input schema only requires these properties to be strings and does not enforce HTML-safe content. A `sanitize()` function exists elsewhere in the file, but the active handler does not use it. Consequently, an attacker who can control the Skill parameters can terminate the surrounding HTML element and inject arbitrary HTML or JavaScript. The malicious markup is then persisted in `dist/index.html`, making this a stored cross-site scripting vulnerability if the generated site is published. For example, an `appName` containing the following value would break out of the title element and introduce executable script content: ```html </title><script>/* attacker-controlled JavaScript */</script> ``` ### Attack Path 1. An attacker gains the ability to submit or influence parameters passed to the Skill. 2. The attacker supplies malicious HTML or JavaScript in `appName` or `contactEmail`. 3. The handler interpolates that value into the `html` template without contextual output encoding. 4. The handler writes the resulting content to `dist/index.html`. 5. The generated directory is deployed to Cloudflare Pages or another web host. 6. A victim visits the deployed page. 7. The victim's browser interprets the injected markup and executes attacker-controlled JavaScript in the security context of the deployed origin. ### Impact Assessment Successful exploitation permits arbitrary client-side code execution for visitors to the generated website. Depending on the data ...[truncated 662 chars]
- Remediation
- ## Remediation Suggestions 1. Apply HTML output encoding to every user-controlled value before inserting it into HTML. At minimum, encode `&`, `<`, `>`, `"`, and `'`. 2. Reuse and strengthen the existing `sanitize()` helper: ```js function sanitize(value) { return String(value) .replace(/&/g, "&") .replace(/</g, "<") .replace(/>/g, ">") .replace(/"/g, """) .replace(/'/g, "'"); } ``` 3. Encode values in the active template: ```js const safeAppName = sanitize(input.appName); const safeContactEmail = sanitize(input.contactEmail); const html = ` <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>${safeAppName}</title> </head> <body> <h1>${safeAppName}</h1> <p>Privacy Policy and Terms placeholder.</p> <p>Contact: ${safeContactEmail}</p> </body> </html> `; ``` 4. Validate `contactEmail` against an appropriate email format and impose reasonable length limits on every input. 5. Prefer a well-maintained HTML templating system with automatic contextual escaping when the project grows beyond simple static templates. 6. Add automated tests using payloads that contain element terminators, event handlers, quotation marks, ampersands, and script elements. Verify that generated output displays these inputs as text rather than executable markup. 7. Consider deploying a restrictive Content Security Policy as defense in depth. Output encoding remains mandatory because a policy alone does not eliminate HTML injection.
