Back to skill

Security audit

Content Claw

Security checks for vulnerabilities and agentic risk

Overview

This is a coherent content-generation skill, but it needs review because it can use social-media session cookies, automate Reddit/X activity, fetch arbitrary URLs, and lacks strong containment around paths and browser execution.

Install only if you are comfortable with a skill that can browse external pages, send prompts/specs to Exa and fal.ai, and optionally use Reddit/X cookies to act through your accounts. Use dedicated low-privilege API keys, avoid internal or sensitive URLs, do not provide browser cookies unless you need publishing/tracking, and run it in a sandboxed environment until URL, path, dependency, and browser-sandbox hardening are added.

Vulnerability Patterns
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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
Findings (6)

T03 · Remote Payload Retrieval and Execution

Error
Location
SKILL.md:53
Finding

Remote installer is executed without integrity verification

Content
View full analysis
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/extractors/extract.py:17
Finding

Unvalidated source URLs permit server-side request forgery and local resource access

Content
View full analysis
str: """Fetch a page's HTML using Playwright with stealth settings.""" from playwright.sync_api import sync_playwright with sync_playwright() as p: browser = p.chromium.launch( headless=True, args=[ "--disable-blink-features=AutomationControlled", "--no-sandbox", ], ) context = browser.new_context( user_agent="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36", viewport={"width": 1280, "height": 800}, locale="en-US", ) page = context.new_page() page.add_init_script("Object.defineProperty(navigator, 'webdriver', {get: () => undefined})") page.goto(url, wait_until="domcontentloaded", timeout=30000) ``` ```python resp = httpx.get( url, follow_redirects=True, timeout=60, headers={ "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36", }, ) resp.raise_for_status() ``` ```python url = sys.argv[1] source_type = detect_type(url) extractors = { "web": extract_web, "pdf": extract_pdf, "reddit": extract_reddit, "twitter": extract_twitter, "github": extract_github, } extractor = extractors.get(source_type) ``` ### Technical Analysis The extractor accepts a caller-controlled URL and passes it directly to Playwright or `httpx`. It does not enforce an `http`/`https` scheme, validate the resolved address, restrict ports, or reject loopback, private, link-local, reserved, and cloud metadata destinations. The PDF path also enables red ...[truncated 1498 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/extractors/extract.py:21
Finding

Chromium processes untrusted web content with the browser sandbox disabled

Content
View full analysis
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
scripts/discover_topics.py:42
Finding

Caller-controlled filesystem paths are not constrained to the declared project directory

Content
View full analysis
dict: """Load all YAML files from a brand graph directory.""" import yaml brand_path = Path(brand_dir) graph = {} for f in brand_path.glob("*.yaml"): with open(f) as fh: data = yaml.safe_load(fh) if data: graph[f.stem] = data return graph ``` ```python brand_dir = sys.argv[1] reddit_cookie = None x_cookie = None ``` Equivalent unrestricted path handling appears in the publisher: ```python def load_run_metadata(content_dir: str) -> dict: """Load run metadata and content files from a run directory.""" path = Path(content_dir) metadata = {} meta_file = path / "metadata.json" if meta_file.exists(): metadata = json.loads(meta_file.read_text()) text_files = list(path.glob("*.md")) spec_files = list(path.glob("*-spec.json")) image_files = list(path.glob("*.png")) + list(path.glob("*.jpg")) ``` Cookie paths are also caller controlled: ```python cookies = json.loads(Path(cookie_path).read_text()) context.add_cookies(cookies) ``` The engagement tracker can write to an unrestricted brand directory: ```python feedback_path = Path(brand_dir) / "feedback.yaml" with open(feedback_path, "w") as f: yaml.dump(feedback, f, default_flow_style=False) ``` ### Technical Analysis The documentation declares that the Skill only accesses files under `BASE_DIR`, but the scripts accept absolute paths and traversal paths without resolving and validating them against that root. The scripts can consequently read Markdown, JSON, YAML, image metadata, and cookie files outside the project. The publisher can w ...[truncated 1290 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/extractors/extract.py:88
Finding

Downloaded PDF files are left behind in the system temporary directory

Content
View full analysis
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
pyproject.toml:6
Finding

Floating dependency constraints permit unreviewed future package versions

