T09 · Insecure Skill Coding Practices
- Location
SKILL.md:143- Finding
Overbroad Report Cleanup Deletes All Matching Reports
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This market-reporting skill is mostly aligned with financial news reporting, but it requires persistent local storage and includes an unsafe automatic report-deletion command that users should review before installing.
Review this skill carefully before installing. It should only be used if you are comfortable with it reading and writing OpenClaw memory/report files, caching fetched news, invoking other local skill scripts, and performing cleanup. The deletion instruction should be corrected or removed before routine use, because it can remove more report history than intended.
SKILL.md:143Overbroad Report Cleanup Deletes All Matching Reports
scripts/news-processor.py:2Runtime Dependencies Are Not Reproducibly Pinned
The description promises a sophisticated cross-market anomaly/news reporting system with explicit source governance and verification. The supplied code does something materially simpler and different: it calculates market-open display status, invokes local scripts to get stock index and BTC prices, and formats a static report shell. The 'news' portion is not implemented; it contains placeholders instructing future collection from certain outlets, but no scraping, searching, URL extraction, whitelist enforcement, source diversity, temporal checks, or anti-hallucination safeguards exist in code. Additionally, the outlets listed in the template differ from the declared set (e.g., 36氪/人民网 appear, while Reuters/东方财富/华尔街见闻 are absent). Therefore the declared description does not accurately represent the actual behavior.
The code’s actual purpose is a simple recent-news fetcher for the last 24 hours from three Chinese finance outlets. While these outlets are mentioned within the declared source set, the implementation is far narrower and materially different from the stated skill. The description promises sophisticated report generation across both Chinese and global markets, using additional sources and Brave search, with whitelist enforcement, diversity quotas, signal scanning, temporal verification, and market-isolation controls. None of those behaviors appear in the code. The script merely retrieves and prints news entries; it does not analyze, score, verify, isolate markets, or synthesize anomaly/delta reports. Therefore the declared description does not accurately represent the supplied code chunk.
The declared description promises a sophisticated market-anomaly reporting skill with search-based source discovery, whitelist enforcement, diversity constraints, verification guardrails, and strict coverage rules across named Chinese and global media. The supplied code instead performs straightforward scraping of a fixed set of endpoints and RSS feeds, then deduplicates and assigns sentiment via simple keyword matching. It outputs a raw news summary report and counts. While it does cover both Chinese and foreign news and includes source URLs when available, many core declared features are absent, and the actual source set materially differs from the declared one. Therefore the description does not accurately represent the code’s actual behavior.
This duplicated finding identifies the same unsafe deletion pattern: a destructive shell command with wildcard expansion and no guardrails. In agentic contexts, parameterized shell deletion is particularly risky because environment differences or future edits can broaden the deletion target unexpectedly.
- ⛔ 此步骤不可跳过。未成功存盘则不得输出报告。
- 存盘后立即执行:删除 24 小时前的旧文件 `rm memory/capital_market_report_*.md`(只保留 24h 内的)
- 下一份报告生成时,第一步就是 `ls memory/capital_market_report_*.md` 加载过去 24h 全部已存报告作为 Delta 基线
### 3.1 格式锁
This duplicated finding identifies the same unsafe deletion pattern: a destructive shell command with wildcard expansion and no guardrails. In agentic contexts, parameterized shell deletion is particularly risky because environment differences or future edits can broaden the deletion target unexpectedly.
- ⛔ 此步骤不可跳过。未成功存盘则不得输出报告。
- 存盘后立即执行:删除 24 小时前的旧文件 `rm memory/capital_market_report_*.md`(只保留 24h 内的)
- 下一份报告生成时,第一步就是 `ls memory/capital_market_report_*.md` 加载过去 24h 全部已存报告作为 Delta 基线
### 3.1 格式锁
This is a true tool-parameter abuse issue because a shell command is assembled dynamically and executed through the shell, allowing shell metacharacters, path manipulation, or environmental influence to alter behavior. In this skill context, the command launches another local script from a user-home path, so compromise of that path or future argument expansion could lead to arbitrary local command execution under the agent's privileges.
cmd = f"uv run {script_path} {' '.join(all_codes)}"
try:
result = subprocess.run(cmd, shell=True, capture_output=True, text=True, timeout=30)
# 解析输出 - 按顺序匹配
lines = result.stdout.strip().split('\n')[2:] # 跳过表头
data = {}
The function accepts a symbol parameter and passes it into a shell command string, creating a direct avenue for tool-parameter abuse if the parameter ever becomes user-controlled or indirectly influenced. Because the code executes a local script from a workspace path, successful exploitation could run arbitrary commands or a swapped malicious helper script, making the impact substantial.
cmd = f"uv run {script_path} {symbol}"
try:
result = subprocess.run(cmd, shell=True, capture_output=True, text=True, timeout=30)
# 解析: "Bitcoin (BTC): $67,947.09"
line = result.stdout.strip()
if "$" in line:
Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.
# 1. 新浪财经 - 要闻(增加数量到30条)
echo "【新浪财经要闻】"
curl -s "https://feed.mix.sina.com.cn/api/roll/get?pageid=153&lid=2509&k=&num=50&r=0.123" 2>/dev/null | python3 -c "
import sys, json
try:
data = json.load(sys.stdin)
Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.
# 2. 财联社 - 电报(增加数量到30条)
echo "【财联社电报】"
curl -s "https://www.cls.cn/api/telegraph?app=CailianpressWeb&os=web&sv=8.4.6&sign=" 2>/dev/null | python3 -c "
import sys, json
try:
data = json.load(sys.stdin)
Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.
# 3. 华尔街见闻(增加数量到20条)
echo "【华尔街见闻】"
curl -s "https://api.wallstreetcn.com/apiv1/content/articles?platform=wscn-platform&channel=global&limit=30" 2>/dev/null | python3 -c "
import sys, json
try:
data = json.load(sys.stdin)
The skill invokes shell commands, reads prior reports, writes new reports, and expects network-backed data collection, but it does not declare an explicit tool scope or allowed-tools boundary. That creates an authorization and review gap: an operator may approve a reporting skill without realizing it can access files, persist data, and execute shell actions.
The skill content and output requirements are written to enforce Chinese-language reporting behavior, including Chinese labels and formatting conventions, without indicating that the user may choose another language. This creates a locale policy concern because the skill appears to mandate a specific language by default rather than offering opt-in or documenting a justified regional constraint.
The skill mandates writing reports into persistent local memory, creating a durable record of generated content and source-derived summaries across sessions. Persistent storage can expose sensitive prompts, outputs, or research history to later tasks or users if retention, isolation, and access controls are not clearly bounded.
# 文件名格式:capital_market_report_YYYYMMDD_HHMM.md
# 示例输出:
write ~/.openclaw/workspace-group/memory/capital_market_report_20260515_1500.md
The documentation instructs deletion of local files as part of normal operation even though file destruction is not necessary to generate a market report. Normalizing cleanup commands in a reporting skill expands its effect on the local environment and can lead to unintended data loss, especially if paths or globbing behave unexpectedly.
A skill whose core purpose is report generation should not include unrelated destructive filesystem operations. This widens the blast radius of execution and makes it easier for operators or downstream agents to perform harmful actions under the guise of routine report handling.
The skill directs the agent to delete files automatically without any user-facing warning, review step, or confirmation. Silent destructive actions are dangerous because they can irreversibly remove historical data and are easy to trigger repeatedly in an automated workflow.
The docstring states the generator 'always fetches all data' and later comments repeat that market-time checks are only for display. In reality, the script only fetches stock and Bitcoin data; commodity prices are left as placeholders and news collection is entirely unimplemented, so the documentation overstates what the code actually retrieves.
The file's natural-language description and embedded report content are entirely in Chinese and indicate fixed behavior for generating the report, with no opt-in or language-selection mechanism. The policy requires flagging language or locale constraints when the skill forces a specific language without user choice or a clearly documented regional justification.
This code constructs a shell command and executes an external script via subprocess.run(..., shell=True), but the only nearby comments describe data retrieval and not the fact that a shell subprocess is being launched. Under the code-file criteria, subprocess execution should have some disclosure such as a clear user-facing log, confirmation, or documented warning unless it is explicitly part of the skill's stated purpose, which is not evident from this file alone.
The code builds a shell command string and executes it with shell=True, which is dangerous because shell parsing introduces command-injection risk if any argument or path becomes attacker-controlled through configuration, environment, or future code changes. In a skill environment that chains other local skills, this also expands the trust boundary to external scripts and the shell interpreter, making unintended command execution more likely and more damaging.
cmd = f"uv run {script_path} {' '.join(all_codes)}"
try:
result = subprocess.run(cmd, shell=True, capture_output=True, text=True, timeout=30)
# 解析输出 - 按顺序匹配
lines = result.stdout.strip().split('\n')[2:] # 跳过表头
data = {}
The manifest describes capital market anomaly and delta reports focused on Chinese and global markets, with equity/media-source controls and web-search/scraper based reporting. This code adds a separate capability by shelling out to a different skill for cryptocurrency pricing, which is not mentioned in the manifest and is not necessary to implement the stated stock/news reporting purpose.
The function builds and runs another shell command to invoke a separate script for cryptocurrency pricing. Although the skill later prints a generic '正在获取数据...' message, it does not specifically disclose that an external subprocess will be executed, which is the kind of safety-relevant behavior this rule asks to warn about in code files.
This subprocess call has the same unsafe pattern: a shell command string is constructed and executed with shell=True. Although the current symbol is hardcoded to BTC, the function accepts a parameter and could become user-influenced later, so the pattern is a real injection and command-execution risk rather than a purely theoretical issue.
cmd = f"uv run {script_path} {symbol}"
try:
result = subprocess.run(cmd, shell=True, capture_output=True, text=True, timeout=30)
# 解析: "Bitcoin (BTC): $67,947.09"
line = result.stdout.strip()
if "$" in line:
The manifest claims enforced coverage of specific Chinese sources such as 华尔街见闻、东方财富 and global outlets including Reuters, but the code's report template instead lists 36氪、人民网 and omits several declared sources. This is a direct description-behavior mismatch because the implemented source set presented to the user differs from the manifest's promised media whitelist and coverage model.
The header comment and printed messaging state that the script gets recent 24-hour events and only focuses on news within the last 24 hours. However, although L12 computes a 24-hour cutoff timestamp, that value is never used; the script simply prints the first N items returned by each feed without comparing article times against the cutoff.
No suspicious patterns detected.