Back to skill

Security audit

行业雷达

Security checks for vulnerabilities and agentic risk

Overview

Review is needed because default access settings could expose saved reports or permit unwanted paid AI requests, and model connections bypass promised safeguards.

Use only an isolated local demo until browser origins are restricted and private credentials are configured before first startup. Changing credential environment variables does not update an existing account. Keep paid models and sensitive keywords disabled until the model HTTP client matches the documented safeguards. Update affected dependencies, and manually remove retained report files when deleting data.

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

Warning
Location
app/backend/main.py
Finding

Default demo credentials and unrestricted CORS permit unauthorized account access

Content
View full analysis

Impact

Read the demo account's subscriptions, articles and briefings; change or delete its subscriptions; and trigger generation using server resources, including configured paid LLM calls. This does not establish access to other users' accounts or arbitrary host files.

Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Output HandlingUnvalidated Output Injection, Cross-Context Output, Unbounded Output
Findings (28)

Cloud Metadata Access

High
Category
Server-Side Request Forgery
Confidence
90% confidence
Finding

Code accesses a cloud instance metadata endpoint (e.g. 169.254.169.254). A single request can return temporary IAM credentials, making this a high-value SSRF target for credential theft.

Content

Scanner excerpt · README.md (reported line 42)May include surrounding context.

md
## 安全设计

- 所有出站请求统一走 `app/backend/net_guard.py`:仅 http/https,禁回环 / 私网 / 链路本地(含 `169.254.169.254`)/ 组播 / 保留段,重定向逐跳复检,响应体上限 3MB
- DNS 校验结果固定到连接层(Host 头与 TLS SNI/证书照旧校验),连接建立后再复核对端 IP,杜绝 DNS 重绑定(TOCTOU)
- Fake-IP 网段 `198.18.0.0/15` 默认拒绝,需显式 `IR_ALLOW_PROXY_FAKEIP=1` 放行
- 不读取 `HTTP_PROXY` / `HTTPS_PROXY`,避免流量被环境变量劫持

Cloud Metadata Access

High
Category
Server-Side Request Forgery
Confidence
90% confidence
Finding

Code accesses a cloud instance metadata endpoint (e.g. 169.254.169.254). A single request can return temporary IAM credentials, making this a high-value SSRF target for credential theft.

Content

Scanner excerpt · SKILL.md (reported line 143)May include surrounding context.

md
- **MUST** LLM API Key 只通过环境变量 `IR_LLM_API_KEY` 注入,绝不写入文件、代码或对话
- **MUST** 默认监听 `127.0.0.1`;对外暴露需 `--host 0.0.0.0` 并自担风险(会话机制为演示级)
- **MUST** 所有出站只走 `app/backend/net_guard.py`:仅允许 http/https,禁止回环 / 私网 /
  链路本地(含 `169.254.169.254` 云元数据)/ 组播 / 保留段,DNS 解析结果逐个校验,
  重定向逐跳重新校验(防「公网 302 到内网」),响应体限 3MB
- **MUST** 校验与连接必须使用同一个 IP:`safe_get()` 在校验后把目标 IP 固定到连接层
  (自定义 `HTTPAdapter` 改写 TCP 目标),同时保留原 Host 头与 TLS SNI/证书校验。

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
80% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

Scanner excerpt · SKILL.md (reported line 89)May include surrounding context.

md
| 登录拿 Token           | `POST /api/login`(demo/demo),后续请求带 `Authorization: Bearer ...` |
| 查看可用数据源         | `GET /api/sources`(14 个内置源,见 references/api-reference.md)    |
| 录入自定义 RSS 源      | `POST /api/custom-sources`(`name` + `url`,录入时即时探测必须抓到 ≥1 条,否则 400) |
| 自定义源列表 / 改 / 删 | `GET` / `PUT` / `DELETE /api/custom-sources/{cs_id}`(`PUT` 可 `enabled=false` 停用) |
| 手动检测自定义源       | `POST /api/custom-sources/{cs_id}/test` —— 返回抓到的条目数,不落库        |
| 在订阅里引用自定义源   | `sources` 数组里写 `"cs:<cs_id>"`(例如 `["36kr","cs:7"]`),只能引自己名下的源 |
| 创建订阅               | `POST /api/subscriptions`(行业词、技术词必填)                      |

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
80% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

Scanner excerpt · SKILL.md (reported line 89)May include surrounding context.

