Back to skill

Security audit

外贸资讯聚合器 (多源 RSS + 翻译 + 飞书推送)

Security checks for vulnerabilities and agentic risk

Overview

The skill fits a news-aggregation purpose, but it needs review because it posts untrusted news reports to external webhooks and gives weak secret-storage guidance.

Install only if you are comfortable sending selected news topics, titles, translations, summaries, and error details to the configured third-party services. Use trusted RSS feeds, a dedicated low-privilege Feishu bot, avoid putting secrets directly in ~/.bashrc or crontab, and consider patching the skill to validate URLs, escape Markdown, and support a local-only mode before scheduled use.

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 (2)

T09 · Insecure Skill Coding Practices

Warning
Location
SKILL.md:30
Finding
Plaintext credential storage in shell startup files or crontab is recommended<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md`, lines 30 and 47-51 **Vulnerability Type**: Plaintext sensitive-data exposure **Risk Level**: Medium ### Vulnerable Code ```markdown 本 Skill 不会自动加载任何外部 `.env` 文件。请通过环境变量或直接在 crontab 中设置密钥. ``` The configuration section also recommends persistent shell configuration: ```bash export BAIDU_APPID="你的AppID" export BAIDU_SECRET="你的密钥" export FEISHU_WEBHOOK="你的飞书Webhook地址" ``` ### Technical Analysis The documentation advises users to place the Baidu API secret and Feishu webhook URL directly in `~/.bashrc` or a crontab entry. Both are persistent plaintext configuration locations. A Feishu webhook URL is effectively a bearer credential: anyone who obtains it can generally submit messages to the associated bot. The Baidu translation secret can similarly be abused to consume the account's API quota or incur charges. Environment variables also become available to child processes and may be exposed through diagnostic output, process inspection under applicable operating-system permissions, shell backups, support bundles, or accidentally shared configuration files. Placing credentials directly in a crontab is unnecessary for the declared news-aggregation functionality. Scheduling the aggregator can be legitimate, but embedding secrets in the schedule definition does not follow least-secret-exposure practices. The project does not itself install a cron job, startup service, or other persistence mechanism. Therefore, the reviewed code does not establish a T06 system-persistence vulnerability. The finding concerns insecure credential-storage guidance rather than unauthorized persistence. ### Attack Path 1. A user follows the documented setup and stores `BAIDU_SECRET` and `FEISHU_WEBHOOK` in `~/.bashrc` or directly inside their crontab. 2. Another local process, account with applicable read permissions, backup operator, diagnostic collector, or person receiving a copied configuration file obtains the p ...[truncated 825 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Do not recommend placing secrets directly in `~/.bashrc` or inline in crontab. - Store credentials in a dedicated file readable only by the owning account, for example with mode `0600`, and load it only in the execution wrapper. - Prefer an operating-system credential facility or secret manager where available. - If cron is used, keep the schedule free of credentials and invoke a restricted wrapper that retrieves secrets at runtime. - Run the scheduled task as an unprivileged, dedicated account with access only to the output and history directories it needs. - Document webhook and API-secret rotation procedures. - Warn users not to print environment variables, commit credential files, or include them in support bundles. - Make `FEISHU_WEBHOOK` optional in metadata as documented, rather than treating it as an unconditional dependency. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
daily-news.sh:125
Finding
Untrusted RSS content is embedded into Feishu Markdown without validation<![CDATA[ ## Vulnerability Details **File Location**: `daily-news.sh`, lines 125-159 **Vulnerability Type**: Markdown content injection and trusted-channel phishing **Risk Level**: Medium ### Vulnerable Code ```bash for ((i=0; i<COUNT; i++)); do title="${final_titles[$i]}" url="${final_urls[$i]}" num=$((i+1)) zh=$(translate "$title") # 清理链接 clean_url=$(echo "$url" | sed 's/^[| ]*//;s/[| ]*$//;s/&amp;/\&/g') # 标题变成可点击链接 echo "**$num. [$title]($clean_url)**" [ -n "$zh" ] && [ "$zh" != "null" ] && echo " - 中文: $zh" echo "" sleep 1 done ``` The resulting attacker-influenced Markdown is then sent directly to Feishu: ```bash if [ -n "$FEISHU_WEBHOOK" ]; then CARD_JSON=$(jq -n \ --arg title "📰 每日外贸资讯 - $DATE" \ --arg content "$(cat "$OUTPUT")" \ '{ "msg_type": "interactive", "card": { "config": {"wide_screen_mode": true}, "header": {"title": {"tag": "plain_text", "content": $title}, "template": "blue"}, "elements": [ {"tag": "div", "text": {"tag": "lark_md", "content": $content}}, {"tag": "hr"}, {"tag": "note", "elements": [{"tag": "plain_text", "content": "Generated by OpenClaw | 外贸资讯聚合器 v2.2.3"}]} ] } }') curl -X POST -H "Content-Type: application/json" -d "$CARD_JSON" "$FEISHU_WEBHOOK" > /dev/null 2>&1 fi ``` ### Technical Analysis RSS titles and links are externally controlled data. The script inserts them directly into Markdown link syntax: ```text [title](URL) ``` The only URL processing trims separators and decodes `&amp;`. It does not: - Escape Markdown metacharacters in titles. - Validate the parsed URL. - Restrict URL schemes to `https` or `http`. - Restrict destination hosts. - Prevent titles from closing the current Markdown construct and adding new links or misleading text. The use of `jq --arg` safely ...[truncated 1852 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Parse RSS using a structured parser and treat every title and link as untrusted. - Escape Markdown metacharacters in titles before constructing Feishu Markdown, including backslashes, brackets, parentheses, asterisks, underscores, backticks, and line breaks as appropriate for Feishu. - Parse each URL and allow only explicit `https` and, if required, `http` schemes. - Reject URLs containing credentials, control characters, malformed hosts, or unexpected schemes. - Consider a destination-host allowlist when the operational requirements permit it. - Prefer Feishu plain-text elements for untrusted titles. If clickable links are required, use structured card elements that keep display text and URL in separate validated fields. - Apply equivalent validation in `classify_news.py` before links are placed into the analysis card. - Record rejected items without reproducing their complete hostile content in logs. - Add tests covering titles such as `](https://attacker.example)[`, embedded newlines, nested formatting, Unicode lookalike domains, and non-HTTP URL schemes. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (20)

