T09 · Insecure Skill Coding Practices
- Location
scripts/report_generator.py:342- Finding
Stored HTML and JavaScript Injection in Generated Reports
- Content
View full analysis
Agent 开发可行性决策报告 - {name} {css}🤖 {name}
{direction}``` Representative unescaped detail-field interpolation: ```python tech_detail = safe_get(tech, "detail", "暂无详细数据") html += f"""🧠 一、技术选型分析
{make_score_bar(tech_score)}{tech_detail}
""" ``` The generated content is then persisted as an executable HTML document: ```python html = generate_report(data) Path(args.output).write_text(html, encoding="utf-8") ``` Similar direct interpolation affects product names, directions, competitor information, market data, technical details, risk descriptions, table cells, and other report fields throughout lines 398-655. ### Technical Analysis The `safe_get()` helper only retrieves values from dictionaries: ```python def safe_get(d, key, default=""): """Safely get dict value.""" if isinstance(d, dict): return d.get(key, default) return default ``` It does not perform HTML escaping, attribute encoding, content validation, or sanitization. Consequently, user-controlled or externally sourced strings are inserted directly into HTML text, title, table, and other markup contexts. An attacker can supply a value containing HTML that closes the surrounding element and introduces executable markup. For exa ...[truncated 2180 chars]- Remediation
View remediation
str: return escape(str(value), quote=True) ``` Use it for every externally supplied value: ```python safe_name = html_text(name) safe_direction = html_text(direction) safe_tech_detail = html_text(tech_detail) html = f""" Agent Development Feasibility Report - {safe_name}{safe_name}
{safe_direction}{safe_tech_detail}
""" ``` 2. **Prefer an auto-escaping template engine.** Move the large HTML template to Jinja2 or an equivalent engine configured with automatic HTML escaping: ```python from jinja2 import Environment, FileSystemLoader, select_autoescape env = Environment( loader=FileSystemLoader("templates"), autoescape=select_autoescape(["html", "xml"]), ) template = env.get_template("report.html") html = template.render(data=data, score_result=score_result) ``` Do not mark externally sourced values as safe unless they have passed a strict allowlist sanitizer. 3. **Treat WebSearch and WebFetch content as untrusted.** Never insert retrieved page content into the report as raw HTML. Convert it to plain text and escape it. If limited formatting is required, sanitize it with a maintained allowlist-based sanitizer that rejects scripts, event-handler attributes, dangerous URLs, embedded objects, frames, and active SVG content. 4. **Validate field types and ranges.** Require strings for descriptive fields and numeric values for scores. Reject nested objects or unexpected types rather than relying on implicit string conversion. Constrain scores to the documented range of 0-100. 5. **Preserve safe JavaScript serialization.** Continue using `json.dumps()` for JavaScript data rather than str ...[truncated 1055 chars]
