Back to skill

Security audit

Ai Daily

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly matches its AI news briefing purpose, but it includes unsafe networking, over-privileged scheduling guidance, and a helper that can send report content to a hard-coded DingTalk group.

Install only if you are comfortable with a Chinese-focused AI news aggregator that contacts external feeds and APIs. Do not use the DingTalk push helper until the destination is configurable and verified. Avoid the root systemd setup; prefer manual runs or user-level scheduling. Remove the curl-to-bash pyenv step, keep API keys out of shell startup files when possible, and fix TLS verification before using Tavily or other authenticated network calls on untrusted networks.

Vulnerability Patterns
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • 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
Findings (4)

T03 · Remote Payload Retrieval and Execution

Error
Location
INSTALL.md:210
Finding
Unverified Remote Installer Is Piped Directly Into a Shell<![CDATA[ ## Vulnerability Details **File Location**: `INSTALL.md:210-216` **Vulnerability Type**: Remote payload retrieval and immediate execution **Risk Level**: Critical ### Vulnerable Code ```bash # Ubuntu/Debian sudo apt install python3.8 # Or use pyenv curl https://pyenv.run | bash pyenv install 3.8.10 pyenv global 3.8.10 ``` ### Technical Analysis The installation guide instructs users to download a mutable script from `https://pyenv.run` and pipe it directly into `bash`. The response is neither inspected nor pinned to a reviewed version, and no cryptographic signature or checksum is verified. Although pyenv is a legitimate project, this installation pattern makes the code ultimately executed on the host depend on the remote server's response at installation time. The effective payload can therefore change after the Skill itself has been reviewed. ### Attack Path 1. A user follows the Python troubleshooting instructions. 2. `curl` retrieves the current response from `pyenv.run`. 3. The response is immediately interpreted by `bash`. 4. If the remote service, publishing pipeline, DNS resolution, or network path is compromised, attacker-supplied shell commands execute with the invoking user's privileges. 5. Those commands can modify user startup files, install additional payloads, access user-readable data, or establish persistence. ### Impact Assessment Successful exploitation provides arbitrary command execution as the user running the command. If the command is run from a privileged shell, the payload receives the same elevated privileges. At minimum, it may access the user's files, environment, credentials, shell configuration, and development workspace. ]]>
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove the `curl | bash` pipeline from the installation guide. 2. Prefer a trusted operating-system package where available. 3. If pyenv is necessary, pin a reviewed release or commit. 4. Download the installer separately rather than executing it immediately: ```bash curl --fail --proto '=https' --tlsv1.2 \ --output pyenv-installer \ https://raw.githubusercontent.com/pyenv/pyenv-installer/<PINNED_COMMIT>/bin/pyenv-installer ``` 5. Verify the file against a documented cryptographic checksum or trusted signature. 6. Inspect the downloaded script before execution. 7. Run installation without `sudo` and under a minimally privileged account. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/ai_daily.py:258
Finding
TLS Certificate Verification Is Disabled for All Application Requests<![CDATA[ ## Vulnerability Details **File Location**: `scripts/ai_daily.py:258-261` **Vulnerability Type**: Improper certificate and hostname validation **Risk Level**: High ### Vulnerable Code ```python def __init__(self, config: Dict[str, Any]): self.config = config self.ssl_context = ssl.create_default_context() self.ssl_context.check_hostname = False self.ssl_context.verify_mode = ssl.CERT_NONE ``` The insecure context is subsequently used for generic feed requests and authenticated Tavily API calls: ```python req = urllib.request.Request( url, data=data, headers={ 'Content-Type': 'application/json', 'Authorization': f'Bearer {self.tavily_api_key}' } ) with urllib.request.urlopen( req, context=self.ssl_context, timeout=30 ) as response: result = json.loads(response.read().decode('utf-8')) ``` The arXiv API is also accessed over plaintext HTTP: ```python url = f"http://export.arxiv.org/api/query?search_query={urllib.parse.quote(search_query)}&start=0&max_results={max_results//len(categories)}&sortBy=submittedDate&sortOrder=descending" ``` ### Technical Analysis Setting `verify_mode` to `ssl.CERT_NONE` disables certificate-chain validation, while disabling `check_hostname` permits a certificate issued for an unrelated host. Consequently, the client cannot authenticate HTTPS endpoints. The same SSL context is used for requests carrying the Tavily bearer token. An attacker capable of intercepting network traffic can present an arbitrary certificate, impersonate `api.tavily.com`, and receive the authorization header. The attacker can also alter RSS, API, and article responses. The plaintext arXiv request provides no transport authenticity or confidentiality at all. ### Attack Path 1. The victim runs the report generator on an attacker-controlled or compromised network. 2. The attacker intercepts DNS or network traffic. 3. For HTTPS requests, the attacker presents an arbitrary certificat ...[truncated 811 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Retain Python's secure default SSL behavior: ```python self.ssl_context = ssl.create_default_context() ``` 2. Remove both of the following assignments: ```python self.ssl_context.check_hostname = False self.ssl_context.verify_mode = ssl.CERT_NONE ``` 3. Replace the arXiv URL with its HTTPS equivalent: ```python url = "https://export.arxiv.org/api/query?..." ``` 4. Fail closed on TLS validation errors rather than retrying insecurely. 5. If a private certificate authority is required, explicitly load only that trusted CA instead of disabling validation. 6. Rotate the Tavily API key if the application has already been used over an untrusted network. 7. Apply host allowlisting and redirect controls to authenticated API requests so credentials cannot be forwarded to an unexpected origin. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/push-to-dingtalk.sh:5
Finding
Generated Report Content Is Sent to a Hard-Coded DingTalk Group<![CDATA[ ## Vulnerability Details **File Location**: `scripts/push-to-dingtalk.sh:5-26` **Vulnerability Type**: Hard-coded external recipient and unintended data disclosure **Risk Level**: High ### Vulnerable Code ```bash TODAY=$(date +%Y-%m-%d) REPORT_FILE="/home/admin/.openclaw/workspace/skills/ai-daily/output/AI-Daily-${TODAY}.md" if [ ! -f "$REPORT_FILE" ]; then echo "❌ Report file for today was not found: $REPORT_FILE" exit 1 fi echo "Preparing to push the ${TODAY} AI report to a DingTalk group..." # Read the first 60 lines of the report as the summary SUMMARY=$(head -60 "$REPORT_FILE") # Construct the message MESSAGE="AI Model Daily Report | ${TODAY} ${SUMMARY} --- *Full report: /home/admin/.openclaw/workspace/skills/ai-daily/output/AI-Daily-${TODAY}.md*" # Send through OpenClaw to the current DingTalk session openclaw sessions send --session "agent:main:dingtalk:group:cid+sxosobsr081ckhs0jpsqw==" --message "$MESSAGE" ``` ### Technical Analysis The script reads local report content and sends it to a fixed DingTalk session identifier embedded in the package. The destination is not supplied or confirmed by the user and is not declared in the main Skill metadata. Any user invoking this helper script may reasonably assume that it targets their own configured group. Instead, the first 60 lines are sent to the bundled destination. The message also discloses an absolute local filesystem path. The script is not called automatically by `generate.sh` or the supplied cron example, which limits exposure to cases where it is explicitly invoked or later integrated into automation. ### Attack Path 1. A user generates a report containing public feed data, customized sources, or locally edited content. 2. The user invokes `scripts/push-to-dingtalk.sh`, or adds it to the generation workflow. 3. The script reads the first 60 lines of the local report. 4. `openclaw sessions send` transmits that content to the hard-coded group session. 5. Members of t ...[truncated 490 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove the hard-coded DingTalk session identifier. 2. Require the destination to be provided explicitly: ```bash : "${DINGTALK_SESSION:?DINGTALK_SESSION must be configured}" openclaw sessions send --session "$DINGTALK_SESSION" --message "$MESSAGE" ``` 3. Display the resolved recipient and require confirmation on first use. 4. Keep notification delivery disabled by default. 5. Document exactly what report content will be transmitted. 6. Avoid including local absolute paths in externally delivered messages. 7. Consider sending only a minimal, user-approved summary instead of reading a fixed number of lines. 8. Validate that the configured destination belongs to the current user or workspace. ]]>

T06 · System Persistence

Warning
Location
INSTALL.md:133
Finding
Installation Guide Creates a Root-Managed Persistent systemd Timer<![CDATA[ ## Vulnerability Details **File Location**: `INSTALL.md:133-158` **Vulnerability Type**: Persistent scheduled execution with excessive system privileges **Risk Level**: Medium ### Vulnerable Code ```bash # Create service sudo tee /etc/systemd/system/ai-daily.service > /dev/null <<EOF [Unit] Description=AI Daily Report Generator [Service] Type=oneshot ExecStart=/bin/bash /home/admin/.openclaw/workspace/skills/ai-daily/scripts/generate.sh WorkingDirectory=/home/admin/.openclaw/workspace/skills/ai-daily EOF # Create timer sudo tee /etc/systemd/system/ai-daily.timer > /dev/null <<EOF [Unit] Description=Run AI Daily every day at 8:00 [Timer] OnCalendar=*-*-* 08:00:00 Persistent=true [Install] WantedBy=timers.target EOF # Enable sudo systemctl enable ai-daily.timer sudo systemctl start ai-daily.timer ``` ### Technical Analysis The instructions create a system-wide service and timer under `/etc/systemd/system`, then enable the timer across reboots. Scheduled execution is relevant to daily-report generation and is explicitly documented rather than hidden. However, system-level systemd persistence exceeds the minimum privileges required because user cron and OpenClaw scheduling are already available. No `User=` or other sandboxing directives are defined in the service. A system service therefore runs as root by default. Its `ExecStart` points to a script inside `/home/admin`, which may be under the control of a non-root account depending on deployment permissions. If that script or one of the imported project files is writable by a less-privileged user, the timer can become a recurring root execution path. ### Attack Path 1. An administrator follows the installation guide and creates the system service and timer. 2. The timer is enabled and survives reboots. 3. systemd invokes the service at 08:00, including after missed schedules because `Persistent=true` is configured. 4. The service runs without an explicit `User=`, so it defaults to root. 5. I ...[truncated 574 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Prefer OpenClaw scheduling, user cron, or a user-scoped systemd timer. 2. If systemd is required, install it under the user's systemd configuration and invoke it with: ```bash systemctl --user enable --now ai-daily.timer ``` 3. For a system service, define a dedicated unprivileged account: ```ini User=ai-daily Group=ai-daily ``` 4. Ensure root owns the executable and project files and that unprivileged users cannot modify them. 5. Add systemd hardening directives such as: ```ini NoNewPrivileges=true PrivateTmp=true ProtectSystem=strict ProtectHome=read-only ReadWritePaths=/var/lib/ai-daily ``` 6. Restrict environment variables and credentials exposed to the scheduled process. 7. Document removal and rollback commands: ```bash sudo systemctl disable --now ai-daily.timer sudo rm /etc/systemd/system/ai-daily.timer sudo rm /etc/systemd/system/ai-daily.service sudo systemctl daemon-reload ``` ]]>
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
Findings (49)

External Script Fetching

High
Category
Supply Chain
Content
sudo apt install python3.8

# 或使用 pyenv
curl https://pyenv.run | bash
pyenv install 3.8.10
pyenv global 3.8.10
```
Confidence
98% confidence
Finding
Piping a remote script from `https://pyenv.run` directly into a shell executes network-fetched code without prior inspection, signature verification, or integrity pinning. This is dangerous because compromise of the remote host, transit path, DNS, or installer content can lead to immediate arbitrary code execution on the user's machine.

Chaining Abuse

High
Category
Tool Misuse
Content
sudo apt install python3.8

# 或使用 pyenv
curl https://pyenv.run | bash
pyenv install 3.8.10
pyenv global 3.8.10
```
Confidence
98% confidence
Finding
The `| bash` construct turns downloaded content directly into executed shell commands, a classic command-chaining anti-pattern. In installation documentation, this materially increases risk because users are encouraged to run opaque remote code with no validation step, making arbitrary execution trivial if the source is malicious or compromised.

Tp2

High
Category
MCP Tool Poisoning
Confidence
85% confidence
Finding
Mixing characters from multiple Unicode scripts in a single identifier is a common technique to create visually ambiguous tool names.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding
The skill is described primarily as fetching and generating a daily brief, but it also exposes a 'view' command for reading previously generated local Markdown files from an output directory. That is a real description-behavior mismatch: undeclared local file access broadens the skill's capability surface and may let users retrieve local content beyond what they expect from a 'generate brief' skill.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The skill is described primarily as fetching and generating a daily brief, but it also exposes a 'view' command for reading previously generated local Markdown files from an output directory. That is a real description-behavior mismatch: undeclared local file access broadens the skill's capability surface and may let users retrieve local content beyond what they expect from a 'generate brief' skill.

Missing User Warnings

High
Confidence
99% confidence
Finding
The code disables TLS certificate validation globally for outbound requests by setting check_hostname to False and verify_mode to ssl.CERT_NONE. This allows a man-in-the-middle attacker to intercept or alter RSS feeds, search API responses, article content, and arXiv data, potentially poisoning the generated report or stealing API-backed request contents.

Natural-Language Policy Violations

Medium
Confidence
94% confidence
Finding
The changelog repeatedly describes automatic generation of "中文摘要" for multiple content types, which indicates a fixed language behavior. Under the policy, forcing a specific language without user opt-in is a natural-language policy violation unless the locale constraint is documented and justified.

Natural-Language Policy Violations

Medium
Confidence
91% confidence
Finding
The text says the skill will "自动生成简洁中文说明," which implies the skill outputs content in Chinese by default. There is no accompanying note that this is region-specific, optional, or configurable, so it appears to impose a locale without user choice.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The report explicitly describes external data sources and API keys, but does not clearly warn users that content, queries, and possibly fetched material will be sent to third-party services. In a skill that aggregates news and uses LLM processing, this omission can mislead users about privacy, data handling, network activity, and cost exposure.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The guide tells users to place API keys in shell startup files, which stores secrets in plaintext and causes them to be automatically loaded into future shell sessions. This increases exposure through local file disclosure, accidental backup/sync, shell debugging, inherited environments, or leakage into child processes and logs.

Session Persistence

Medium
Category
Rogue Agent
Content
#### 选项 A: 使用 Cron

```bash
crontab -e

# 添加每日 8:00 执行
0 8 * * * cd /home/admin/.openclaw/workspace/skills/ai-daily && bash scripts/generate.sh >> /var/log/ai-daily.log 2>&1
Confidence
85% confidence
Finding
The cron example establishes recurring execution, which is a persistence mechanism. In a skill that fetches external content and runs scripts regularly, persistence raises risk because any later compromise of the script, config, or dependencies will be repeatedly executed automatically.

Missing User Warnings

Medium
Confidence
88% confidence
Finding
The instructions create system-wide systemd units under `/etc/systemd/system` using `sudo`, which modifies privileged persistence mechanisms. Even if intended for convenience, this teaches users to install scheduled execution with elevated configuration scope without warning about the trust and persistence implications.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
```bash
# 创建 service
sudo tee /etc/systemd/system/ai-daily.service > /dev/null <<EOF
[Unit]
Description=AI Daily Report Generator
Confidence
82% confidence
Finding
This command requires `sudo` to write a system service definition into a privileged directory, enabling persistent execution at the system level. In skill-install documentation, normalizing privileged setup increases the blast radius if the referenced script is later modified, replaced, or behaves unexpectedly.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
EOF

# 创建 timer
sudo tee /etc/systemd/system/ai-daily.timer > /dev/null <<EOF
[Unit]
Description=Run AI Daily every day at 8:00
Confidence
82% confidence
Finding
This second `sudo tee` writes a timer unit into `/etc/systemd/system`, creating another privileged persistence mechanism. It expands the attack surface by scheduling code execution through system-managed startup without emphasizing review and least privilege.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
EOF

# 启用
sudo systemctl enable ai-daily.timer
sudo systemctl start ai-daily.timer
```
Confidence
84% confidence
Finding
`sudo systemctl enable ai-daily.timer` persists execution across reboots and user sessions at system scope. In the context of a downloadable skill, enabling persistence with elevated privileges can be abused if the underlying script, its dependencies, or fetched content are compromised later.

Session Persistence

Medium
Category
Rogue Agent
Content
EOF

# 启用
sudo systemctl enable ai-daily.timer
sudo systemctl start ai-daily.timer
```
Confidence
87% confidence
Finding
`systemctl enable` explicitly configures persistence, causing the timer to survive reboots. This is more sensitive in a content-aggregation skill because it will continue executing unattended and may process attacker-controlled external inputs over time.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
# 启用
sudo systemctl enable ai-daily.timer
sudo systemctl start ai-daily.timer
```

## 📊 输出示例
Confidence
77% confidence
Finding
Starting the timer with `sudo systemctl start` activates the privileged persistent task immediately. While not inherently malicious, it operationalizes elevated scheduled execution in a way that can magnify the impact of future script changes or compromise.

Natural-Language Policy Violations

Medium
Confidence
94% confidence
Finding
This markdown explicitly describes optimizing the output to increase Chinese media dominance, including prioritizing zh-CN sources and making them occupy most top results. The file does not indicate any user choice, opt-in, or region-specific justification for this language/locale bias, which conflicts with the policy against forcing a specific language or locale.

Natural-Language Policy Violations

Medium
Confidence
89% confidence
Finding
The embedded configuration sets the added sources' language to "zh-CN" and the surrounding text frames the change as a general optimization rather than a user-selected option. Because the file presents this as a default behavior and does not offer an alternative locale path, it constitutes a natural-language locale policy concern.

Natural-Language Policy Violations

Medium
Confidence
86% confidence
Finding
The document explicitly boosts Chinese-language keywords and specific Chinese media sources in ranking, which creates a baked-in source and language bias without any indication of user preference, transparency, or override controls. In a news-summarization skill, this can systematically skew what users see, suppress alternative high-quality sources, and misrepresent coverage as objective selection.

Natural-Language Policy Violations

Medium
Confidence
81% confidence
Finding
The reported output distribution shows 100% dominance by a single Chinese source, normalizing a highly concentrated and non-user-driven editorial bias. In the context of an AI daily briefing skill, this makes the generated report less trustworthy and more susceptible to information narrowing, agenda shaping, and omission of relevant perspectives from other reputable sources.

Natural-Language Policy Violations

Medium
Confidence
92% confidence
Finding
The README says the tool generates a structured Chinese briefing, and the rest of the documentation presents Chinese output as the fixed behavior. There is no indication that users can opt into another language or that the Chinese-only constraint is required for a documented region-specific use case.

Session Persistence

Medium
Category
Rogue Agent
Content
```bash
# 编辑 crontab
crontab -e

# 添加每日 8:00 执行
0 8 * * * cd /home/admin/.openclaw/workspace/skills/ai-daily && bash scripts/generate.sh >> /var/log/ai-daily.log 2>&1
Confidence
85% confidence
Finding
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Session Persistence

Medium
Category
Rogue Agent
Content
```bash
# 编辑 crontab
crontab -e

# 添加每日 8:00 执行
0 8 * * * cd /home/admin/.openclaw/workspace/skills/ai-daily && bash scripts/generate.sh >> /var/log/ai-daily.log 2>&1
Confidence
85% confidence
Finding
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
启用:
```bash
sudo systemctl enable ai-daily.timer
sudo systemctl start ai-daily.timer
```
Confidence
70% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Static analysis

No suspicious patterns detected.