Tainted flow: 'WEBHOOK_URL' from os.environ.get (line 6, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Content
# 打印发送的 JSON 用于调试
print("发送的 JSON:", card)

resp = requests.post(WEBHOOK_URL, json=card)
print(f"✅ 分析报告已推送,状态码: {resp.status_code}")
print("响应内容:", resp.text)
Confidence
90% confidence
Finding
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Tainted flow: 'WEBHOOK_URL' from os.environ.get (line 8, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Content
}
    }
    try:
        resp = requests.post(WEBHOOK_URL, json=card)
        print(f"趋势报告已推送,状态码: {resp.status_code}")
    except Exception as e:
        print(f"推送失败: {e}")
Confidence
90% confidence
Finding
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The skill explicitly sends fetched news content to external services: titles/content are transmitted to Baidu Translate, RSS data is pulled from external sources, and results may be posted to a Feishu group. Because the description does not clearly warn users that third parties may receive potentially sensitive keywords, article titles, or generated summaries, users may unknowingly expose business interests or internal monitoring topics to outside services.

Context-Inappropriate Capability

Medium
Confidence
89% confidence
Finding
No manifest is available, so there is no declared purpose establishing that sending processed news data to a remote webhook is intended. The code reads a local news file, formats its contents, and posts the resulting report to an externally configured URL, which is a materially broader capability than simple local classification.

Natural-Language Policy Violations

Medium
Confidence
91% confidence
Finding
The script uses Chinese-only user-facing messages and category labels, including error text, report headers, and summaries, with no option for the user to select another language. This creates a natural-language locale policy issue because the skill implicitly forces Chinese output rather than offering opt-in or documenting that the skill is intentionally Chinese-only.

External Transmission

Medium
Category
Data Exfiltration
Content
# 打印发送的 JSON 用于调试
print("发送的 JSON:", card)

resp = requests.post(WEBHOOK_URL, json=card)
print(f"✅ 分析报告已推送,状态码: {resp.status_code}")
print("响应内容:", resp.text)
Confidence
80% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
Comments, status messages, errors, and output headings are written exclusively in Chinese, and the translation target is forced to zh. This imposes a specific language/locale without any opt-in mechanism or documented justification that the skill is intended only for Chinese-speaking users.

Context-Inappropriate Capability

