Back to skill

Security audit

Daily News Skill

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent Chinese daily-news broadcaster, but it ships an unsafe script that can turn a configurable news limit into local command execution and encourages persistent scheduled runs with messaging credentials.

Review before installing. Use only a low-privilege account, do not run the cron job as root, protect the config file from untrusted edits, and avoid installing until the news limit is validated and passed to Python as data rather than source code. Store Feishu, NoizAI, and Tavily credentials in protected secret storage, scope the Feishu app narrowly, and confirm the destination chat because scheduled runs can send messages automatically.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/news_broadcast.sh:136
Finding

Arbitrary Python Code Execution Through an Unvalidated News Limit

Content
View full analysis

Vulnerability Details

File Location: scripts/news_broadcast.sh:48-59, 136-145, 174-177
Vulnerability Type: Code injection through dynamic Python source construction
Risk Level: High

Vulnerable Code

bash
while [[ $# -gt 0 ]]; do
    case $1 in
        -c|--config)
            CONFIG_FILE="$2"
            shift 2
            ;;
        -o|--output)
            OUTPUT_TYPE="$2"
            shift 2
            ;;
        --limit)
            NEWS_LIMIT="$2"
            shift 2
            ;;
bash
limit=${limit:-$NEWS_LIMIT}

local news=$(search_news "$category" "$keywords" "$limit")
bash
echo "$result" | python3 -c "
import sys, json
try:
    data = json.load(sys.stdin)
    results = data.get('results', [])
    for i, r in enumerate(results[:$limit], 1):
        title = r.get('title', 'No title')
        content = r.get('content', '')[:200]
        print(f'{i}. {title}')

Technical Analysis

The limit value originates either from the third field of the user-controlled configuration file or from the --limit command-line argument. The script performs no numeric validation before directly interpolating this value into source code passed to python3 -c.

Consequently, limit is treated as a Python expression rather than as data. An attacker able to modify the configuration file or invocation arguments can supply an expression such as:

text
__import__('os').system('id') or 1

This produces an executable expression equivalent to:

python
results[:__import__('os').system('id') or 1]

Python evaluates the injected function call while calculating the slice boundary. The vulnerability is reached when TAVILY_API_KEY is configured and the Tavily request returns a non-empty response.

Attack Path

  1. The attacker gains the ability to modify the news configuration file or influence the arguments passed to the ...[truncated 1407 chars]
Remediation
View remediation

Remediation Suggestions

  1. Validate both command-line and configuration-derived limits as decimal integers:

    bash
    validate_limit() {
        local value="$1"
        if [[ ! "$value" =~ ^[0-9]+$ ]] || (( value < 1 || value > 100 )); then
            echo "Invalid news limit" >&2
            exit 1
        fi
    }
    
    validate_limit "$limit"
    
  2. Never interpolate external values into Python source. Pass the limit as a positional argument:

    bash
    python3 -c '
    import json
    import sys
    
    limit = int(sys.argv[1])
    data = json.load(sys.stdin)
    results = data.get("results", [])
    
    for i, result in enumerate(results[:limit], 1):
        title = result.get("title", "No title")
        content = result.get("content", "")[:200]
        print(f"{i}. {title}")
        print(f"   {content}...")
        print()
    ' "$limit"
    
  3. Apply the same validation immediately after parsing --limit and after reading each configuration row, rather than relying only on validation at the final sink.

  4. Run the scheduled task under a dedicated, unprivileged account with access only to the required configuration and output locations. Do not run it as root.

  5. Protect the configuration file from modification by less-trusted users and avoid exposing API credentials to processes that do not require them.

  6. Add regression tests covering nonnumeric values, Python expressions, negative numbers, excessive limits, missing arguments, and malformed configuration rows.

Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
Findings (23)

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding

The declared purpose understates important external behaviors: sending content to Feishu, relying on third-party APIs, and implying scheduled delivery without documenting the operational model. This is dangerous because users may authorize the skill for news fetching while not realizing it also transmits content and credentials through external integrations, creating consent, privacy, and supply-chain risk.

