T09 · Insecure Skill Coding Practices
- Location
scripts/fetch_and_digest.py:35- Finding
Untrusted URLs Can Be Misclassified as High-Credibility Sources
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This skill is a scheduled news digest, but its documented Feishu/QQ delivery does not match the code, which can post to an undocumented WeCom webhook and notify everyone there.
Review before installing. Only use this if you are comfortable with an automatic scheduled script posting digests externally, and verify the actual destination variable WECOM_WEBHOOK_URL before running it. Treat webhook URLs as secrets, remove the default @all behavior unless wanted, and do not rely on the documented Feishu/QQ delivery claims without fixing the implementation.
scripts/fetch_and_digest.py:35Untrusted URLs Can Be Misclassified as High-Credibility Sources
scripts/fetch_and_digest.py:302Notification Configuration Mismatch Can Cause Unexpected WeCom Delivery
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.
"max_results": num_results
}
response = requests.post(TAVILY_API_URL, json=payload, timeout=20)
if response.status_code == 200:
data = response.json()
The webhook destination is taken directly from an environment variable and used as the outbound URL without validation or allowlisting. If an attacker can influence environment configuration, they can redirect the full digest to an arbitrary endpoint, causing unintended data exfiltration and possible SSRF into internal network services.
}
}
response = requests.post(webhook_url, json=payload, timeout=10)
if response.status_code == 200:
result = response.json()
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
# 编辑 .env 文件
notepad "$env:USERPROFILE\.openclaw\.env"
# 添加以下内容(替换为你的飞书机器人 Webhook)
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
# 编辑 .env 文件
notepad "$env:USERPROFILE\.openclaw\.env"
# 添加以下内容(替换为你的飞书机器人 Webhook)
FEISHU_WEBHOOK_URL="https://open.feishu.cn/open-apis/bot/v2/hook/xxxxxx"
A description-behavior mismatch is security-relevant because users may approve the skill based on the stated behavior while the implementation actually sends to different services, gathers broader content, and relies on different sources than claimed. That breaks informed consent and can hide unexpected data flows or operational behavior behind misleading documentation.
The manifest says this skill sends the evening digest to QQ and Feishu, but the only real outbound delivery implemented here is send_to_wecom, which posts to an Enterprise WeChat webhook. send_to_qq is only a placeholder that logs a message and returns success, and there is no Feishu sender at all, so the runtime behavior materially diverges from the stated delivery targets.
The guide instructs users to place a Feishu webhook URL into a shared environment file but does not clearly label it as a secret or warn against exposing it in logs, screenshots, backups, or source control. Feishu bot webhooks often function as bearer-style credentials, so disclosure can let an attacker send arbitrary messages to the configured channel and abuse the bot integration.
The README states that the skill automatically pushes news digests to QQ and Feishu but does not clearly warn users that content will be sent to external messaging platforms. This creates a consent and data-sharing risk because users may trigger or configure the skill without understanding that information leaves the local agent context and is delivered through third-party services.
The skill documents network access and environment-variable use but does not declare any explicit tool scope or permissions boundary. That weakens reviewability and least-privilege enforcement, making it easier for a skill that can send outbound messages and read secrets to do more than users expect.
The skill is designed to automatically transmit generated content to external messaging platforms on a schedule, but the user-facing description does not prominently warn about that external disclosure. Automatic scheduled exfiltration to third-party services increases privacy and operational risk, especially if future prompts or generated summaries include unintended sensitive content.
Documenting a webhook variable without an explicit warning obscures that all included message content will be posted to the configured Feishu bot endpoint, which is an external service boundary. Users may paste internal or sensitive content into a system that forwards it off-platform without realizing the privacy and retention implications.
The top-level docstring states the script uses a Multi-Source-Research skill and integrates Tavily API, multi-source search, and social media monitoring. In practice, multi_source_search only makes a single Tavily API call, and there is no separate implementation for social media monitoring, academic-source retrieval, or other claimed integrations.
The manifest description says the digest references the World Monitor data source, but this file's actual retrieval logic uses Tavily search requests and fallback inline article data. World Monitor only appears as a formatted footer link/string, not as an actual upstream source in the implemented data collection path.
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
# Tavily API configuration
TAVILY_API_KEY = os.environ.get('TAVILYAPIKEY', '')
TAVILY_API_URL = 'https://api.tavily.com/search'
# Multi-Source-Research configuration
MULTI_SOURCE_ENABLED = os.environ.get('MULTI_SOURCE_ENABLED', 'true').lower() == 'true'
This function's docstring explicitly lists social media monitoring, academic sources, and news aggregators as integrated inputs. However, the body only constructs one Tavily search request and processes its results, so the documentation overstates and contradicts the implemented behavior.
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
"max_results": num_results
}
response = requests.post(TAVILY_API_URL, json=payload, timeout=20)
if response.status_code == 200:
data = response.json()
The script forces Chinese-language queries, Chinese formatted digest text, and Shenzhen-specific weather content throughout the generated output. There is no opt-in, configuration, or documented justification for restricting language/locale, which matches the policy concern for forced language or locale behavior.
This code sends the full generated digest to a WeCom webhook via HTTP, which is a network transmission of collected content to an external service. While the module docstring says it "pushes to QQ and Feishu," there is no explicit user warning near the sending logic about outbound transmission, recipient scope, or that message contents will leave the local system.
This code posts the full digest to a destination URL entirely controlled by environment configuration, with no validation of scheme, host, or network location. In a compromised or misconfigured deployment, that allows silent redirection of outbound content to attacker infrastructure or internal services.
}
}
response = requests.post(webhook_url, json=payload, timeout=10)
if response.status_code == 200:
result = response.json()
The natural-language instructions and usage examples are presented exclusively in Chinese, with no indication that other languages are supported or that the user can choose their preferred language. Under the stated policy, forcing a specific language without user opt-in is a natural-language policy concern.
The name, description, title, and sample behavior all indicate a Chinese-language evening digest, but the document does not state that language is configurable or optional. Under the policy, forcing a specific language without user opt-in can be a natural-language policy violation unless the locale constraint is clearly justified.
The script reads WECOM_WEBHOOK_URL from the environment and uses it as a credential-bearing destination for message delivery. Although missing configuration is logged, there is no warning or comment explaining that this value is sensitive and controls external message delivery.