Back to skill

Security audit

clawCat-BRIEF

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent briefing/report generator, but it needs Review because LLM-controlled inputs can drive broad network fetches and file writes without enough containment.

Review before installing or running. Use an isolated workspace and network, avoid exposing sensitive environment variables, pin dependencies, vendor or block remote report assets, and add validation for RSS URLs and output paths before using it on sensitive topics or systems.

Vulnerability Patterns
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (4)

T09 · Insecure Skill Coding Practices

Error
Location
clawcat/adapters/news/rss.py:24
Finding

Planner-Controlled RSS URLs Permit Server-Side Request Forgery

Content
View full analysis
FetchResult: import asyncio config = config or {} feeds = config.get("feeds", DEFAULT_FEEDS) max_per_feed = config.get("max_per_feed", 10) items: list[Item] = [] seen_urls: set[str] = set() for feed_cfg in feeds: url = feed_cfg.get("url", "") label = feed_cfg.get("label", url[:40]) if not url: continue try: parsed = await asyncio.to_thread(feedparser.parse, url) ``` ### Technical Analysis `SourceSelection.config` is an unrestricted dictionary generated by the planner LLM. The fetch node merges this dictionary into the adapter configuration without schema validation. The RSS adapter then passes each supplied URL directly to `feedparser.parse()`. There is no validation of: - The URL scheme - The destination hostname - Resolved IP addresses - Loopback, link-local, private, or reserved address ranges - Cloud instance metadata endpoints - Redirect destinations Although custom RSS ...[truncated 1491 chars]
Remediation
View remediation

T01 · Skill Instruction Hijacking

Warning
Location
clawcat/nodes/summarize.py:72
Finding

Untrusted News Content Is Exposed to Indirect Prompt Injection

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
clawcat/nodes/render.py:71
Finding

Unvalidated Report Type Can Escape the Output Directory

Content
View full analysis
Remediation
View remediation

T03 · Remote Payload Retrieval and Execution

Error
Location
clawcat/templates/base.html:7
Finding

Generated Reports Execute Mutable Third-Party CDN Code and Installation Uses Unpinned Dependencies

Content
View full analysis
@import url('https://fonts.googleapis.com/css2?family=Noto+Sans+SC:wght@400;500;700&display=swap'); ``` ```python # clawcat/nodes/render.py:104-121 from playwright.sync_api import sync_playwright with sync_playwright() as p: browser = p.chromium.launch(channel="chrome") pdf_page = browser.new_page() pdf_page.set_content(html, wait_until="networkidle") pdf_out = output_dir / f"{prefix}_{ts}.pdf" pdf_page.pdf(path=str(pdf_out), format="A4", print_background=True) pdf_path_str = str(pdf_out) logger.info("Exported PDF: %s", pdf_out) pdf_page.close() png_context = browser.new_context( viewport={"width": 390, "height": 800}, device_scale_factor=2, ) png_page = png_context.new_page() png_page.set_content(html, wait_until="networkidle") ``` ```text # requirements.txt:3-28 langchain-openai langgraph instructor pydantic>=2.0 pydantic-settings[yaml] feedparser httpx aiohttp>=3.9 akshare pandas ddgs baidusearch jinja2>=3.1 playwright pyyaml>=6.0 ``` ### Technical Analysis The generated HTML references `https://cdn.tailwindcss.com`, which is a remotely mutable JavaScript payload. Playwright loads the generated HTML with `wait_until="networkidle"`, causing the browser to retrieve and execute that script while report content is present in the page DOM. No Subresource Integrity hash or restrictive Content Security Policy is shown. The effective code executed during rendering can therefore change after the Sk ...[truncated 2199 chars]
Remediation
View remediation
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
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • System Prompt LeakageDirect Leakage, Indirect Extraction, Tool-Based Exfiltration
Findings (83)

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 · PLAN.md (reported line 322)May include surrounding context.

md
"""ClawCat configuration — powered by pydantic-settings.

Loads from: environment variables > .env > config.yaml (descending priority).
"""

from __future__ import annotations

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 147)May include surrounding context.

md
"""ClawCat configuration — powered by pydantic-settings.

Loads from: environment variables > .env > config.yaml (descending priority).
"""

from __future__ import annotations

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 · clawcat/config.py (reported line 3)May include surrounding context.

python
"""ClawCat configuration — powered by pydantic-settings.

Loads from: environment variables > .env > config.yaml (descending priority).
"""

from __future__ import annotations

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 · clawcat/config.py (reported line 81)May include surrounding context.

python
"""ClawCat configuration — powered by pydantic-settings.

Loads from: environment variables > .env > config.yaml (descending priority).
"""

from __future__ import annotations

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 · clawcat/config.py (reported line 56)May include surrounding context.

python
model_config = SettingsConfigDict(
        yaml_file=["config.yaml", "config.local.yaml"],
        yaml_file_encoding="utf-8",
        env_file=".env",
        env_nested_delimiter="__",
        extra="ignore",
    )

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
83% confidence
Finding

The plan explicitly stores prior items and user-related memory across reporting periods, but it does not mention disclosure, consent, retention limits, or deletion controls. Persistent memory can expose behavioral history, interests, or sensitive topics if accessed improperly, and the risk is increased because this system aggregates user requests and source selections over time.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

UserProfile persistence stores preferences such as preferred sources, excluded topics, and tone preferences without any stated user warning or lifecycle controls. Those preferences can reveal political, financial, health, or workplace interests, making silent retention a privacy and compliance risk even if the feature is intended for convenience.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The README advertises automatic selection of external data sources, network fetching, and saving rendered outputs, but does not clearly warn users that running the tool will initiate outbound requests and create local files. In an agent or skill context, this can violate user expectations, leak prompts/topics to third parties, and write artifacts to disk without explicit consent or path transparency.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
84% confidence
Finding

