T09 · Insecure Skill Coding Practices
Note
- Location
- handler.mjs:185
- Finding
- Unescaped User-Controlled Project Name in Markdown Output<![CDATA[ ## Vulnerability Details **File Location**: `handler.mjs:185-188` **Vulnerability Type**: Markdown injection through unescaped user input **Risk Level**: Low ```javascript function toMarkdown(story) { const lines = []; lines.push('# ' + story.title); lines.push(''); ``` The value of `story.title` originates from the request-controlled `projectName` field: ```javascript title: request.projectName || 'Our Family Story', ``` Equivalent unsafe Markdown construction also exists in `handler.ts`, and other request-controlled values such as event titles, descriptions, speaker names, and conversation content are inserted into generated Markdown without escaping. ### Technical Analysis The Markdown generator constructs output through direct string concatenation. An attacker can supply Markdown control characters or embedded HTML in `projectName`, causing the value to escape the intended heading and introduce additional links, images, headings, or raw HTML. For example, a malicious project name could contain line breaks followed by an external image reference. The Skill itself does not make a network request, but a downstream Markdown renderer may interpret the injected content and retrieve the external resource. The practical risk depends on the consuming renderer. Renderers that permit raw HTML or automatically load remote images create a greater risk than renderers that sanitize HTML and proxy or disable external resources. ### Attack Path 1. An attacker submits a story-generation request with a crafted `projectName`. 2. `generateStory()` copies that value into `story.title`. 3. `toMarkdown()` concatenates the title directly after a Markdown heading marker without escaping it. 4. The returned `outputContent` contains attacker-controlled Markdown or HTML. 5. A user or downstream application renders the generated Markdown. 6. The injected content is interpreted. Depending on renderer policy, it may display deceptive links or trigger requests fo ...[truncated 802 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Escape Markdown metacharacters in every request-controlled value before inserting it into Markdown, including project names, speaker names, titles, descriptions, and conversation content. 2. Strip or encode line breaks where a field is expected to remain on one heading or list-item line. 3. Disable raw HTML in the downstream Markdown renderer. 4. Sanitize generated links and images with an allowlist-based policy. 5. Disable external image loading or route images through a privacy-preserving proxy. 6. Prefer a structured Markdown abstract syntax tree or a well-maintained renderer over manual string concatenation. 7. Add tests using payloads containing headings, links, images, raw HTML, and multiline input. 8. Apply the same correction to the duplicate Markdown-generation implementation in `handler.ts`. ]]>
