T09 · Insecure Skill Coding Practices
- Location
scripts/generate_postmortem.py:383- Finding
Stored HTML and JavaScript Injection in Generated Reports
- Content
View full analysis
\1', html, flags=re.MULTILINE) html = re.sub(r'^## (.+)$', r'\1
', html, flags=re.MULTILINE) html = re.sub(r'^### (.+)$', r'\1
', html, flags=re.MULTILINE) # Bold html = re.sub(r'\*\*(.+?)\*\*', r'\1', html) # Italic html = re.sub(r'_(.+?)_', r'\1', html) # Code html = re.sub(r'`(.+?)`', r'\1', html) # Lists html = re.sub(r'^- (.+)$', r'- \1
', html, flags=re.MULTILINE) # Tables (simple conversion) def convert_table(match): lines = match.group(0).strip().split('\n') rows = [] for i, line in enumerate(lines): if '---' in line: continue cells = [c.strip() for c in line.strip('|').split('|')] tag = 'th' if i == 0 else 'td' row = ''.join(f'<{tag}>{c}' for c in cells) rows.append(f'{row}') return f'{"".join(rows)}' html = re.sub(r'(\|.+\|(?:\n\|.+\|)*)', convert_table, html) # Paragraphs (lines not already wrapped) lines = html.split('\n') processed = [] for line in lines: if line.strip() and not line.strip().startswith('<') and not line.strip().startswith('*'): processed.append(f'
{line}
') else: processed.append(line) html = '\n'.join(processed) return f"""- Remediation
View remediation
`, ``, `<object>`, `<embed>`, and similar active elements. - Event-handler attributes such as `onclick`, `onerror`, and `onload`. - Dangerous URL schemes such as `javascript:` and unsafe `data:` URLs. - Unexpected SVG or MathML elements and attributes. 4. Construct the document title from an escaped value: ```python import html safe_title = html.escape(str(title), quote=True) ``` 5. Treat log messages as plain text rather than markup, because logs commonly contain attacker-controlled request data. 6. Consider adding a restrictive Content Security Policy to generated reports as defense in depth: ```html <meta http-equiv="Content-Security-Policy" content="default-src 'none'; style-src 'unsafe-inline'; img-src data:"> ``` This should supplement output encoding and sanitization, not replace them. 7. Add regression tests covering payloads in every input channel, including: - Incident titles and summaries. - Timeline event text. - Action-item table cells. - Parsed log messages. - Closing-tag payloads such as `</title>`. - Event handlers and dangerous URL schemes. The tests should verify that payloads appear only as encoded text and cannot create executable DOM elements or attributes. ]]>
