Back to skill

Security audit

Claw News

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly behaves like a news digest tool, but it ships plaintext API keys and exposes the user environment to an unverified helper, so it needs review before installation.

Review before installing. The publisher should remove and rotate the exposed API keys, stop logging key prefixes, pin dependencies, verify or bundle the external MCP helper, pass a minimal environment to subprocesses, restrict custom API endpoints, and add clearer privacy and permission disclosures. If testing anyway, use an isolated environment with your own low-scope keys and do not enable cron or Slack delivery until those issues are fixed.

Vulnerability Patterns
  • Tool Hijacking and SpoofingModifies or replaces tools so legitimate-looking calls execute attacker logic
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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 (7)

T09 · Insecure Skill Coding Practices

Error
Location
test_minimax.py:5
Finding

Hardcoded MiniMax API Credential in Executable Test Script

Content
View full analysis
' url = 'https://api.minimax.chat/v1/text/chatcompletion_v2' headers = { 'Authorization': 'Bearer ' + api_key, 'Content-Type': 'application/json' } payload = { 'model': 'MiniMax-M2.5', 'messages': [ {'role': 'system', 'content': '你是一个新闻搜索助手。请搜索并返回结构化结果。'}, {'role': 'user', 'content': '搜索关于"人工智能"的最新新闻,返回 JSON 格式:标题、URL、摘要、来源'} ], 'tools': [{'type': 'web_search'}], 'temperature': 0.3 } response = requests.post(url, headers=headers, json=payload, timeout=30) ``` The credential value is redacted from this report to avoid further disclosure. The audited file contains the complete plaintext value. ### Technical Analysis An API credential is embedded directly in an executable Python file. Anyone with access to the project archive, source repository, package cache, build artifacts, or source history can recover it without running the program. The script transmits the credential as a bearer token when executed. Although transmission is directed to an HTTPS MiniMax endpoint, embedding the credential in source code violates secret-management boundaries and makes access control dependent on the confidentiality of the entire source tree. ### Attack Path 1. An attacker obtains a copy of the Skill package or repository. 2. The attacker opens `test_minimax.py` and extracts the plaintext API key. 3. The attacker sends authenticated requests to the MiniMax API using that key. 4. Requests consume the victim's quota and may incur charges or access data and capabilities associated with the credential. 5. If the credential was committed to version control, deleting it from the current file does not remove it from repository history. ### Impact Assessment An attacker can impe ...[truncated 505 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/generate_digest.py:9
Finding

Hardcoded Kimi API Credential in Digest Generator

Content
View full analysis
', base_url='https://api.moonshot.cn/v1' ) interests = [ ('🤖 人工智能', ['AI', '大模型', 'AGI', '机器学习']), ('💻 科技动态', ['科技', '互联网', '初创公司', '融资']), ('🚀 马斯克', ['Elon Musk', 'Tesla', 'SpaceX']), ('⛓️ 区块链', ['区块链', '加密货币', 'Web3']) ] for title, keywords in interests: try: query = ' '.join(keywords[:3]) response = client.chat.completions.create( model='kimi-k2-5', messages=[ {'role': 'system', 'content': '你是新闻助手,用中文总结最新新闻。每条新闻用"• 标题 - 摘要"格式,简洁明了。'}, {'role': 'user', 'content': f'搜索"{query}"的最新新闻(过去24小时),列出3-4条最重要的,格式:标题+一句话摘要。'} ], tools=[{'type': 'builtin_function', 'function': {'name': 'web_search'}}], temperature=0.3, timeout=60 ) ``` The credential value is redacted from this report to prevent additional disclosure. The audited source contains the full plaintext value. ### Technical Analysis The digest generator constructs an OpenAI-compatible client with a Kimi credential hardcoded in the program. Executing the script automatically uses this shared credential for multiple web-search requests. The key is not a placeholder and has a live credential format. Source distribution therefore also distributes access to the associated API account. The behavior exceeds least-secret exposure requirements because the Skill already documents environment-variable-based configuration and does not need to ship a credential. ### Attack Path 1. An attacker downloads or receives the Skill package. 2. The attacker extracts the key ...[truncated 601 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
rss/kimi_client.py:67
Finding

