T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/generate_daily.py:75
- Finding
- Unescaped report data executes in a local-file-enabled Chromium context<![CDATA[ ## Vulnerability Details **File Locations**: - `scripts/generate_daily.py:75-129` - `scripts/generate_daily.py:154-198` - `scripts/generate_daily.py:225-228` **Vulnerability Type**: Stored HTML and JavaScript injection during automated PDF rendering **Risk Level**: High ### Vulnerable Code The report body directly interpolates dynamic values into HTML: ```python body = f"""<!DOCTYPE html> <html lang="zh-CN"><head> <meta charset="UTF-8"> <title>涨停板龙虎榜深度研判报告-{date}</title> <style> body{{font-family:"PingFang SC","Microsoft YaHei",sans-serif;max-width:980px;margin:24px auto;color:#12181F;line-height:1.65}} h1{{color:#002B5C;border-bottom:3px solid #C5A572;padding-bottom:8px}} h2{{color:#002B5C;margin-top:32px;border-left:4px solid #C5A572;padding-left:10px}} pre{{background:#F6F8FA;padding:12px;border-left:3px solid #C5A572;overflow:auto}} table{{border-collapse:collapse;width:100%;margin:12px 0;font-size:13px}} th,td{{border:1px solid #DDE3EA;padding:6px 10px;text-align:left}} th{{background:#0A3D6E;color:#fff;font-weight:600}} tr:nth-child(even){{background:#F6F8FA}} .ok{{color:#1E8449;font-weight:600}} .no{{color:#C1272D;font-weight:600}} .callout{{background:#FDF3F3;border-left:4px solid #C1272D;padding:10px 14px;margin:12px 0}} .muted{{color:#6B7785;font-size:12px}} </style> </head><body> <h1>涨停板龙虎榜深度研判报告 · {date}</h1> <p class="muted">口径版本 <b>{C.CALIBER_VERSION}</b> · 框架:L1→L2→L2.5→L3 四层漏斗 + 财富密码选股策略</p> <h2>0. 本报告口径(v2 永久生效)</h2> {caliber_html} <h2>1. 四层漏斗执行结果</h2> {funnel_html} <h2>2. 评分管道 · 风控信号表</h2> {rows_html} <h2>3. α 账本</h2> <p class="muted">阶段 <b>{result['ledger']['stage']}</b> · α_max <b>{result['ledger']['alpha_budget']:.1%}</b> · 已用 <b>{result['ledger']['used_pct']:.2%}</b> · 剩余 <b>{result['ledger']['remaining']:,.0f}</b> 元 · 持仓 <b>{result['ledger']['positions']}</b> 笔</p> <h2>4. 盘前 6 项检查</h2> {PB.render_checklist_md().replace("<table>", '<table><thead>').replace("</table>", "</thead></table>").replace("<tr>", "<tr><th>#</th><th>检 ...[truncated 4235 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. **Escape every untrusted value according to its output context.** - Apply `html.escape(str(value), quote=True)` to stock names, codes, notes, actions, industry names, rejection reasons, dates, and all other dynamic text. - Do not escape complete, trusted HTML fragments and untrusted values using the same helper. 2. **Use an auto-escaping template engine.** - Replace manual f-string HTML construction with Jinja2 or an equivalent engine configured with auto-escaping. - Require explicit marking for the small number of trusted HTML fragments. 3. **Validate structured input.** - Restrict the date to a strict `YYYY-MM-DD` format. - Validate stock codes, actions, stages, and numeric values against allowlists or schemas. - Reject unexpected object types and unknown fields with a JSON Schema or typed validation model. 4. **Remove unnecessary Chromium privileges.** - Remove `--allow-file-access-from-files` from both `scripts/generate_daily.py` and `templates/make_pdf.py`. - If local assets are required, use a narrowly scoped local HTTP server or embed trusted assets directly. 5. **Disable network access during rendering.** - Use Playwright route interception to abort `http://`, `https://`, WebSocket, and other unnecessary requests. - Permit only the exact local resources needed for report generation. 6. **Apply a restrictive Content Security Policy.** - Disallow inline scripts and event handlers. - Use a nonce or hash for any required trusted script. - Set `default-src 'none'`, then explicitly permit only necessary resources. 7. **Add security regression tests.** - Test names and notes containing script elements, event handlers, malformed tags, quotes, and URL-bearing elements. - Confirm that payloads appear as visible text and do not execute during PDF generation. ]]>