Content

No source excerpt is available for this finding.

External Script Fetching

High
Category
Supply Chain
Confidence
90% confidence
Finding

Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

Content

Scanner excerpt · scripts/news_broadcast.sh (reported line 126)May include surrounding context.

sh
# 尝试使用 Tavily API
    if [ -n "$TAVILY_API_KEY" ]; then
        local result=$(curl -s "https://api.tavily.com/search" \
          -H "Content-Type: application/json" \
          -d "{
            \"api_key\": \"$TAVILY_API_KEY\",

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The README explicitly advertises automatic internet fetching and scheduled push delivery, but it does not warn users that the skill will transmit data to external services and send outbound messages automatically. In a skill that pulls remote content and pushes it on a schedule, lack of transparency meaningfully increases the risk of unintended data exposure, unexpected network activity, and misuse in environments with restricted egress or messaging policies.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The documentation instructs users to export multiple sensitive credentials, including app secrets and API keys, without any guidance on secure storage, least privilege, rotation, or avoiding shell history/log leakage. This creates a realistic path to credential exposure, especially when users copy commands into shared terminals, commit setup snippets, or run scheduled jobs that may inherit poorly protected environment variables.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
89% confidence
Finding

The skill documents shell execution and automation behavior but does not declare any explicit tool scope or permissions boundary. This is dangerous because users and hosting platforms cannot clearly assess or constrain what commands the skill may run, increasing the chance of unintended command execution, package installation, or persistence-related behavior being approved implicitly.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The skill advertises automatic internet fetching and scheduled pushing but does not clearly warn that it performs recurring outbound network access and automatic message delivery. This is dangerous because users may enable it without understanding that it will continuously contact external sources and send generated content on a schedule, which can create privacy, bandwidth, and policy-compliance issues.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The setup instructions ask users to export multiple sensitive credentials directly in the shell without any guidance on secure storage, rotation, or least-privilege handling. This is dangerous because such secrets can leak via shell history, process inspection, logs, shared environments, or copied setup snippets, potentially enabling unauthorized access to Feishu and third-party APIs.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
85% confidence
Finding

The instructions explicitly direct the user to install a cron job, creating persistent automated execution. Persistence is risky here because the skill performs network fetching and outbound delivery; once scheduled, it can continue running and transmitting data without further user review, especially if the scripts later change or are misconfigured.

Content

Scanner excerpt · SKILL.md (reported line 75)May include surrounding context.

bash scripts/news_broadcast.sh

加入定时任务(每天早上 8 点)

crontab -e 0 8 * * * bash /path/to/news_broadcast.sh

text

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The manifest explicitly requires multiple sensitive credentials and describes automatic internet news aggregation, but it does not disclose to users what external services will receive data, what data may be transmitted, or what trust assumptions apply. In a news-broadcasting skill that fetches remote content and posts/broadcasts results, this creates a real security and privacy transparency gap that can lead to credential misuse, unintended data egress, or unsafe reliance on untrusted content sources.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The file's comments and usage guidance are entirely in Chinese, including the title and scheduling instructions, with no indication that this language choice is optional or region-specific. This creates a natural-language locale policy concern because the skill documentation implicitly requires Chinese comprehension without user opt-in.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
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.

Content

Scanner excerpt · README.md (reported line 43)May include surrounding context.

md
# 定时任务配置示例
# 添加到 crontab: crontab -e

# 每天早上 8 点播报
0 8 * * * bash /root/.openclaw/workspace/skills/daily-news-skill/scripts/news_broadcast.sh >> /tmp/news_broadcast.log 2>&1

Session Persistence

Medium
Category
Rogue Agent
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.

Content

Scanner excerpt · examples/crontab.txt (reported line 2)May include surrounding context.

text
# 定时任务配置示例
# 添加到 crontab: crontab -e

# 每天早上 8 点播报
0 8 * * * bash /root/.openclaw/workspace/skills/daily-news-skill/scripts/news_broadcast.sh >> /tmp/news_broadcast.log 2>&1

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The package description is broad enough that an agent may invoke this skill in situations beyond the user's actual intent, such as general news queries, internet lookup requests, or unsolicited broadcast tasks. Over-broad invocation scope can cause unnecessary web access, unwanted content retrieval, and unexpected audio or messaging behavior, which is a real security and safety issue for agent-integrated skills.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
84% confidence
Finding

The metadata indicates Chinese-language behavior as a built-in characteristic without clarifying that language selection is optional or user-controlled. In agent environments, hard-coded language behavior can lead to misdelivery, inaccessible output, or user-confusing execution when the agent selects the skill for non-Chinese-speaking users.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The script's user-facing help, status messages, date formatting, and broadcast text are written in Chinese and the generated output is hard-coded to Chinese phrasing. There is no option for users to select another language or indication that this skill is intentionally limited to a Chinese-only audience.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
84% confidence
Finding

The script accesses third-party messaging credentials in addition to news-related API keys, and those credentials are not necessary for merely fetching news. In a skill context, collecting extra secrets increases blast radius: compromise, misconfiguration, or repurposing of the script could turn a simple news tool into a channel for unintended outbound messaging.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The skill is presented as a news fetch/broadcast tool, but it requires Feishu messaging credentials and later uses them to deliver outbound content. That expands the trust boundary from local news retrieval into external message delivery, which can surprise users and create privacy or misuse risk if broadcasts are sent without clear consent or destination validation.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The script sends user-configured keywords to an external search service and may send generated broadcast text to messaging/voice services, but it does not provide a clear runtime warning or consent prompt about those disclosures. Even if the data seems low sensitivity, configuration keywords, topics of interest, and generated summaries can reveal private interests or organizational focus.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
76% confidence
Finding

This finding points to the same external Tavily endpoint usage, which exposes search queries and operational metadata to a third-party service. In context, this is functional rather than overtly malicious, but it still creates a data disclosure and dependency risk if users are not informed or if sensitive keywords are used.

Content

Scanner excerpt · scripts/news_broadcast.sh (reported line 126)May include surrounding context.

sh
# 尝试使用 Tavily API
    if [ -n "$TAVILY_API_KEY" ]; then
        local result=$(curl -s "https://api.tavily.com/search" \
          -H "Content-Type: application/json" \
          -d "{
            \"api_key\": \"$TAVILY_API_KEY\",

External Transmission

Medium
Category
Data Exfiltration
Confidence
76% confidence
Finding

This finding points to the same external Tavily endpoint usage, which exposes search queries and operational metadata to a third-party service. In context, this is functional rather than overtly malicious, but it still creates a data disclosure and dependency risk if users are not informed or if sensitive keywords are used.

Content

Scanner excerpt · scripts/news_broadcast.sh (reported line 126)May include surrounding context.

sh
# 尝试使用 Tavily API
    if [ -n "$TAVILY_API_KEY" ]; then
        local result=$(curl -s "https://api.tavily.com/search" \
          -H "Content-Type: application/json" \
          -d "{
            \"api_key\": \"$TAVILY_API_KEY\",

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
82% confidence
Finding

The README content is predominantly in Chinese, including the core usage instructions, and does not indicate that the skill is intentionally region-specific or provide an alternative language option. This can violate language or locale policy where user-facing skills should not force a language without opt-in or justification.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

SQP-3 applies to all file types and covers language or locale policy violations. The natural-language instructions and example broadcast are entirely Chinese, and the skill does not indicate that language is optional, user-selectable, or intentionally limited to a China-specific deployment context.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
81% confidence
Finding

The display name, description, and tags indicate a Chinese-language news broadcast experience, but the manifest does not mention any user language choice or justify a Chinese-only locale restriction. That can conflict with the language/locale policy when a skill implicitly forces a specific language without opt-in.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.