md
| 登录拿 Token           | `POST /api/login`(demo/demo),后续请求带 `Authorization: Bearer …` |
| 查看可用数据源         | `GET /api/sources`(14 个内置源,见 references/api-reference.md)    |
| 录入自定义 RSS 源      | `POST /api/custom-sources`(`name` + `url`,录入时即时探测必须抓到 ≥1 条,否则 400) |
| 自定义源列表 / 改 / 删 | `GET` / `PUT` / `DELETE /api/custom-sources/{cs_id}`(`PUT` 可 `enabled=false` 停用) |
| 手动检测自定义源       | `POST /api/custom-sources/{cs_id}/test` —— 返回抓到的条目数,不落库        |
| 在订阅里引用自定义源   | `sources` 数组里写 `"cs:<cs_id>"`(例如 `["36kr","cs:7"]`),只能引自己名下的源 |
| 创建订阅               | `POST /api/subscriptions`(行业词、技术词必填)                      |

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
80% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

Scanner excerpt · SKILL.md (reported line 98)May include surrounding context.

md
| 读取简报(列表/详情)  | `GET /api/briefings?subscription_id=…` / `GET /api/briefings/{id}`   |
| 导出 Markdown         | `GET /api/briefings/{id}/export`                                     |
| 趋势 / 总览看板        | `GET /api/trend?subscription_id=…` / `GET /api/dashboard`            |
| 修改 / 删除订阅        | `PUT` / `DELETE /api/subscriptions/{id}`                             |

### 典型调用链

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
80% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

Scanner excerpt · SKILL.md (reported line 186)May include surrounding context.

md
- **启用 LLM 即外发**:采集到的文章正文、标题、订阅的行业/技术关键词会发送到
  `IR_LLM_BASE_URL` 指定的第三方模型服务商。涉密或未公开情报场景请保持
  `IR_LLM_BASE_URL` / `IR_LLM_API_KEY` 未配置状态(自动降级为本地规则引擎,全程不出网到模型方)
- **删除订阅不等于删除数据**:`DELETE /api/subscriptions/{id}` 只清库中订阅与关联记录,
  `app/data/briefings/*.md` 历史简报仍留在磁盘,需自行清理
- **自定义源 URL 会外发**:录入的自定义 RSS 地址由本机直接请求,不做任何中转或共享

Cloud Metadata Access

High
Category
Server-Side Request Forgery
Confidence
90% confidence
Finding

Code accesses a cloud instance metadata endpoint (e.g. 169.254.169.254). A single request can return temporary IAM credentials, making this a high-value SSRF target for credential theft.

Content

Scanner excerpt · app/backend/net_guard.py (reported line 8)May include surrounding context.

python
----
本服务的正文页 URL 来自 RSS 条目、也就是**外部可控内容**。若直接
`requests.get(article_url)`,攻击者只要在源里塞一条指向
`http://169.254.169.254/...`(云元数据)或 `http://10.0.0.5:8080/`
(内网服务)的链接,就能借服务端身份去访问内网。

策略(默认拒绝)

Cloud Metadata Access

High
Category
Server-Side Request Forgery
Confidence
90% confidence
Finding

Code accesses a cloud instance metadata endpoint (e.g. 169.254.169.254). A single request can return temporary IAM credentials, making this a high-value SSRF target for credential theft.

Content

Scanner excerpt · app/backend/net_guard.py (reported line 18)May include surrounding context.

python
2b. 端口白名单(默认 80/443,`IR_ALLOWED_PORTS` 可配),杜绝借高位端口探测内网服务;
    IP 字面量仅当落在公网地址段时才放行。
3. 主机名先按字面判断,再做 DNS 解析,**所有**解析结果必须落在公网地址段,
   否则拒绝——命中回环、私网、链路本地(含 169.254.169.254 元数据)、
   CGNAT、保留段、组播、IPv6 ULA / link-local 都要拦。
4. 不自动跟随重定向:手动逐跳跟随(最多 MAX_REDIRECTS 次),
   每一跳都重新走第 1~3 步,防止「公网 302 到内网」绕过。

Cloud Metadata Access

High
Category
Server-Side Request Forgery
Confidence
90% confidence
Finding

Code accesses a cloud instance metadata endpoint (e.g. 169.254.169.254). A single request can return temporary IAM credentials, making this a high-value SSRF target for credential theft.

Content

Scanner excerpt · app/backend/net_guard.py (reported line 31)May include surrounding context.

