T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/padel_americano.py:747
- Finding
- HTML Injection During PDF Export with Chromium Sandbox Disabled<![CDATA[ ## Vulnerability Details **File Location**: `scripts/padel_americano.py:747-750`, `scripts/padel_americano.py:769`, and `scripts/padel_americano.py:780-797` **Vulnerability Type**: HTML injection through unvalidated tournament state combined with unsafe browser execution **Risk Level**: High ### Vulnerable Code ```python for rnd in state["rounds"]: for m in rnd["matches"]: score = "-" if not m.get("score") else f"{m['score'][0]}-{m['score'][1]}" schedule_rows.append( f"<tr><td>{rnd['round']}</td><td>{m['court']}</td><td>{esc(' / '.join(m['team1']))}</td>" f"<td>{esc(' / '.join(m['team2']))}</td><td>{score}</td></tr>" ) ``` ```python <div class='meta'>Players: {esc(', '.join(state['players']))} | Courts: {state['courts']} | Rounds: {state['round_count'] or len(state['rounds'])} | Points/game: {state['points_per_game']}</div> ``` ```python def cmd_export_pdf(args): state = load_state(args.state) out = Path(args.out) out.parent.mkdir(parents=True, exist_ok=True) html_path = out.with_suffix(".html") html_path.write_text(html_report(state), encoding="utf-8") chrome = shutil.which("google-chrome") or shutil.which("chromium") or shutil.which("chromium-browser") if not chrome: print(f"No Chrome/Chromium found. Wrote HTML instead: {html_path}") return subprocess.run([ chrome, "--headless", "--disable-gpu", "--no-sandbox", f"--print-to-pdf={out}", html_path.as_uri(), ], check=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) print(f"Exported {out}") ``` ### Technical Analysis The application loads tournament state directly from a JSON file and does not validate it against a strict schema. Although tournament and player names are escaped in the HTML report, several other JSON-derived fields are inserted into HTML without escaping, including: - Round identifiers - Court identifiers - Score ele ...[truncated 2719 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. **Validate state files against a strict schema before use** - Require round, court, court-count, round-count, points, and score values to be integers. - Reject booleans, strings, objects, and arrays where numeric values are expected. - Enforce sensible minimum and maximum values. - Validate the structure and element types of teams, matches, rounds, and scores. 2. **Escape every value inserted into HTML** - Apply `html.escape(str(value))` to all JSON-derived values, including fields expected to be numeric. - Use a template engine with automatic HTML escaping rather than manually constructing HTML with f-strings. Example: ```python f"<tr><td>{esc(rnd['round'])}</td><td>{esc(m['court'])}</td>" ``` The score should also be escaped after formatting: ```python score = "-" if not m.get("score") else f"{m['score'][0]}-{m['score'][1]}" safe_score = esc(score) ``` 3. **Remove `--no-sandbox`** - Run Chromium with its normal sandbox enabled. - If the deployment environment cannot support the Chromium sandbox, perform conversion inside a separately isolated container or restricted worker account. - Limit the worker's filesystem access and disable network access when it is not required. 4. **Restrict browser capabilities** - Disable JavaScript for report rendering where supported. - Block external network requests and external resource loading. - Use a restrictive Content Security Policy, such as one that permits only inline styles required by the report and denies scripts, frames, objects, and network connections. 5. **Handle generated HTML securely** - Create intermediate files with restrictive permissions. - Prefer a secure temporary directory. - Remove the intermediate HTML after successful PDF creation unless the user explicitly requests an HTML copy. - Avoid overwriting unrelated files through ambiguous output paths. 6. **Fail safely** - Report Chr ...[truncated 168 chars]
