Back to skill

Security audit

Industry News Agent

Security checks for vulnerabilities and agentic risk

Overview

This appears to be a legitimate RSS news helper, but it documents persistent daily cron execution and broad configurable network fetching without enough guardrails.

Review before installing. Manual use is consistent with the stated RSS-news purpose, but avoid the cron command unless you are comfortable creating a persistent daily job and know how to inspect and remove it from your crontab. Keep RSS sources limited to trusted public feed URLs, and be aware that the keyword filter may fall back to showing recent articles even when no keywords matched.

Vulnerability Patterns
  • System PersistenceInstalls backdoors, hooks, services, or scheduled tasks that survive the run
  • 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
Findings (2)

T06 · System Persistence

Error
Location
SKILL.md:137
Finding
Persistent Daily Execution Through a User Crontab Entry## Vulnerability Details **File Location**: `SKILL.md`, lines 137-140 **Vulnerability Type**: Persistent scheduled execution **Risk Level**: High **Vulnerable Code:** ```bash ### Set up daily automatic delivery ```bash (crontab -l 2>/dev/null; echo "0 9 * * * python3 ~/.openclaw/workspace/skills/industry-news-agent/scripts/fetch_news.py") | crontab - ``` ``` ### Technical Analysis The documentation instructs the user to modify the user-level crontab so that the Skill's Python script runs every day at 09:00. This creates execution that survives both the current Skill invocation and the current login session. Scheduled operation is related to the declared daily-news functionality, but the command is not necessary for manual RSS retrieval and exceeds the privileges required for a one-time run. It also has the following weaknesses: - It establishes persistent execution without an accompanying removal procedure. - It uses a script under a user-writable workspace. Any later modification of that script will be executed automatically. - It uses `python3` through the cron environment's `PATH` rather than a verified absolute interpreter path. - Repeating the installation command appends duplicate scheduled entries. - It hardcodes the schedule instead of reading the `schedule` value from `config.yaml`. - The current implementation prints results locally and does not implement a delivery destination, despite describing the feature as automatic delivery. This command is presented as an optional manual setup step; the reviewed Python script does not install the cron entry automatically. ### Attack Path 1. A user follows the documented automatic-delivery instructions. 2. The command appends a persistent cron entry to the user's crontab. 3. An attacker or another process that can modify the Skill workspace later replaces or alters `scripts/fetch_news.py`. 4. At 09:00, cron resolves `python3` and runs the modified scri ...[truncated 904 chars]
Remediation
## Remediation Suggestions - Keep scheduled operation explicitly opt-in and clearly explain that it creates a persistent user-level task. - Provide a dedicated, idempotent installer that checks for an existing uniquely marked entry before making changes. - Provide a documented uninstall command that removes only the Skill's own entry. - Use verified absolute paths for both the Python interpreter and the script. - Verify script ownership and permissions before scheduled execution. - Use the schedule declared in `config.yaml` instead of maintaining a separate hardcoded value. - Prefer a restricted user service or scheduler configuration with resource, filesystem, and network controls where supported. - If the Skill is intended only for on-demand retrieval, remove the cron instructions entirely.

T09 · Insecure Skill Coding Practices

Error
Location
scripts/fetch_news.py:55
Finding
Server-Side Request Forgery Through Unrestricted Configurable RSS URLs## Vulnerability Details **File Location**: `scripts/fetch_news.py`, lines 55-61 **Vulnerability Type**: Unrestricted outbound request / SSRF **Risk Level**: High **Vulnerable Code:** ```python req = urllib.request.Request( source['url'], headers={'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'} ) with urllib.request.urlopen(req, timeout=15) as response: content = response.read().decode('utf-8', errors='ignore') ``` ### Technical Analysis Every URL from the user-editable `rss_sources` configuration is passed directly to `urllib.request.urlopen`. The code does not enforce an allowed scheme, validate the destination hostname or resolved IP address, restrict redirects, or block loopback, private, reserved, and link-local networks. Consequently, a malicious or compromised configuration can direct the process to internal services such as loopback applications, private network endpoints, or cloud metadata addresses. Redirects also require validation because an initially public URL could redirect to a prohibited internal address. The timeout limits request duration but does not mitigate SSRF. In addition, `response.read()` has no maximum size, allowing a configured or compromised server to cause excessive memory consumption. ### Attack Path 1. An attacker modifies `config.yaml` or persuades the user to add an attacker-controlled RSS source. 2. The source URL points directly to an internal address or to a public server that redirects to one. 3. The user runs the script manually, or the installed cron task invokes it automatically. 4. `urlopen` sends a request from the victim host to the attacker-selected destination. 5. The attacker uses response behavior, errors, timing, or RSS-compatible response content to probe internal services. 6. If the internal endpoint returns XML containing suitably dated and keyword-matching entries, selected response data may be incorporated into ...[truncated 858 chars]
Remediation
## Remediation Suggestions - Accept only `https` RSS URLs unless another scheme is explicitly required and secured. - Resolve destination hostnames and reject loopback, private, link-local, multicast, reserved, and unspecified IP ranges. - Repeat destination validation after every DNS resolution and redirect. - Disable redirects or impose a small redirect limit with validation at each hop. - Consider an explicit allowlist of trusted RSS domains. - Reject URLs containing embedded credentials or unexpected ports. - Stream responses and enforce a strict maximum response size before XML parsing. - Apply connection and read timeouts separately where possible. - Run scheduled retrieval with restricted network and filesystem permissions. - Protect `config.yaml` from unauthorized modification and validate its schema before use.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Rogue AgentSelf-Modification, Session Persistence
  • YARA SignaturesMalware Match, Webshell Match, Cryptominer Match
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (10)