Unrestricted Kimi Base URL Can Exfiltrate API Credentials and Input Content

Content
View full analysis
str: kimi_config = config.get('kimi', {}) api_key = kimi_config.get('api_key', '') base_url = kimi_config.get('base_url', 'https://api.moonshot.cn/v1') model = kimi_config.get('model', 'moonshot-v1-8k') if not api_key: raise ValueError("Kimi API key not configured. Set KIMI_API_KEY environment variable.") prompt = create_summary_prompt(title, content, max_words, chinese) headers = { 'Content-Type': 'application/json', 'Authorization': f'Bearer {api_key}' } data = { 'model': model, 'messages': [ {'role': 'system', 'content': '你是一个专业的新闻摘要助手。请生成简洁、准确的新闻摘要。'}, {'role': 'user', 'content': prompt} ], 'max_tokens': max_tokens, 'temperature': temperature } req = urllib.request.Request( f'{base_url}/chat/completions', data=json.dumps(data).encode('utf-8'), headers=headers, method='POST' ) with urllib.request.urlopen(req, timeout=60) as response: result = json.loads(response.read().decode('utf-8')) ``` This path is reached from `rss/rss_summarize.py:230-245` when API summarization is selected. ### Technical Analysis `KIMI_BASE_URL` is accepted from the environment without: - Enforcing HTTPS. - Restricting the destination hostname. - Rejecting loopback or private-network destinations. - Separating cre ...[truncated 1449 chars]
Remediation
View remediation

T07 · Tool Hijacking and Spoofing

Error
Location
scripts/search_engine.py:172
Finding

External MCP Client Executes with the Full Process Environment

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/test_kimi_api.py:28
Finding

Kimi Diagnostic Script Discloses Credential Prefix to Logs

Content
View full analysis
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
requirements.txt:1
Finding

Unpinned Dependencies Permit Unreviewed Future Package Versions

Content
View full analysis
=1.0.0 anthropic>=0.18.0 requests>=2.31.0 python-dateutil>=2.8.0 beautifulsoup4>=4.12.0 ``` The installation command is documented in `SKILL.md:59-60`: ```bash pip install -r requirements.txt ``` ### Technical Analysis Every dependency uses an open-ended lower bound. A future installation may therefore resolve to package versions that did not exist and were not reviewed when the Skill was audited. No lockfile or package hashes are supplied. This is not evidence that the currently named packages are malicious. The vulnerability is the absence of reproducible, integrity-checked dependency resolution. ### Attack Path 1. A dependency account, release process, or package-index delivery path is compromised, or a future release introduces unsafe behavior. 2. The attacker publishes a version satisfying the broad `>=` constraint. 3. A user follows the documented installation command. 4. `pip` resolves and installs the unreviewed version. 5. Malicious or compromised package code executes during installation or later import. ### Impact Assessment Python packages execute with the privileges of the installing or running user. A compromised dependency could read project files and environment secrets, alter generated output, make network requests, or execute arbitrary local code. Actual impact depends on the privileges of the Python environment. ]]>
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
rss/rss_fetcher.py:174
Finding

Default RSS Sources Use Cleartext HTTP Transport