Content
View full analysis
=0.27", "pymupdf>=1.24", "readabilipy>=0.2", "playwright>=1.49", "fal-client>=0.5", "exa-py>=1.0", ] [dependency-groups] dev = [ "pytest>=8.0", "pyyaml>=6.0", ] ``` The installation instructions invoke dependency resolution directly: ```markdown After installing uv, run `uv sync` in the skill directory to install all Python dependencies. ``` ### Technical Analysis All dependencies use minimum-only version constraints. A future release satisfying the `>=` constraint can therefore be selected even though that version was not included in this audit. No lock file or hash-pinned dependency set was present in the audited project structure. This makes installation non-reproducible and expands the supply-chain trust boundary to all future compatible releases of every dependency and their transitive dependencies. ### Attack Path 1. A dependency maintainer account, package release process, or package index entry is compromised. 2. A malicious or compromised package version is published with a version satisfying the declared lower bound. 3. A user runs `uv sync` without an audited lock file. 4. The resolver selects and installs the newer package. 5. Package installation or later imports execute attacker-controlled code with the Skill process's privileges. ### Impact Assessment A compromised dependency can execute Python code in the Skill environment and access files, environment variables, API keys, and authentication material available to the process. The exact impact depends on the compromised package and execution context. The audit found no evidence that the currently named packages are intentionally malicious; the issue is the absence of reproducible, reviewed dependency r ...[truncated 14 chars]
Remediation
View remediation
Vulnerability Patterns
  • 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
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
Findings (65)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The declared description presents a content generation skill that converts input materials such as URLs, papers, podcasts, Reddit threads, or GitHub repos into publishable content assets. The supplied code does something materially different: it autonomously discovers trending topics relevant to a brand by querying Exa and scraping Reddit/X, then ranks them for relevance. This is not just a supporting component of generation; it is a separate primary capability focused on research and trend discovery. The code also accesses external web platforms through Playwright and can load cookie files for Reddit/X sessions, which are significant undeclared behaviors. While EXA_API_KEY is mentioned in the description, FAL_KEY is not used here, and no content generation or transformation logic appears in this chunk. Therefore the description does not accurately represent the actual behavior.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared description presents this skill as an automated content generation system whose primary function is transforming source material into finished content artifacts. The supplied code instead implements only a source extraction utility: it routes URLs by type, fetches/render pages, extracts readable text or README/PR/PDF text, and returns structured JSON. While extraction could be a supporting component in a broader content-generation pipeline, this chunk’s actual primary purpose is materially different from the declared purpose. The description also mentions image generation, topic discovery, recipes, and brand graphs, none of which appear in the code.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The description presents a full content-generation pipeline capable of turning many kinds of source material into multiple content formats, including text outputs and image outputs. The supplied code chunk only implements one supporting subcomponent: image generation via fal.ai from an already prepared spec or prompt. It uses FAL_KEY, but there is no evidence of source-material ingestion, topic discovery, recipe/brand-graph orchestration, or generation of non-image content. This is a material scope mismatch in primary purpose and supported capabilities, even though infographics/diagrams are partially aligned.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared description emphasizes automated content generation from inputs like papers, podcasts, Reddit threads, and GitHub repos, with recipes/brand graphs and dependencies on FAL_KEY and EXA_API_KEY. The supplied code does not generate or transform source material at all. Its primary purpose is materially different: publishing existing content from a local directory to Reddit or X/Twitter via Playwright using authenticated session cookies, while modifying links with UTM tags and recording publication metadata. These are significant undeclared capabilities and a different workflow, so this is a clear description-behavior mismatch.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared description presents this skill as an automated content generation engine for creating posts and media from source material. The supplied code chunk does not generate content at all. Its primary function is post-publication analytics: it scrapes Reddit and X engagement metrics, processes publish records, and writes feedback data. That is a materially different purpose from content creation. The code also accesses external social platforms through Playwright and optional cookie files, which is not reflected in the declared description. While the broader product wording mentions brand graphs, this script specifically implements engagement tracking and feedback updates, not content generation, so the description does not accurately represent the actual behavior.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

This is a clear description-behavior mismatch. The description promises a content generation pipeline that converts source material into platform-ready content and references brand graphs, recipes, and image/topic APIs. The actual code chunk contains only tests for an extractor script: it invokes a subprocess, classifies URLs by type, validates extracted text/title/word count, and checks truncation and error JSON behavior. While source extraction could be a supporting component of a larger content-generation system, this specific code chunk does not perform generation or anything close to the declared primary purpose. Therefore the declared description does not accurately represent what this code actually does.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared description presents a runtime content-generation skill, but the supplied code only contains unit tests for validating YAML recipe metadata and file references. It does not generate posts, summaries, diagrams, or any platform-ready content, nor does it ingest external source material or call external services/APIs. While the test code references concepts like recipes and brand_graph, that is only schema validation support and not the declared primary capability. This is a clear description-behavior mismatch.

Content

No source excerpt is available for this finding.

Vague Triggers

High
Category
Not specified by scanner
Confidence
96% confidence
Finding

The trigger language is extremely broad and can match generic requests like 'make a post from this' or 'turn this into content,' causing the skill to activate in contexts where users did not intend scraping, external API use, or credential-backed actions. Over-broad activation increases the chance of unnecessary data processing, unexpected tool invocation, and user surprise around external side effects.

Content

No source excerpt is available for this finding.

Self-Modification

High
Category
Rogue Agent
Confidence
96% confidence
Finding

This task explicitly plans for the skill to write or define its own SKILL.md, which is a self-modification capability affecting the agent's instruction set. In agent systems, allowing a skill to author or rewrite the instructions that govern future behavior can enable persistence, privilege escalation, safety bypasses, or insertion of adversarial directives, especially because SKILL.md is described here as 'the instruction set that makes the OpenClaw agent a content engine.'

Content

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

md
- **Effort:** S
- **Blocked by:** Recipe YAML schema.

