Back to skill

Security audit

AI Weekly Report

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly matches its AI weekly report purpose, but it needs review because deployment and scheduling paths use broad persistent credentials and one maintenance script can make published reports vulnerable to injected JavaScript.

Install only if you are comfortable with a skill that can fetch public news, generate HTML, optionally post to Feishu, deploy to hosting providers, and create a recurring OS scheduler task when explicitly run. Prefer short-lived or tightly scoped credentials, avoid storing GitHub PATs in .github_token where possible, use dry-run modes first, and do not publish reports modified by backfill_translations.py until its NEWS_DATA serialization is fixed.

Vulnerability Patterns
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (1)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/backfill_translations.py:62
Finding
Stored Cross-Site Scripting Through Unsafe NEWS_DATA Re-serialization## Vulnerability Details **File Location**: `scripts/backfill_translations.py`, lines 62–64 and 161–175 **Vulnerability Type**: Stored cross-site scripting caused by unsafe embedding of untrusted JSON in a JavaScript context **Risk Level**: High **Vulnerable code:** ```python def write_news_data(html: str, data: list[dict], m: re.Match) -> str: """Write NEWS_DATA back into the report.""" blob = json.dumps(data, ensure_ascii=False) return html[:m.start(1)] + blob + html[m.end(1):] ``` ```python new_html, n_cards = patch_signal_cards( write_news_data(html, data, m), data) if n_cards: print(f" 🏷️ Market signal cards updated: {n_cards}") if not gained and not n_cards: print(" ⏭️ No new translations; skipping write") continue if dry_run: print(f" 🏃 dry-run: would write {after['cn_summary']} summaries / " f"{after['cn_title']} titles / {n_cards} card annotations") else: p.write_text(new_html, encoding="utf-8") ``` ### Technical Analysis Reports store news records in a JavaScript variable named `NEWS_DATA`. These records may originate from automatically retrieved RSS feeds or externally supplied news JSON and therefore cross a third-party trust boundary. The main renderer accounts for this boundary by escaping `<`, `>`, and `&` before placing serialized JSON inside a script block. However, the translation backfill path parses the protected JSON with `json.loads()`, which converts sequences such as `\u003c` back into literal `<` characters. It then re-serializes the records using ordinary `json.dumps()` without script-context escaping. JSON string escaping alone does not protect an inline script block. HTML parsers recognize a literal `</script>` sequence even when it occurs inside a JavaScript string. Consequently, an attacker-controlled news field can terminate the containing script element and introduce a new executable element. The unsafe result i ...[truncated 1705 chars]
Remediation
## Remediation Suggestions 1. Replace plain `json.dumps()` with the same script-safe serialization routine used by `scripts/aiweekly/render.py`. 2. At minimum, escape HTML-significant characters after JSON serialization: ```python def script_safe_json(value) -> str: return ( json.dumps(value, ensure_ascii=False) .replace("<", "\\u003c") .replace(">", "\\u003e") .replace("&", "\\u0026") ) ``` 3. Use this function in `write_news_data()` before inserting the JSON into the inline script block. 4. Centralize embedded-JSON serialization in one shared helper so the generator and backfill paths cannot diverge. 5. Add regression tests containing payloads such as: ```html </script><script>alert(1)</script> ``` Verify that no raw `</script` appears inside the serialized `NEWS_DATA` value after backfilling. 6. Run the existing report validation logic after every backfill and fail closed if an embedded JSON variable contains a raw script terminator or if dangerous link schemes are introduced. 7. Consider embedding the data in a non-executable `<script type="application/json">` element while retaining the same escaping protections, then parse it with `JSON.parse(textContent)` in the browser.
Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
Findings (231)

Tainted flow: 'req' from os.environ.get (line 222, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Content
},
    )
    try:
        with urllib.request.urlopen(req, timeout=30) as resp:
            if resp.status in (200, 201, 204):
                return True
            print(f"⚠️ Pages 源切换返回 HTTP {resp.status}")
