T09 · Insecure Skill Coding Practices
- Location
scripts/core/report_core.py:64- Finding
Unescaped Report Data Enables Stored HTML and JavaScript Injection
- Content
View full analysis
Vulnerability Details
File Location:
scripts/core/report_core.py, lines 64–95
Vulnerability Type: Stored HTML injection / cross-site scripting in generated reports
Risk Level: MediumVulnerable Code
python for r in results: icon = "✅" if r["severity"] == "通过" else "⚠️" if r["severity"] in ("提示", "警告") else "❌" rows += f"""<tr> <td>{icon}</td> <td>{r['check_id']}</td> <td>{r['description']}</td> <td>{r['severity']}</td> <td>{r.get('recommendation','')}</td> </tr>\n""" return f"""<!DOCTYPE html> <html lang="zh-CN"> <head><meta charset="utf-8"> <title>{data.get('tool','合规检查报告')}</title> <style> body {{ font-family: -apple-system, sans-serif; max-width: 960px; margin: 2rem auto; padding: 0 1rem; }} h1 {{ color: #1a1a2e; }} .summary {{ display: flex; gap: 1rem; margin: 1rem 0; }} .card {{ padding: 1rem 1.5rem; border-radius: 8px; background: #f5f5f5; text-align: center; }} .card.pass {{ background: #d4edda; }} .card.warn {{ background: #fff3cd; }} .card.fail {{ background: #f8d7da; }} table {{ width: 100%; border-collapse: collapse; margin-top: 1rem; }} th, td {{ padding: 0.5rem; text-align: left; border-bottom: 1px solid #ddd; }} th {{ background: #e9ecef; }} </style> </head><body> <h1>{data.get('tool','')}</h1> <p><strong>法规:</strong>{data.get('regulation','')} | <strong>时间:</strong>{data.get('check_time','')[:19]}</p>Technical Analysis
ReportGenerator.to_html()constructs an HTML document through direct string interpolation. Dynamic report fields—includingtool,regulation,check_time,check_id,description,severity, andrecommendation—are inserted without HTML encoding or sanitization.If any of these fields contains attacker-controlled markup, the generated report preserves it as active HTML. For example, a description containing:
html <img src=x onerror="alert(document.domain)">would be emitted unchanged and execute when the generated report is ...[truncated 1653 chars]
- Remediation
View remediation
Remediation Suggestions
- Escape every dynamic value before inserting it into HTML:
python from html import escape def html_value(value): return escape(str(value), quote=True)Apply this helper to all report-derived fields, including
tool,regulation,check_time,check_id,description,severity, andrecommendation.- Prefer an HTML template engine configured with automatic escaping rather than constructing markup with f-strings. If Jinja2 is used, create the environment with autoescaping enabled:
python from jinja2 import Environment, select_autoescape env = Environment( autoescape=select_autoescape(enabled_extensions=("html", "xml")) )-
Do not mark report values as safe HTML unless they have passed a strict allowlist sanitizer.
-
Add regression tests using payloads such as:
html <script>alert(1)</script> <img src=x onerror=alert(1)> "><svg onload=alert(1)>Tests should verify that the generated output contains encoded text such as
<script>, not executable markup.- If generated reports may be hosted, add a restrictive Content Security Policy as defense in depth. Escaping remains mandatory.
