T09 · Insecure Skill Coding Practices
- Location
scripts/report_builder.py:69- Finding
Stored HTML and JavaScript Injection in Generated Reports
- Content
View full analysis
str: """构建项目概览卡片""" items = [ ("项目名称", info.get("project_name", "未提取")), ("项目编号", info.get("project_number", "未提取")), ("预算金额", info.get("budget", "未提取")), ("招标人", info.get("bidder", "未提取")), ("投标截止", info.get("bid_deadline", "未提取")), ] cards = "".join( f'{label}{value}' for label, value in items ) return f'' def _build_requirements_table(requirements: list[dict]) -> str: """构建需求清单表格""" if not requirements: return '项目概览
{cards}' rows = "" for req in requirements: mandatory_icon = "★" if req.get("mandatory") else "" risk_class = f"risk-{req.get('risk_level', 'low')}" rows += ...[truncated 2425 chars]需求清单
暂未提取需求
- Remediation
View remediation
str: return escape(str(value if value is not None else ""), quote=True) ``` 2. Use the encoder for project metadata, requirements, review content, revision data, version metadata, and risks. 3. Replace direct string construction with a template engine such as Jinja2 configured with automatic escaping: ```python from jinja2 import Environment, FileSystemLoader, select_autoescape env = Environment( loader=FileSystemLoader(template_directory), autoescape=select_autoescape(["html", "xml"]), ) ``` 4. Do not allow arbitrary values in HTML classes or style attributes. Map risk levels through a strict allowlist: ```python allowed_risks = {"low", "medium", "high", "critical"} risk_level = req.get("risk_level", "low") if risk_level not in allowed_risks: risk_level = "low" ``` 5. Validate numeric fields before using them in CSS properties such as progress-bar widths, and clamp percentages to the range `0` through `100`. 6. Add a restrictive Content Security Policy. Prefer moving the inline script into a local static file and disallowing inline event handlers. 7. Add automated tests using payloads in every output field, including closing tags, quoted attribute payloads, SVG payloads, and malformed CSS values. ]]>
