T09 · Insecure Skill Coding Practices
- Location
faq_publish.py:47- Finding
Stored Cross-Site Scripting in Generated HTML FAQ Pages
- Content
View full analysis
{title} ``` Categories are inserted into both HTML text and attribute contexts without escaping: ```python for category in sorted(by_category.keys()): cat_id = category.lower().replace(" ", "-") html += f'- {category}
\n' ``` FAQ fields and related-question data are also inserted directly into the generated document: ```python for category in sorted(by_category.keys()): cat_id = category.lower().replace(" ", "-") html += f'\n' html += f'{category}
\n' for entry in by_category[category]: active_class = "" if collapsible else "active" html += f'\n' html += '\n' html += f' {entry.question}\n' if entry.priority in ["critical", "high"]: html += f' {entry.priority.upper()}\n' if collapsible: html += ' ▼\n' html += '\n' html += '\n' html += f'{entry.answer}
\n' if entry.tags or entry.related: ...[truncated 3608 chars]- Remediation
View remediation
str: value = re.sub(r'[^A-Za-z0-9_-]', '-', value) value = re.sub(r'-+', '-', value).strip('-') return value or "section" ``` 4. Validate database fields when loading and importing them. In particular: - Require strings for questions, answers, categories, priorities, products, IDs, and tags. - Restrict priorities to `low`, `normal`, `high`, or `critical`. - Restrict identifiers used in attributes to a safe character set. - Reject malformed nested structures. 5. Treat FAQ answers as plain text by default. If rich HTML is an intended feature, process it through a maintained allowlist-based HTML sanitizer and prohibit scripts, event-handler attributes, unsafe URLs, embedded frames, and active SVG content. 6. Add a restrictive Content Security Policy to generated pages as defense in depth. For example, move the existing inline JavaScript to a separate static file and use a policy similar to: ```html ``` Output encoding remains mandatory because a CSP can be weakened or omitted during deployment. 7. Add regression tests for every output context, including: - `` - `` - `" onmouseover="alert(1)` - Categories containi ...[truncated 249 chars]