Medium
Confidence
92% confidence
Finding
The file is documented as an '外贸资讯聚合器' (trade/foreign-trade news aggregator), but it also supports pulling top stories from Hacker News via the INCLUDE_HACKER_NEWS option. General technology-news scraping is not obviously justified by the stated trade-news purpose and expands the skill's capability beyond the described context.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
Article titles are sent to Baidu's translation API, which is a third-party service, without any disclosure or consent mechanism. Even if titles are public, the selected set of content, keywords, and usage pattern can reveal business interests, monitoring priorities, or sensitive research topics.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
if command -v xmlstarlet >/dev/null 2>&1; then
        xmlstarlet sel -t -m "//item" -v "title" -o "||" -v "link" -o "||" -n "$tmp" 2>/dev/null
    else
        echo "错误:未安装 xmlstarlet,请运行 sudo apt install xmlstarlet -y" >&2
        return 1
    fi
    rm "$tmp"
Confidence
70% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Context-Inappropriate Capability

Medium
Confidence
92% confidence
Finding
The script transmits runtime error details to an external Feishu webhook without any built-in consent, warning, or data minimization. Error messages can contain network details, feed URLs, file paths, or other operational context that may be sensitive in an enterprise environment.

External Transmission

Medium
Category
Data Exfiltration
Content
local error_msg="$1"
    if [ -n "$FEISHU_WEBHOOK" ]; then
        local json=$(jq -n --arg msg "❌ 外贸资讯聚合器运行失败\n\n错误详情: $error_msg" '{"msg_type":"text","content":{"text":$msg}}')
        curl -X POST -H "Content-Type: application/json" -d "$json" "$FEISHU_WEBHOOK" > /dev/null 2>&1
    fi
}
Confidence
93% confidence
Finding
This line performs an external POST of error information to a configurable webhook endpoint. Because the destination and contents are externally transmitted, this can leak operational details or be abused for unintended data exfiltration if the webhook is misconfigured or controlled by an untrusted party.

External Transmission

Medium
Category
Data Exfiltration
Content
]
            }
        }')
    curl -X POST -H "Content-Type: application/json" -d "$CARD_JSON" "$FEISHU_WEBHOOK" > /dev/null 2>&1
    echo "✅ 已推送到飞书(卡片消息)"
fi
Confidence
95% confidence
Finding
This line sends the full generated report to an external webhook, creating a clear exfiltration path for collected and transformed content. In a business setting, the aggregated topics and translations may reveal strategic interests or internal monitoring activity.

Missing User Warnings

Medium
Confidence
96% confidence
Finding
The generated report content is posted to Feishu via webhook without explicit disclosure in the script's primary behavior. This creates an external data-sharing path that could expose curated news selections, translated text, and organizational interests to a third-party messaging platform.

Context-Inappropriate Capability

Medium
Confidence
91% confidence
Finding
The file's comments and title describe a news aggregator, but at the end it triggers classify_news.py and trend_analysis.py, adding downstream classification and multi-day trend-analysis behavior. Those extra analytics capabilities are broader than straightforward aggregation and are not evident from the stated purpose in this file.

Context-Inappropriate Capability

Medium
Confidence
88% confidence
Finding
The skill requires a secret webhook from the environment and uses it to transmit derived local data off-host, but the provided context does not declare or justify this external reporting behavior. In agent environments, undeclared outbound channels are risky because they can silently export workspace-derived information to an external service.

Natural-Language Policy Violations

Medium
Confidence
92% confidence
Finding
This code emits user-facing messages in Chinese, indicating a fixed language choice rather than adapting to user preference. The file provides no opt-in, configuration, or documentation justifying a Chinese-only locale, which matches the language/locale policy violation criteria.

Context-Inappropriate Capability

Medium
Confidence
93% confidence
Finding
This code aggregates categories from a local file and history directory, then posts the resulting trend report to an external Feishu webhook. Even though the payload is summarized rather than raw content, it still constitutes exfiltration of locally derived information without any stated authorization boundary or consent mechanism.

Natural-Language Policy Violations

Medium
Confidence
89% confidence
Finding
The report title and console messages are all hard-coded in Chinese, and the skill does not expose any way for users to choose another language. Because this affects multiple user-visible outputs, it represents an ongoing locale policy issue rather than a single isolated string.

External Transmission

Medium
Category
Data Exfiltration
Content
}
    }
    try:
        resp = requests.post(WEBHOOK_URL, json=card)
        print(f"趋势报告已推送,状态码: {resp.status_code}")
    except Exception as e:
        print(f"推送失败: {e}")
Confidence
80% confidence
Finding
The skill performs an external HTTP POST to a webhook, sending data derived from local files to a third-party endpoint. In this context the transmission appears functional rather than overtly malicious, but undeclared outbound data flow from an agent skill is security-relevant because it can leak workspace information beyond the local trust boundary.

Static analysis

No suspicious patterns detected.