Content
View full analysis
List[Dict]: """Get default news sources.""" return [ {'name': 'techcrunch', 'url': 'https://techcrunch.com/feed/', 'category': 'tech', 'language': 'en'}, {'name': 'the-verge', 'url': 'https://www.theverge.com/rss/index.xml', 'category': 'tech', 'language': 'en'}, {'name': 'ars-technica', 'url': 'http://feeds.arstechnica.com/arstechnica/index', 'category': 'tech', 'language': 'en'}, {'name': 'bbc-tech', 'url': 'http://feeds.bbci.co.uk/news/technology/rss.xml', 'category': 'tech', 'language': 'en'}, {'name': 'bbc-world', 'url': 'http://feeds.bbci.co.uk/news/world/rss.xml', 'category': 'world', 'language': 'en'}, {'name': 'scientific-american', 'url': 'https://www.scientificamerican.com/rss/news.cfm', 'category': 'science', 'language': 'en'}, {'name': 'espn', 'url': 'https://www.espn.com/espn/rss/news', 'category': 'sports', 'language': 'en'}, ] ``` The content is retrieved at `rss/rss_fetcher.py:66-72`: ```python def fetch_feed_requests(url: str, timeout: int = 30) -> str: headers = { 'User-Agent': 'Newsman/1.0 (OpenClaw News Aggregator)' } response = requests.get(url, headers=headers, timeout=timeout) response.raise_for_status() return response.text ``` ### Technical Analysis Several default RSS feeds use plain HTTP. HTTP does not authenticate the origin or protect content integrity. A network-positioned attacker can alter titles, summaries, links, or publication metadata before parsing. Modified content is cached and can be incorporated into generated digests. If API summarization is subsequently used, attacker-controlled feed text is also inserted into an LLM prompt. The audited code does not execute instructions contained in art ...[truncated 978 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Output HandlingUnvalidated Output Injection, Cross-Context Output, Unbounded Output
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
Findings (96)

Tainted flow: 'headers' from os.getenv (line 376, credential/environment) → requests.get (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/search_engine.py (reported line 387)May include surrounding context.

python
"freshness": "day"  # 过去 24 小时
            }
            
            response = requests.get(url, headers=headers, params=params, timeout=self.timeout)
            response.raise_for_status()
            
            data = response.json()

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

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

2. 配置 API Keys

bash
cp .env.example .env
# 编辑 .env 文件,添加你的 API Keys

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

A benign-looking manifest paired with hardcoded credentials, external API usage, and missing promised features is highly risky because it conceals the true security posture of the skill. The combination of deception-by-omission and secret exposure can lead to credential compromise, unreviewed outbound data transfer, and unsafe deployment decisions.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

A benign-looking manifest paired with hardcoded credentials, external API usage, and missing promised features is highly risky because it conceals the true security posture of the skill. The combination of deception-by-omission and secret exposure can lead to credential compromise, unreviewed outbound data transfer, and unsafe deployment decisions.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

A benign-looking manifest paired with hardcoded credentials, external API usage, and missing promised features is highly risky because it conceals the true security posture of the skill. The combination of deception-by-omission and secret exposure can lead to credential compromise, unreviewed outbound data transfer, and unsafe deployment decisions.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

A benign-looking manifest paired with hardcoded credentials, external API usage, and missing promised features is highly risky because it conceals the true security posture of the skill. The combination of deception-by-omission and secret exposure can lead to credential compromise, unreviewed outbound data transfer, and unsafe deployment decisions.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

A benign-looking manifest paired with hardcoded credentials, external API usage, and missing promised features is highly risky because it conceals the true security posture of the skill. The combination of deception-by-omission and secret exposure can lead to credential compromise, unreviewed outbound data transfer, and unsafe deployment decisions.

Content

No source excerpt is available for this finding.

Unvalidated Output Injection

High
Category
Output Handling
Confidence
85% confidence
Finding

Model output is used without validation or sanitization. Unvalidated output injected into downstream contexts (SQL, shell, HTML) enables injection attacks and arbitrary code execution.

Content

Scanner excerpt · references/rss_examples.md (reported line 81)May include surrounding context.

md
)
news = json.loads(result.stdout)

# Generate digest digest_result = subprocess.run(     ['python', 'scripts/digest.py', '--format', 'slack'],
    input=result.stdout, capture_output=True, text=True
)

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

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

md
def _load_dotenv():
    """从 .env 文件加载环境变量"""
    env_file = Path(__file__).parent.parent / ".env"
    if env_file.exists():
        with open(env_file, "r", encoding="utf-8") as f:

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

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

md
def _load_dotenv():
    """从 .env 文件加载环境变量"""
    env_file = Path(__file__).parent.parent / ".env"
    if env_file.exists():
        with open(env_file, "r", encoding="utf-8") as f:

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/config.py (reported line 14)May include surrounding context.

python
def _load_dotenv():
    """从 .env 文件加载环境变量"""
    env_file = Path(__file__).parent.parent / ".env"
    if env_file.exists():
        with open(env_file, "r", encoding="utf-8") as f:

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/test_kimi_api.py (reported line 15)May include surrounding context.

python
def _load_dotenv():
    """从 .env 文件加载环境变量"""
    env_file = Path(__file__).parent.parent / ".env"
    if env_file.exists():
        with open(env_file, "r", encoding="utf-8") as f:

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/config.py (reported line 15)May include surrounding context.

python
def _load_dotenv():
    """从 .env 文件加载环境变量"""
    env_file = Path(__file__).parent.parent / ".env"
    if env_file.exists():
        with open(env_file, "r", encoding="utf-8") as f:
            for line in f:

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/test_kimi_api.py (reported line 16)May include surrounding context.

python
def _load_dotenv():
    """从 .env 文件加载环境变量"""
    env_file = Path(__file__).parent.parent / ".env"
    if env_file.exists():
        with open(env_file, "r", encoding="utf-8") as f:
            for line in f:

Missing User Warnings

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

A live API credential is hard-coded directly in source code, which exposes it to anyone with repository or package access and enables unauthorized use of the third-party account. This can lead to account abuse, unexpected billing, service disruption, and possible access to associated provider-side data or logs.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

该文件实现的是对 Kickstarter 热门众筹项目的抓取、筛选、缓存和报告生成,而清单将技能描述为“每日新闻简报”,聚焦全网新闻搜索、RSS/Atom 订阅、兴趣管理和 AI 摘要。Kickstarter 众筹追踪既不是所述的新闻/RSS获取实现细节,也没有体现与新闻简报目标的直接对应,说明代码能力与技能宣称用途存在明显偏离。

Content

No source excerpt is available for this finding.

Env Variable Harvesting

High
Category
Data Exfiltration
Confidence
90% confidence
Finding

Copying the full parent environment into a child process unnecessarily exposes all ambient secrets and runtime metadata to the external Node/MCP helper. Because that helper is executed from a workspace path and is outside this module's direct control, any compromise or tampering of the helper can harvest unrelated credentials from the inherited environment.

Content

Scanner excerpt · scripts/search_engine.py (reported line 184)May include surrounding context.

python
print("⚠️ MiniMax MCP client 未找到,跳过")
                return []
            
            env = os.environ.copy()
            env["MINIMAX_API_KEY"] = self.config.api_keys['minimax']
            env["MINIMAX_API_HOST"] = "https://api.minimaxi.com"

Missing User Warnings

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

A live-looking API key is hardcoded directly in source code, which exposes the credential to anyone with repository or package access. If valid, an attacker could reuse it for unauthorized API calls, incur charges, access associated account capabilities, and potentially pivot into other systems if the key is reused or linked to broader services.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The skill description and user interaction instructions are written entirely in Chinese, including the example command phrasing for Slack use. Under the policy, language constraints should either be optional or clearly justified; this file does not indicate that the skill is China-specific or that users may choose another language.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding

The skill advertises commands that install dependencies, run Python scripts, access environment variables, perform network requests, and schedule cron jobs, but the manifest does not declare any tool scope or permissions. This creates an authorization and review gap: users and hosting platforms are not clearly informed that the skill can read secrets, write files, access the network, and invoke shell commands.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The description does not warn users that their interests, keywords, and possibly names of tracked people may be transmitted to third-party AI APIs and external RSS/feed providers. This is a privacy and consent problem because seemingly simple briefing requests can leak personal or sensitive research interests to outside services.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

Broad trigger keywords like common words can cause accidental invocation of the skill in unrelated conversations. Unintended activation matters here because the skill may initiate network access, process user interests, or trigger automation without the user clearly intending to engage it.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The manifest omits the documented custom tracker capability for scraping Kickstarter projects, which means reviewers and users are not fully informed about the skill's data-collection behavior. Hidden or under-disclosed scraping functionality is risky because it expands network and content-processing scope beyond the stated purpose.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

This markdown template uses Chinese throughout, including the title, section headings, table labels, and usage hint, with no indication that the skill is region-specific or that users can opt into another language. That creates a natural-language locale policy concern because the file effectively forces a specific language without user choice.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
85% confidence
Finding

This markdown file describes using the Web Search tool and sending a user query to the Claude API, but it does not warn that prompts may be transmitted to external services or that web search involves outbound network activity. Under the markdown-specific SQP-2 criteria, descriptions that omit warnings about privacy or system-impacting behavior should be flagged.

Content

No source excerpt is available for this finding.