T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/generate_report.py:455
- Finding
- Unescaped Ranking Data Enables HTML and Script Injection in Generated Reports<![CDATA[ ## Vulnerability Details **File Location**: `scripts/generate_report.py`, lines 455–479, 584–612, 633–650, and 684–695 **Vulnerability Type**: HTML injection, script injection, and unsafe URL interpolation **Risk Level**: High ### Vulnerable Code ```python ROW_TEMPLATE_CAT = """ <tr> <td><span class="rank-badge {rank_class}">{rank}</span></td> <td><a href="{profile_url}" target="_blank" class="account-name" title="点击查看抖音主页">{account_name}</a></td> <td class="category">{category}</td> <td><span class="score">{score}</span></td> <td>{followers}</td> <td class="interaction">{new_fans}</td> <td class="interaction">{new_likes}</td> <td class="interaction">{new_comments}</td> <td class="interaction">{new_shares}</td> </tr>""" ROW_TEMPLATE = """ <tr> <td><span class="rank-badge {rank_class}">{rank}</span></td> <td><a href="{profile_url}" target="_blank" class="account-name" title="点击查看抖音主页">{account_name}</a></td> <td><span class="score">{score}</span></td> <td>{followers}</td> <td class="interaction">{new_fans}</td> <td class="interaction">{new_likes}</td> <td class="interaction">{new_comments}</td> <td class="interaction">{new_shares}</td> </tr>""" ``` ```python account_name = item.get('accountName', '') profile_url = item.get('profileUrl', '') # ... if is_all_category: account_category = item.get('category', '-') rows.append(ROW_TEMPLATE_CAT.format( rank_class=rank_class, rank=rank, account_name=account_name, profile_url=profile_url or '#', category=account_category, score=score, followers=followers, new_fans=new_fans, new_likes=new_likes, new_comments=new_comments, new_shares=new_shares, )) else: rows.append(ROW_TEMPLATE.format( rank_class=rank_class, rank=rank, account_name=account_name, profile_url=p ...[truncated 3680 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Escape every untrusted value according to its HTML context: ```python from html import escape safe_account_name = escape(str(account_name), quote=True) safe_category = escape(str(account_category), quote=True) ``` 2. Validate profile links using `urllib.parse.urlparse`. Permit only HTTPS URLs on an explicit host allowlist, such as `www.douyin.com`: ```python from urllib.parse import urlparse def safe_profile_url(value: str) -> str: try: parsed = urlparse(value) if parsed.scheme == "https" and parsed.hostname == "www.douyin.com": return escape(value, quote=True) except Exception: pass return "#" ``` 3. Reject `javascript:`, `data:`, `file:`, and other unexpected schemes. Host validation must occur after parsing rather than through prefix matching. 4. Prefer a template engine with auto-escaping enabled instead of assembling HTML through unrestricted `str.format()` calls. 5. Add a restrictive Content Security Policy, for example one that denies inline scripts and limits network connections to the minimum required origins. 6. Remove automatic report opening or place it behind an explicit `--open` option. Report generation should not render externally controlled content without user confirmation. 7. Add regression tests containing account names such as `<script>...</script>`, quotes, event handlers, and malformed URLs to confirm that they are rendered as text rather than executable markup. ]]>
