T07 · Tool Hijacking and Spoofing
- Location
scripts/post_daily_report.py:6- Finding
Execution of an Unverified External Shell Script
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The skill’s report-to-X automation is mostly disclosed, but it delegates posting to an unverified external shell script and can publish publicly or schedule recurring posts without a clear confirmation gate.
Review before installing. This skill can post publicly to the X account already logged in on the machine and may be used with cron for recurring posts. Only use it if you trust the external tweet.sh script it calls, understand which X account/session it will use, and are comfortable with unattended public posting and local posting-history state.
scripts/post_daily_report.py:6Execution of an Unverified External Shell Script
scripts/post_daily_report.py:52Failed Publication Is Unconditionally Recorded as Successful
External input (network, user) flows to a code execution sink. This enables remote code execution or command injection.
tweet = f"New AI research report released.\n\n{latest}\n\n{summary}\n\nReport:\n{REPORT_SITE}\n\n#AI #TechTwitter"
subprocess.run(["bash", TWEET_SCRIPT, tweet, "https://x.com"], check=False)
posted.add(latest)
with open(STATE_FILE, "w") as f:
The code largely matches the core declared purpose: it fetches the latest unposted report from a website, drafts an English X post, calls a separate script to publish it via X, and records prior posts to avoid duplicates. However, there are material gaps versus the description. The implementation only handles a hardcoded HTML website and contains no JSON feed support. It stores posted report titles, not IDs. Also, this chunk itself does not implement scheduling, though that may be external. These differences are enough to mark a partial mismatch, even though the primary purpose is substantially aligned.
The skill clearly instructs use of network access, shell execution, and file writes, but it declares no explicit tool scope or permissions. That creates an overbroad execution surface where an agent may use more capabilities than the user expects, especially because the workflow includes external posting and state persistence.
The skill is designed to perform automated external actions, including posting to X and setting up scheduled cron execution, but it does not require an explicit warning or confirmation step. This increases the risk of unintended public posting or persistent automation being launched without sufficiently informed user consent.
The activation section lists example requests such as '自动把最新报告发到 X' and '帮我把报告站做成自动社媒分发', but it does not define what kinds of sources, posting scopes, or user intents should not invoke the skill. This ambiguity could cause the skill to be selected for loosely related social-media automation requests beyond the intended report-to-X workflow.
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
tweet = f"New AI research report released.\n\n{latest}\n\n{summary}\n\nReport:\n{REPORT_SITE}\n\n#AI #TechTwitter"
subprocess.run(["bash", TWEET_SCRIPT, tweet, "https://x.com"], check=False)
posted.add(latest)
with open(STATE_FILE, "w") as f:
The manifest describes selecting a report, drafting a post, and publishing via the logged-in X web session. While posting to X is in scope, invoking an external bash script adds a general subprocess-execution capability that is not itself justified or disclosed by the stated purpose, and it delegates sensitive behavior outside the visible Python logic.
The script publishes to a logged-in X session automatically with no confirmation, dry-run, or explicit user-visible warning in the code path. In a scheduled automation context, that makes remote website content capable of triggering unintended public posts, including reputationally damaging or policy-violating messages if the source site is compromised or parsing is manipulated.
The instruction '默认英文发帖:除非用户要求中文或双语' imposes a language default rather than asking the user to choose their preferred language first. This is a natural-language policy issue because it forces a locale/language behavior without explicit user opt-in.
The script writes posting history to ~/.openclaw/memory/zeelin_last_report.json at L56-L57, which affects user data on disk. This file includes no visible warning, prompt, or explanatory docstring/comment telling the user that local state will be created and updated.
No suspicious patterns detected.