The README presents the skill entirely in Chinese and all usage examples are Chinese prompts, with no indication that other languages are supported or that users may choose their preferred language. This is a natural-language policy concern because it imposes a locale/language expectation without opt-in or justification.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
82% confidence
Finding

整个技能描述、交互提示和示例均默认且仅支持中文表述,没有说明是否允许用户选择其他语言或区域设置。按语言/locale 政策,若技能默认强制单一语言而无用户 opt-in,可能构成自然语言层面的策略违规。

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The skill states it will automatically choose data sources, fetch latest information, analyze it, and generate deliverable HTML reports, but it does not clearly warn the user up front about external network access and file generation side effects. This can undermine informed user consent and lead to unexpected data retrieval, privacy exposure, or creation of artifacts the user did not anticipate.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

该 markdown 文件给出的示例用法包含“做个每日 AI 新闻”“今天 A 股怎么样”“帮我做一份……”等宽泛自然语言表达,缺少更明确的触发边界或限定场景。对于通过自然语言匹配激活的 skill,这类短语容易与普通对话请求重叠,增加非预期调用风险。

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · clawcat/adapters/finance/akshare_macro.py (reported line 30)May include surrounding context.

python
pmi = latest.get("制造业-Loss", latest.get("PMI", ""))
                items.append(Item(
                    title=f"中国制造业PMI: {pmi}",
                    url="https://data.eastmoney.com/cjsj/pmi.html",
                    source="akshare_macro",
                    raw_text=f"日期: {date_val}, PMI: {pmi}",
                    published_at=datetime.now().isoformat(),

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · clawcat/adapters/finance/akshare_macro.py (reported line 47)May include surrounding context.

python
pmi = latest.get("制造业-Loss", latest.get("PMI", ""))
                items.append(Item(
                    title=f"中国制造业PMI: {pmi}",
                    url="https://data.eastmoney.com/cjsj/pmi.html",
                    source="akshare_macro",
                    raw_text=f"日期: {date_val}, PMI: {pmi}",
                    published_at=datetime.now().isoformat(),

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The DuckDuckGo adapter guidance directs users to include both Chinese and English keywords and suggests setting region to 'cn-zh' to prioritize Chinese results, which steers locale behavior rather than offering a neutral or user-selected choice. This is a natural-language locale policy concern because the manifest text prescribes language/region defaults without explicit user opt-in or a documented compliance justification.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The Baidu adapter states that queries should be Chinese keywords, which is a natural-language instruction imposing a specific language choice. While the source itself is China-focused, the file does not explicitly frame this as a user choice or region-specific justification in policy terms, so the instruction reads as a forced locale constraint.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
81% confidence
Finding

The natural-language documentation is entirely in Chinese and describes the adapter as suitable for Chinese search quality and domestic access, but it does not indicate that this locale/language constraint is optional or limited to a region-specific use case. Under the policy, forcing a specific language or locale without opt-in can be a violation.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The top-level docstring and user-facing configuration descriptions are entirely in Chinese, including warnings and parameter explanations. This imposes a specific language on users and maintainers without any opt-in, fallback, or justification that the skill is intended only for a Chinese-speaking or region-specific environment.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · clawcat/adapters/tech/github_trending.py (reported line 61)May include surrounding context.

python
try:
                async with new_client() as client:
                    resp = await client.get(
                        "https://api.github.com/search/repositories",
                        params={"q": q_str, "sort": sort, "order": "desc", "per_page": str(per_query)},
                        headers=headers,
                    )

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The module docstring and argument help present only Chinese example queries, which communicates that the skill is intended to be used in a specific language. Under the policy, locale or language restrictions should be opt-in or clearly justified; this file provides neither an explicit user choice nor a documented regional limitation.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

This code emits a natural-language warning string in Chinese: "数值 {num} 在素材中找不到来源,可能为 LLM 编造". Because the file provides no opt-in, fallback, or documented justification for a Chinese-only user-facing message, it violates the language/locale policy criterion for natural-language policy issues.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The system prompt explicitly instructs the model to "使用中文撰写" (write in Chinese). This imposes a fixed language choice in natural-language instructions, and the file does not show any user opt-in or documented region-specific justification for that locale restriction.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The module documentation states that items without published_at are discarded as part of the freshness guarantee, but the implementation never enforces that check. As a result, undated items bypass the intended freshness filter and may be processed or retained indefinitely, weakening downstream trust in time-based filtering and allowing stale or unbounded content into the pipeline.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The code dynamically imports a module path and executes its fetch() function with no allowlist or validation of what module may be loaded. If an attacker can influence registry.json or selected source configuration, they can cause import-time or function-execution code from arbitrary installed modules to run, which is effectively arbitrary code execution within the agent process.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The system prompt explicitly requires Chinese output and Chinese headings, which imposes a specific language/locale policy on all generated outlines. There is no indication in this file that the user can choose another language or that the Chinese-only constraint is documented as a justified region-specific requirement.

Content

No source excerpt is available for this finding.

Static analysis

Detected: suspicious.exposed_secret_literal, suspicious.install_untrusted_source

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
clawcat/llm.py:18

Install source points to URL shortener or raw IP.

Warn
Code
suspicious.install_untrusted_source
Location
clawcat/adapters/registry.json:180

Install source points to URL shortener or raw IP.

Warn
Code
suspicious.install_untrusted_source
Location
config.yaml:22