T09 · Insecure Skill Coding Practices
- Location
scripts/generate_hot_html.py:34- Finding
Stored HTML and JavaScript Injection Through Unescaped Article Data
- Content
View full analysis
Vulnerability Details
File Location:
scripts/generate_hot_html.py, lines 34-77
Vulnerability Type: Stored cross-site scripting and unsafe URL injection
Risk Level: HighVulnerable Code
python def get_article_html(article: dict, rank: int, is_top: bool = False) -> str: """生成单篇文章的HTML""" try: title = article.get("title", "未知标题") url = article.get("oriUrl", "#") account = article.get("userName", article.get("accountId", "未知账号")) account_id = article.get("accountId", "") reads = article.get("clicksCount", "0") # 处理日期 public_time = article.get("publicTime", "") if public_time: try: date = str(public_time)[:10] except: date = "" else: date = "" # 生成公众号名片链接 if account_id: account_url = f"https://open.weixin.qq.com/qr/code?username={account_id}" else: account_url = "#" top_class = " top-item" if is_top else "" rank_display = get_rank_display(rank) top_rank_class = " top" if is_top else "" return f''' <li class="article-item{top_class}"> <div class="article-body"> <div class="article-rank{top_rank_class}">{rank_display}</div> <div class="article-content"> <a href="{url}" target="_blank" class="article-title">{title}</a> <div class="article-info"> <span class="info-item"><a href="{account_url}" target="_blank" class="info-source-link"><span class="info-source-icon">👤</span>{account}</a></span> <span class="info-item"><span class="info-stat">📖 阅读 <span class="info-stat-value">{reads}</span></span></s ...[truncated 2847 chars]- Remediation
View remediation
Remediation Suggestions
- Escape every text value with
html.escape(value, quote=True)before inserting it into HTML. - Perform separate, contextual handling for text nodes, HTML attributes, and JavaScript strings. Do not rely on one generic escaping operation for all contexts.
- Validate link schemes using
urllib.parse.urlparseand allow onlyhttps, optionally with an explicit hostname allowlist such asmp.weixin.qq.com. - Reject
javascript:,data:,file:, protocol-relative, and malformed URLs. - Encode
accountIdas a URL query component withurllib.parse.quote. - Avoid interpolating
keywordinto JavaScript. Serialize it usingjson.dumpsor generate the filename entirely from sanitized characters. - Add a restrictive Content Security Policy, for example prohibiting inline scripts and limiting
connect-srcand navigation targets. - Add automated tests containing quotes, angle brackets, event handlers,
javascript:URLs, and closingscripttags. - Consider generating the page with a template engine that enables HTML auto-escaping by default.
- Escape every text value with