python
残余风险与生产建议
----
本模块已消除应用层 DNS 重绑定窗口,但仍建议在网络层做纵深防御:云上部署时在
VPC 侧配置 Security Group + NAT 白名单,禁止访问 169.254.169.254 与内网网段。
注意:为保持 IP 固定有效,本模块**故意忽略** HTTP_PROXY / HTTPS_PROXY 环境变量;
如需经代理出网,请使用 TUN / fake-IP 模式(并显式设置 IR_ALLOW_PROXY_FAKEIP=1)。
"""

Cloud Metadata Access

High
Category
Server-Side Request Forgery
Confidence
90% confidence
Finding

Code accesses a cloud instance metadata endpoint (e.g. 169.254.169.254). A single request can return temporary IAM credentials, making this a high-value SSRF target for credential theft.

Content

Scanner excerpt · app/backend/net_guard.py (reported line 67)May include surrounding context.

python
"10.0.0.0/8",         # 私网 A
    "100.64.0.0/10",      # CGNAT(云厂商内部常用)
    "127.0.0.0/8",        # 回环
    "169.254.0.0/16",     # 链路本地:169.254.169.254 云元数据
    "172.16.0.0/12",      # 私网 B
    "192.0.0.0/24",       # IETF 协议分配
    "192.0.2.0/24",       # TEST-NET-1

Cloud Metadata Access

High
Category
Server-Side Request Forgery
Confidence
90% confidence
Finding

Code accesses a cloud instance metadata endpoint (e.g. 169.254.169.254). A single request can return temporary IAM credentials, making this a high-value SSRF target for credential theft.

Content

Scanner excerpt · app/backend/net_guard.py (reported line 107)May include surrounding context.

python
_BLOCKED_HOSTNAMES = {
    "localhost", "localhost.localdomain", "ip6-localhost", "ip6-loopback",
    "metadata", "metadata.google.internal", "instance-data",
}
_BLOCKED_SUFFIXES = (".localhost", ".local", ".internal", ".home.arpa")

Known Vulnerable Dependency: python-multipart==0.0.20 — 14 advisory(ies): CVE-2026-53539 (python-multipart: Quadratic-time querystring parsing with semicolon separators c); CVE-2026-53538 (python-multipart: Semicolon treated as querystring field separator enables param); CVE-2026-40347 (python-multipart affected by Denial of Service via large multipart preamble or e) +11 more

High
Category
Supply Chain
Confidence
88% confidence
Finding

The supplied advisories identify this python-multipart pin as affected by parsing vulnerabilities, including denial of service and parameter interpretation inconsistencies. Its presence alongside FastAPI makes processing attacker-controlled form or multipart input plausible, potentially exposing backend availability if affected parsing paths are reachable. The requirements file does not establish endpoint exposure or whether this application's query-string handling uses the affected parser, so application-level exploitability remains conditional.

Content

No source excerpt is available for this finding.

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
80% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

Scanner excerpt · references/api-reference.md (reported line 105)May include surrounding context.

md
会清零 `fail_count`,给它一次干净的重试机会。响应:`{"message": "更新成功"}`
(改过 URL 时额外带 `items`)。非本人源一律 `404`。

### DELETE /api/custom-sources/{cs_id}

响应:`{"message": "已删除"}`。会先把引用它的订阅里对应的 `cs:<id>` 摘掉,
不会留下指向空源的订阅。

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
80% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

Scanner excerpt · references/api-reference.md (reported line 188)May include surrounding context.

md
会清零 `fail_count`,给它一次干净的重试机会。响应:`{"message": "更新成功"}`
(改过 URL 时额外带 `items`)。非本人源一律 `404`。

### DELETE /api/custom-sources/{cs_id}

响应:`{"message": "已删除"}`。会先把引用它的订阅里对应的 `cs:<id>` 摘掉,
不会留下指向空源的订阅。

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
80% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

Scanner excerpt · references/api-reference.md (reported line 264)May include surrounding context.

md
Body 传需要修改的字段(同上,均可选,另支持 `enabled` 0/1)。响应:`{"message": "更新成功"}`

### DELETE /api/subscriptions/{sub_id}

响应:`{"message": "已删除"}`。注意:历史简报 `.md` 文件保留在磁盘。

Whitespace Padding

Medium
Category
Prompt Injection
Confidence
70% confidence
Finding

Large whitespace padding was detected (a block of blank lines or a long run of spaces). This can push injected instructions below or to the right of the visible area so a human reviewer never sees them while the agent still reads them. Manual review of the hidden content is recommended.

Content

Scanner excerpt · SKILL.md (reported line 113)May include surrounding context.

md
## 关键陷阱

| 陷阱                              | 原因 / 规则                                                                                                              |
| --------------------------------- | ------------------------------------------------------------------------------------------------------------------------ |
| run 只补增量文章                  | simhash 去重会过滤已入库文章;同一订阅短时间内重复 run 新文章很少。要全新效果请用 `/api/preview` 或删除订阅后重建        |
| Token 重启即失效                  | 会话存内存。服务重启后所有 Token 失效,重新 `POST /api/login` 即可                                                        |

Whitespace Padding

Medium
Category
Prompt Injection
Confidence
70% confidence
Finding

Large whitespace padding was detected (a block of blank lines or a long run of spaces). This can push injected instructions below or to the right of the visible area so a human reviewer never sees them while the agent still reads them. Manual review of the hidden content is recommended.

Content

Scanner excerpt · SKILL.md (reported line 130)May include surrounding context.

md
## 故障排查

| 症状                           | 修复                                                                                     |
| ------------------------------ | ---------------------------------------------------------------------------------------- |
| `run` 返回 500 生成失败        | 看服务日志(终端输出)中的 pipeline 异常;多为网络全挂——检查代理后重试                  |
| 端口被占用                     | `python3 scripts/run_local.py --port 8001`                                                |

Summaries and insights are forced to Chinese without user opt-in.

Medium
Category
Output Handling
Confidence
98% confidence
Finding

The skill states that its summary and insight prompts hard-code Chinese and that no language-switching configuration is available. Requiring users to edit local prompt templates does not provide a user-facing language choice, and no locale-specific justification is given for the restriction.

Content

No source excerpt is available for this finding.

Unbounded Resource Access

Medium
Category
Excessive Agency
Confidence
80% confidence
Finding

Skill allows unbounded resource consumption (API calls, storage, compute). Without rate limits or quotas, a compromised or misbehaving agent can cause denial-of-service or cost overruns.

Content

Scanner excerpt · app/backend/net_guard.py (reported line 376)May include surrounding context.

python
# 环境代理会重新解析域名,使 IP 固定失效,因此显式忽略代理配置。
    session.trust_env = False
    adapter: HTTPAdapter = (
        _PinnedHTTPSAdapter(server_hostname=target.host, expected_ip=ip, max_retries=0)
        if target.scheme == "https"
        else _PinnedHTTPAdapter(expected_ip=ip, max_retries=0)
    )

Unbounded Resource Access

Medium
Category
Excessive Agency
Confidence
80% confidence
Finding

Skill allows unbounded resource consumption (API calls, storage, compute). Without rate limits or quotas, a compromised or misbehaving agent can cause denial-of-service or cost overruns.

Content

Scanner excerpt · app/backend/net_guard.py (reported line 378)May include surrounding context.

python
adapter: HTTPAdapter = (
        _PinnedHTTPSAdapter(server_hostname=target.host, expected_ip=ip, max_retries=0)
        if target.scheme == "https"
        else _PinnedHTTPAdapter(expected_ip=ip, max_retries=0)
    )
    session.mount(target.scheme + "://", adapter)
    try:

Known Vulnerable Dependency: requests==2.32.5 — 2 advisory(ies): CVE-2026-25645 (Requests has Insecure Temp File Reuse in its extract_zipped_paths() utility func); CVE-2026-25645 (Requests is a HTTP library. Prior to version 2.33.0, the `requests.utils.extract)

Medium
Category
Supply Chain
Confidence
85% confidence
Finding

The supplied advisory identifies this pinned Requests version as affected by insecure temporary-file reuse in extract_zipped_paths(); the two advisory entries refer to the same CVE, not two distinct vulnerabilities. Exploitation depends on use of that utility and an attacker being able to influence the relevant temporary-file environment, neither of which is established by this requirements file. Exact version pinning improves reproducibility but does not protect against vulnerabilities in the pinned release.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
80% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · app/backend/summarizer.py (reported line 45)May include surrounding context.

python
"Content-Type": "application/json",
    }
    try:
        resp = requests.post(url, json=payload, headers=headers, timeout=LLM_TIMEOUT)
        resp.raise_for_status()
        data = resp.json()
        return (data["choices"][0]["message"]["content"] or "").strip()

Generation prompts require Chinese output without a user language choice.

Medium
Category
Output Handling
Confidence
99% confidence
Finding

The prompts explicitly require a Chinese summary (L115), Chinese insights (L136), and a Chinese section title (L180). The file provides no language opt-in or documented regional requirement justifying these fixed-language instructions.

Content

No source excerpt is available for this finding.

The documented exception-safe fallback does not cover prompt construction, allowing curated_closing to abort report generation.

Medium
Category
Excessive Agency
Confidence
98% confidence
Finding

curated_closing constructs article context before entering its try/except: a missing title raises KeyError, and a non-string summary can fail during slicing. If malformed external article records reach this function, they can abort report generation instead of triggering the documented fallback; upstream validation may reduce exploitability but is not shown here.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · references/api-reference.md (reported line 12)May include surrounding context.

POST /api/login

bash
curl -s -X POST http://127.0.0.1:8000/api/login \
  -H 'Content-Type: application/json' \
  -d '{"username":"demo","password":"demo"}'

Static analysis

No suspicious patterns detected.