Confidence
90% confidence
Finding
A GitHub token from the environment is sent in an Authorization header to the GitHub API. While this is functionally intended, it is still an external transmission of a sensitive secret, and if the remote/repository context is wrong or the environment is compromised, the token could be used against an unintended repository or exposed through surrounding tooling/logging.

Credential Access

High
Category
Privilege Escalation
Content
2. 把 GitHub Pages **源**切到 `gh-pages / /root`(二选一):
   - **手动**:仓库 **Settings → Pages → Source** 选 **Deploy from a branch → `gh-pages` / `/root`** → Save。
   - **自动(方案 B,推荐)**:建一个 **Classic PAT**(Fine-grained 不被 Pages API 支持,会 403),再跑脚本:
     1. GitHub → 头像 → **Settings → Developer settings → Personal access tokens → Tokens (classic) → Generate new token**。
     2. 勾选 **`repo`**(含 `public_repo`)与 **`pages:write`**;设较长过期(如 1 年)。
     3. 生成后复制 token(只显示一次),在本机设环境变量并跑:
        ```bash
Confidence
96% confidence
Finding
The documentation instructs users to create a long-lived Classic Personal Access Token with broad `repo` and `pages:write` scopes, and elsewhere suggests storing a GitHub token in a local `.github_token` file. In an agent-skill context, encouraging broad, persistent credentials materially increases the blast radius if the workstation, repository directory, logs, or automation environment are compromised; an attacker could push code, alter Pages content, or access private repositories.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The declared description presents a full-featured AI news site generator with RSS ingestion, optional external data injection, triggers, and automation. The supplied code chunk does not implement any of that behavior; it is only a chart library file stub/comment. While a charting library could be a supporting asset for the described tool, this chunk by itself does not match the declared primary purpose or capabilities. Therefore this code chunk is mismatched relative to the description.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
声明描述的是一个完整的 AI 行业新闻周报/网站生成技能,核心能力应包括新闻采集、数据整合、页面生成与运维分发。而提供的代码仅包含 diagnostics.py,一个纯展示层的异常提示模块:基于规则匹配告警文本,生成用户友好的原因和处理建议,并打印提示信息。虽然该模块可能是整个项目的辅助组成部分,但就此代码片段本身而言,其主要行为与声明的主要用途明显不一致,且缺失声明中几乎所有核心功能。因此应判定为描述与代码行为不匹配。

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
声明描述的是一个“AI 行业新闻网站生成工具”,重点能力应是从 RSS 新闻源抓取新闻、生成单文件 HTML 新闻站、支持搜索筛选和暗色模式,并可由用户注入外部新闻 JSON。实际代码却完全聚焦于“模型排行榜”数据处理:从多个 leaderboard 源抓取模型榜单,按地区选择源,回退到本地缓存或国内快照,构建历史趋势,计算名次变化,生成选型说明,并同步模型档案。代码中没有体现新闻 RSS 抓取、新闻网站 HTML 生成、搜索/筛选/暗色模式实现,也没有体现声明中的触发词、飞书推送、GitHub Pages 部署或定时生成逻辑。因此这不是对声明功能的支撑细节,而是一个 materially different primary purpose,属于明显不匹配。

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
声明描述的核心能力是生成 AI 行业新闻网站,重点在新闻采集、HTML 页面生成、搜索筛选、暗色模式、外部新闻/图表注入以及自动化分发。实际代码却完全没有新闻抓取、页面生成、搜索筛选、暗色模式、部署或调度相关逻辑;它只是一个用于校验模型排行榜数据质量的纯函数模块。虽然声明里提到“刷新模型排行榜”作为运维触发词之一,但该片段的主功能仍明显属于排行榜数据治理子模块,而不是所宣称的新闻网站生成能力。因此该代码片段与声明用途存在明显不匹配。

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
声明描述的核心能力是生成 AI 行业新闻网站,重点在 RSS 新闻抓取、新闻聚合、可搜索展示、暗色模式、以及可选外部新闻注入。实际代码却完全没有新闻抓取、RSS 处理、HTML 生成、站点渲染或自然语言触发逻辑;它的功能是并行抓取多个模型排行榜源、监控这些榜源的可用性和延迟、并将健康快照写入 JSONL 文件。这不是单纯的底层支撑细节,而是一个与“新闻网站生成”明显不同的子系统,属于未在描述中体现的重要能力与不同目的。因此描述与代码行为存在实质性不匹配。

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
声明的核心能力是生成 AI 行业新闻网站,并强调新闻来自 RSS 抓取、可由外部新闻 JSON 增强;而代码实际是 leaderboard_sources.py,专门负责从多个模型榜单站点抓取排行榜、热度、价格、上下文、许可证等数据。它没有体现新闻抓取、RSS 解析、HTML 新闻站生成、搜索筛选 UI、暗色模式、分发部署或定时生成逻辑。虽然声明中提到一个运维触发词“刷新模型排行榜”,这说明整个技能可能包含排行榜相关子功能,但本代码块的主要行为与声明的主体用途“AI 行业新闻网站生成工具”并不相符,因此应判定为描述与代码行为存在明显不匹配。

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
声明描述的是一个 AI 行业新闻网站生成工具,核心能力应围绕新闻抓取、聚合、展示和站点生成。实际代码却完全聚焦于模型排行榜数据的元数据补全与权威资料卡覆盖,处理对象是模型名称、成本、上下文窗口、许可证、商用属性和多模态等字段。代码没有显示任何 RSS 抓取、新闻内容处理、HTML 网站生成、搜索筛选、暗色模式、推送部署或定时任务相关逻辑。因此这不是单纯的底层支持实现细节,而是与声明主用途明显不同的功能模块,构成实质性不匹配。

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The declared description presents an end-user skill for generating an AI news website from RSS feeds with optional injected external data and automation triggers. The supplied code chunk, however, is not implementing that user-facing functionality. It is a test module validating low-level internal functions around AI model leaderboards and metadata handling. While such functions could be supporting components of a broader AI weekly/news system, this specific chunk’s actual behavior is materially different from the declared primary purpose: it neither generates a website, nor parses RSS, nor handles triggers, deployment, or dark-mode/search/filter UI. Therefore this code chunk does not accurately represent the declared skill behavior.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
声明描述的是一个面向最终用户的 AI 新闻网站生成与分发技能,核心能力应是抓取 RSS、生成单文件 HTML 新闻站、支持自然语言触发、自动化生成/部署等。而代码片段实际是一个运维/修复性质的离线脚本,专门处理历史 HTML 周报中的翻译缺失问题。它不实现 RSS 抓取、网站生成、搜索/筛选/暗色模式、自然语言触发、部署推送或定时自动生成等声明中的核心功能。相反,它引入了声明未强调的本地 Ollama 翻译依赖,并执行回填翻译、修补静态卡片注解、导出译文缓存源等维护操作。因此代码行为与技能声明的主要用途存在明显不一致。

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
声明描述的核心能力是“生成 AI 行业新闻网站”,而代码的核心用途完全不同:它是一个本地/仓库内容扫描器,用于发布前合规门禁。脚本会遍历 git 跟踪文件或指定目录,匹配敏感词、WARN 叙事、代理提及、凭据模式,并检查若干禁止打包的文件/目录。这与新闻采集、内容生成、网页构建和自动化发布无关,属于明显的主要目的不一致,并且代码具备未在描述中声明的合规审查与秘密扫描功能,因此应判定为描述与行为不匹配。

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The declared description presents a full end-user feature set for generating and operating an AI news website. The supplied code chunk does not implement any of those capabilities; it only adjusts Python import paths for pytest. While such a file could be a supporting test configuration within a larger project, evaluating this chunk alone shows behavior that is materially different from the declared purpose and unrelated to the described triggers and functionality.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
该代码块的实际职责是“部署已生成的 HTML 周报”,而不是“生成 AI 行业新闻网站”。虽然声明文本中确实提到部分运维/分发触发词(如部署到 GitHub Pages、推送到飞书),说明部署属于整体技能的一部分,但这段代码超出了仅 GitHub Pages 的范围,新增了多个外部托管后端,并直接依赖云存储 SDK 与第三方部署 CLI。对于一个宣称核心为 RSS 驱动新闻网站生成、且强调不内置第三方商业 API 的技能来说,这段代码表现出的主要能力是多平台发布基础设施,和声明的主功能存在明显偏移。故应判定为描述与代码行为不完全一致,属于实质性 mismatch。

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
声明描述的是一个完整的 AI 新闻网站生成与分发/运维工具,核心能力应包括收集新闻、生成单文件 HTML 新闻站,以及可选部署和推送。而实际代码块的职责非常有限:它只对已经存在的 HTML 报告做解析,提取标题与 KPI,输出摘要 JSON 和通知文本。代码注释还明确说明“不依赖任何 Agent SDK / 云端部署工具”“具体推送由调用方决定”,进一步表明它不负责声明中的生成、抓取、部署、推送等核心能力。因此,该代码块与声明的主要用途存在明显不一致,属于实质性能力不匹配。

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding
声明把技能核心描述为“AI 新闻网站生成工具”,并特别强调默认依赖 RSS、且不内置任何第三方商业 API,若要外部知识类 API 增强应由用户自行提供数据注入。实际代码虽然与‘RSS 抓取 AI 新闻’这一部分高度一致,但它本身不是网站生成代码,而是上游抓取脚本。此外,代码明确内置了可选 News API 集成:只要传入 --news-api 并设置 NEWSAPI_KEY,就会直接请求第三方商业新闻接口,这与“不内置任何第三方商业 API、由用户自行获取数据注入”的说法冲突。代码还会默认请求 Hugging Face leaderboard 外部接口,并可选调用本地 Ollama 做翻译,这些属于声明未充分体现的额外能力。综合来看,描述与该代码块存在实质性不匹配,尤其是在外部 API 使用方式和代码主职责上。

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The declared description presents the skill as an AI news website generator with RSS aggregation, optional external data injection, search/filter/dark-mode output, deployment, and scheduled generation. The supplied code chunk does none of that. Instead, it is a standalone Feishu configuration wizard that stores webhook or target identifiers in JSON files for later use by separate publishing scripts. While Feishu push is mentioned in the broader description as a supported operational action, this code’s actual purpose is narrowly scoped to configuring Feishu delivery, not generating or updating the AI news website itself. That makes the code chunk materially different from the declared primary purpose.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
描述的核心能力是“生成 AI 行业新闻网站/周报”,并提到自动化生成;但这段代码的实际职责是安装或卸载一个系统级定时调度器,用于定时运行另一个刷新脚本。虽然“支持自动化”与定时执行在高层上有关联,但该代码具体实现的是对操作系统调度资源的持久化配置,这属于重要的系统修改能力,描述中未明确说明会创建 Windows 任务计划或修改 crontab。且这段代码本身不执行新闻聚合、网站生成、搜索筛选、暗色模式等宣称功能,因此就该代码块而言,实际行为与声明用途存在明显不匹配。

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The declared description is about generating an AI news website and handling news ingestion, optional injected external news data, distribution, and scheduled report generation. The supplied code does not generate any HTML, fetch RSS news, process AI industry news items, or implement user-facing natural-language triggers. Instead, it is a maintenance/diagnostic utility focused on probing accessibility of leaderboard data sources and mirrors, likely for troubleshooting ranking-source collection. This is a materially different primary purpose from the declared skill behavior, so it should be flagged as a mismatch.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
声明描述的是一个“AI 行业新闻网站生成工具”,核心能力应包括抓取新闻源(RSS)、汇总 AI 行业动态、生成新闻网站/周报页面,并可能支持分发、自动化和外部新闻注入。实际代码却是一个独立的镜像构建脚本:调用 aiweekly.leaderboard.fetch_all_leaderboards 抓取排行榜数据,写出 leaderboard.json,并复制 model_profiles.json。它处理的是模型/排行榜镜像托管问题,而非新闻站生成。虽然声明中提到“刷新模型排行榜”这一触发词,说明整个技能可能包含排行榜相关子功能,但这段代码的主要目的与声明的主功能明显不一致,且缺少新闻抓取、HTML 生成、搜索筛选、暗色模式、RSS 处理等关键行为。因此应判定为描述与代码行为存在实质性不匹配。

Tp4

High
Category
MCP Tool Poisoning
Confidence
93% confidence
Finding
描述将该技能的核心定位为“AI 行业新闻网站生成工具”,强调 RSS 抓取生成单文件 HTML 网站,并提及分发/运维触发词作为附属能力。当前代码片段却不是网站生成或 RSS 抓取逻辑,而是一个发布脚本:复用已有结构化产物,组装 report.json,构造飞书卡片,向飞书 webhook 推送,并可进一步部署现成 HTML 到多个托管后端。虽然描述中确实提到“把周报推送到飞书、部署到 GitHub Pages”,因此飞书分发与部署并非完全未声明,但该代码片段的主功能与所宣称的主功能明显不同:它不负责生成 AI 新闻网站,也不体现“直接说人话触发”“RSS 默认抓取”“无第三方商业 API 新闻增强注入”等核心承诺。就‘描述是否准确代表该代码块实际行为’而言,存在明显不一致,应判定为 mismatch。

Tp4

High
Category
MCP Tool Poisoning
Confidence
93% confidence
Finding
描述强调的是“AI 行业新闻网站生成工具”:自然语言触发、RSS 聚合新闻、可选外部新闻注入、生成单文件 HTML 网站。当前代码片段本身并不执行这些核心新闻抓取与内容生成逻辑,而是一个运维/发布脚本,负责调用其他脚本生成页面、提交 gh-pages,并推送到 GitHub。尤其是它显式访问 GitHub 凭据并进行远端部署,这属于较强的额外能力,而声明中未提到需要读取凭据或执行 git push。虽然描述里提到“部署到 GitHub Pages”“每周一自动生成最新版网站”等运维场景,因此与整体技能方向并非完全无关,但该代码片段的主要目的已经偏向部署自动化与凭据处理,而不是所声明的核心网站生成/RSS 抓取能力,因此应判定为存在描述与实际行为的不匹配。

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
声明描述的核心功能是生成 AI 行业新闻网站,并基于 RSS/可选外部新闻数据来形成新闻周报站点;而给出的代码块并未抓取新闻、生成 HTML、处理自然语言触发词、部署 GitHub Pages、推送飞书或做自动化周报生成。它的唯一明确用途是维护一个国内模型排行榜兜底快照 JSON:抓取 Artificial Analysis、DataLearner 等榜单数据,判断历史数据是否同源,给不可达源保留缓存并重写说明字段,然后写回本地文件。这与“AI 新闻网站生成工具”的主功能和数据类型都明显不一致,属于实质性描述与行为不匹配。

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
声明描述的核心能力是“生成 AI 行业新闻网站”,包括新闻抓取、周报生成、外部数据注入和自动化分发。实际代码却是一个运维/部署辅助脚本,专门用于配置 GitHub Pages 的发布来源到 gh-pages 分支。虽然声明中提到“部署到 GitHub Pages”属于整体技能场景的一部分,但这段代码本身的主功能并不是生成新闻网站,而是修改 GitHub 仓库 Pages 设置,且需要访问 GitHub API 与令牌凭证。这构成了与声明主用途明显不一致的代码行为,因此应判定为 mismatch。

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The declared description presents an end-user skill for generating and operating an AI news website, including content sourcing, optional external data injection, deployment, and automation. The supplied code chunk does not implement those behaviors. It only exposes an internal API of validation utilities by importing and re-exporting checker functions from several modules. While some checker names relate to news, charts, rankings, and safety, this chunk’s actual role is report/site validation infrastructure, not the described website generation workflow. Therefore the code chunk does not accurately represent the declared purpose.

Static analysis

Detected: suspicious.insecure_tls_verification

HTTPS certificate verification is disabled.

Warn
Code
suspicious.insecure_tls_verification
Location
scripts/aiweekly/utils.py:249