YARA rule 'backdoor_persistence': Backdoor persistence with malicious payloads (shell commands, SSH key injection, hidden root users) [malware]

High
Category
YARA Match
Content
��**:3月25日,速腾聚创公布2025年第四季度及全年业绩报告。财报显示,2025年全年,速腾聚创实现营收约19.41亿元...

**链接**:https://36kr.com/p/37397129...

---

共 12 条资讯
```

---

## 🔧 使用方式

### 手动运行
```bash
python3 ~/.openclaw/workspace/skills/industry-news-agent/scripts/fetch_news.py
```

### 设置每日自动推送
```bash
(crontab -l 2>/dev/null; echo "0 9 * * * python3 ~/.openclaw/workspace/skills/industry-news-agent/scripts/fetch_news.py") | crontab -
```

---

## ❓ 常见问题

### Q: 如何添加新的 RSS 源?

**A:** 编辑 `config.yaml`,添加:
```yaml
rss_sources:
  - name: 媒体名称
    url: https://example.com/feed
```

### Q: 如何修改关键词?

**A:** 编辑 `config.yaml`,修改 `keywords_include` 和 `keywords_exclude`。

---

## 📝 更新日志

- **v3.1.0** - 🔧 改为获取最近24小时文章;修复 pubDate 解析 bug(Element 布尔判断问题)
- **v3.0.2** - 修�
Confidence
75% confidence
Finding
YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Lp3

Medium
Category
MCP Least Privilege
Confidence
86% confidence
Finding
The skill documentation describes capabilities that read local configuration files and access remote RSS feeds, but it does not declare an explicit tool scope such as permissions or allowed-tools. This can cause the runtime to grant broader-than-expected access or make reviewers unaware of the skill's actual privileges, which increases risk if the skill is modified or misused.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The instructions recommend installing a cron job that creates a persistent scheduled task, but they do not clearly warn the user that this modifies system state beyond the current session. Persistent automation can surprise users, continue running indefinitely, and repeatedly perform network activity without explicit ongoing consent.

Session Persistence

Medium
Category
Rogue Agent
Content
### 设置每日自动推送
```bash
(crontab -l 2>/dev/null; echo "0 9 * * * python3 ~/.openclaw/workspace/skills/industry-news-agent/scripts/fetch_news.py") | crontab -
```

---
Confidence
85% confidence
Finding
The cron example establishes session persistence by registering a recurring task in the user's crontab. While the payload appears to be a legitimate news-fetch script rather than an obvious backdoor, persistence is still security-relevant because it creates ongoing autonomous execution and recurring network access.

Natural-Language Policy Violations

Medium
Confidence
91% confidence
Finding
The file title and surrounding configuration are explicitly written for a Chinese-language workflow ('行业资讯小哨兵') and include a Chinese-only source selection such as '金融时报中文', with no indication that users may choose another language or locale. Under the policy, forcing a specific language without user opt-in is a natural-language policy violation unless the locale restriction is explicitly justified.

Description-Behavior Mismatch

Medium
Confidence
88% confidence
Finding
The manifest says the skill supports custom keywords and filtered news pushing, which implies results should respect those filters. In filter_articles(), when keyword filtering yields no matches, the code falls back to returning the latest deduplicated articles anyway, defeating the stated filtering behavior.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The docstring mandates a fixed output format entirely in Chinese, and the rest of the user-facing messages in the script are also Chinese-only. For an all-file-types language policy check, this is a natural-language locale constraint with no user opt-in or documented regional justification.

Natural-Language Policy Violations

Low
Confidence
87% confidence
Finding
文件描述和整体使用说明均将技能定位为中文输出/中文配置场景,但未说明这是可选项,也未给出语言或区域选择。按规则,若技能强制特定语言而无用户 opt-in,属于自然语言层面的策略问题。

Intent-Code Divergence

Low
Confidence
97% confidence
Finding
The module docstring states '通过 RSS 获取昨日新闻', and main() also labels the fetch date as '昨天'. However, fetch_rss() filters articles using get_recent_24h_range() rather than calendar-day 'yesterday', so the documentation and user-facing messaging describe different behavior than the code performs.

Intent-Code Divergence

Low
Confidence
96% confidence
Finding
main() prints '抓取日期: ...(昨天)', which implies a fixed previous-day window. But the actual selection logic in fetch_rss() compares publication times against now minus 24 hours, so the runtime messaging actively misstates the implemented time scope.

Static analysis

No suspicious patterns detected.