### Write SKILL.md (core skill definition)
- **What:** Write the OpenClaw SKILL.md that teaches the agent the full Content Claw pipeline: recipe execution, brand graph wizard, recipe listing, error handling, all user commands.
- **Why:** This IS the product. The SKILL.md is the instruction set that makes the OpenClaw agent a content engine.
- **Effort:** M

Lp1

High
Category
MCP Least Privilege
Confidence
82% confidence
Finding

The script reads secrets from a local .env file and uses them to access external services, which is a real sensitive capability. If the skill manifest does not explicitly declare environment/secret access, users and hosting systems may not understand that the skill consumes credentials, creating a permission transparency and least-privilege issue.

Content

No source excerpt is available for this finding.

Lp1

High
Category
MCP Least Privilege
Confidence
95% confidence
Finding

This extractor performs broad outbound network access to arbitrary user-supplied URLs via Playwright and httpx, but the finding indicates that capability is not declared in the skill's permissions. Undeclared network access is dangerous because it enables fetching untrusted remote content, increases SSRF-style exposure to internal services or cloud metadata endpoints if reachable, and reduces transparency for users and hosting platforms about what the skill can contact.

Content

No source excerpt is available for this finding.

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/discover_topics.py (reported line 13)May include surrounding context.

python
uv run generate_image.py --prompt "description" <output-path>

Environment:
    FAL_KEY - Required. Set in .env file.
"""

import 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 · scripts/discover_topics.py (reported line 24)May include surrounding context.

python
uv run generate_image.py --prompt "description" <output-path>

Environment:
    FAL_KEY - Required. Set in .env file.
"""

import 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 · scripts/generate_image.py (reported line 12)May include surrounding context.

python
uv run generate_image.py --prompt "description" <output-path>

Environment:
    FAL_KEY - Required. Set in .env file.
"""

import 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 · scripts/generate_image.py (reported line 209)May include surrounding context.

python
uv run generate_image.py --prompt "description" <output-path>

Environment:
    FAL_KEY - Required. Set in .env file.
"""

import 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 · scripts/generate_image.py (reported line 249)May include surrounding context.

python
uv run generate_image.py --prompt "description" <output-path>

Environment:
    FAL_KEY - Required. Set in .env file.
"""

import 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 · scripts/publish.py (reported line 27)May include surrounding context.

python
uv run generate_image.py --prompt "description" <output-path>

Environment:
    FAL_KEY - Required. Set in .env file.
"""

import 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 · scripts/track_engagement.py (reported line 22)May include surrounding context.

python
uv run generate_image.py --prompt "description" <output-path>

Environment:
    FAL_KEY - Required. Set in .env file.
"""

import json

Direct Prompt Extraction

High
Category
System Prompt Leakage
Confidence
85% confidence
Finding

Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.

Content

Scanner excerpt · scripts/generate_image.py (reported line 113)May include surrounding context.

python
f"\n\n{content_description}"
        )

    return prompt


FAL_MODELS = {

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The skill metadata frames this tool as a content-generation engine, but this file automates authenticated social-media drafting workflows for Reddit and X. That scope expansion is dangerous because it enables actions on external user accounts using stored session cookies, which materially changes the trust boundary from local content processing to account-affecting browser automation.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The code loads authenticated Reddit cookies from disk and injects them into a Playwright browser context, allowing the script to operate as the user on a third-party platform. In a skill advertised for content generation, this is an unjustified credentialed action surface that could be abused for account misuse, unintended posting, or session theft exposure if cookie files are mishandled.

Content

No source excerpt is available for this finding.

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/discover_topics.py (reported line 26)May include surrounding context.

python
def load_env():
    """Load only declared keys from .env (scoped to FAL_KEY, EXA_API_KEY)."""
    allowed = {"FAL_KEY", "EXA_API_KEY"}
    env_path = Path(__file__).parent.parent / ".env"
    if not env_path.exists():
        return
    for line in env_path.read_text().splitlines():

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/generate_image.py (reported line 251)May include surrounding context.

python
def load_env():
    """Load only declared keys from .env (scoped to FAL_KEY, EXA_API_KEY)."""
    allowed = {"FAL_KEY", "EXA_API_KEY"}
    env_path = Path(__file__).parent.parent / ".env"
    if not env_path.exists():
        return
    for line in env_path.read_text().splitlines():

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/publish.py (reported line 29)May include surrounding context.

python
def load_env():
    """Load only declared keys from .env (scoped to FAL_KEY, EXA_API_KEY)."""
    allowed = {"FAL_KEY", "EXA_API_KEY"}
    env_path = Path(__file__).parent.parent / ".env"
    if not env_path.exists():
        return
    for line in env_path.read_text().splitlines():

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/track_engagement.py (reported line 24)May include surrounding context.

python
def load_env():
    """Load only declared keys from .env (scoped to FAL_KEY, EXA_API_KEY)."""
    allowed = {"FAL_KEY", "EXA_API_KEY"}
    env_path = Path(__file__).parent.parent / ".env"
    if not env_path.exists():
        return
    for line in env_path.read_text().splitlines():

Static analysis

No suspicious patterns detected.