Back to skill

Security audit

Ai Product Monitor

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly does what it says, but its one-click pipeline can automatically browse and screenshot externally supplied links without URL safety checks.

Install or run this only if you trust the configured feeds and are comfortable with it making outbound RSS/search/browser requests and saving results under data/. Run it in a sandbox or with network controls if your environment can reach internal services, and avoid adding untrusted feeds until URL validation or an allowlist is added.

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

Warning
Location
scripts/pipeline.py:146
Finding

Untrusted RSS URLs Can Trigger Server-Side Requests Through Screenshot Capture

Content
View full analysis

Vulnerability Details

File Location: scripts/pipeline.py, lines 146–161 and 258–271
Vulnerability Type: Server-Side Request Forgery (SSRF) through unvalidated browser navigation
Risk Level: Medium

Vulnerable Code

python
link = ""
if link_el is not None:
    link = link_el.attrib.get("href", "") or (link_el.text or "").strip()

pub_date = date_el.text.strip() if date_el is not None and date_el.text else ""
desc = desc_el.text.strip() if desc_el is not None and desc_el.text else ""

if not title or not link:
    continue

# Check if launch-related
text_blob = f"{title} {desc}".lower()
if not any(kw in text_blob for kw in keywords):
    continue

iid = item_id(title, link)
if iid in existing_ids:
    continue

launches.append({
    "id": iid,
    "title": title,
    "url": link,

The stored URL subsequently reaches the browser screenshot command:

python
url = item.get("url", "")
if not url:
    continue

print(f"  Capturing: {item['title'][:60]}")
try:
    # Use OpenClaw browser tool if available
    result = subprocess.run(
        ["openclaw", "browser", "screenshot", "--url", url, "--out", str(out_file)],
        capture_output=True, text=True, timeout=45,
    )
    if result.returncode != 0:
        print(f"    ⚠ Screenshot failed: {result.stderr[:100]}")
except Exception as e:
    print(f"    ⚠ Screenshot error: {e}")

Technical Analysis

RSS entry links are externally controlled. The pipeline stores these links without validating their URL scheme, destination host, resolved IP address, port, or redirect chain. During the screenshot stage, each stored URL is passed directly to the OpenClaw browser.

Although the argument-list form of subprocess.run prevents shell command injection, it does not constrain browser navigation. A malicious or compromised RSS feed can provide a URL targeting a loopback address, private network, link-local service, cloud metadata endpoint, or another resource accessible from the browser's ...[truncated 1846 chars]

Remediation
View remediation

Remediation Suggestions

  1. Accept only explicitly permitted URL schemes, preferably https.
  2. Reject URLs containing embedded credentials, malformed hosts, or unexpected ports.
  3. Resolve destination hostnames before navigation and reject loopback, private, link-local, multicast, reserved, unspecified, and cloud metadata address ranges for both IPv4 and IPv6.
  4. Revalidate the destination after DNS resolution immediately before use to reduce DNS-rebinding risk.
  5. Validate every redirect target rather than validating only the initial URL.
  6. Consider an allowlist of expected product or publisher domains where operationally feasible.
  7. Run screenshot capture in an isolated browser profile without user credentials, cookies, local-file access, or access to the host and private networks.
  8. Apply outbound network controls at the container, sandbox, or firewall layer so application-level validation is not the sole defense.
  9. Record rejected destinations without logging credentials, sensitive query parameters, or other secrets.
  10. Add tests covering loopback, RFC1918, link-local, IPv6-local, alternate IP notation, DNS rebinding, and public-to-private redirects.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (9)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The documented purpose sounds like a benign monitoring workflow, but the implementation reportedly performs undeclared external network access and invokes additional CLI/browser automation capabilities. That mismatch is dangerous because reviewers may approve or run the skill without realizing it can reach arbitrary URLs, automate a browser, or execute external commands, which broadens the attack surface significantly.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding

The skill advertises executable pipeline behavior that reads and writes local files, performs network access, and invokes shell commands, but it declares no explicit tool scope or permissions. This is dangerous because users and enforcement layers cannot accurately evaluate or constrain what resources the skill will access, increasing the risk of unintended data exposure, unreviewed outbound requests, or unsafe command execution.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The search stage invokes an external CLI to perform web searches using launch titles as queries, which transmits data to an outside service and then stores returned snippets in enriched_launches.json. Although the stage prints that it is searching, it does not clearly warn users that data derived from collected items will be sent to an external service.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
85% confidence
Finding

The manifest describes an AI product launch monitoring workflow with RSS monitoring, search, screenshot capture, and trend analysis. While search and screenshoting fit that purpose, implementing them by spawning the external openclaw CLI introduces a general subprocess-execution capability that is not justified by the stated scope and is more powerful than the described workflow itself.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/pipeline.py (reported line 214)May include surrounding context.

python
search_snippet = ""
        try:
            # Use openclaw's web search if available
            result = subprocess.run(
                ["openclaw", "web-search", query, "--count", "3", "--format", "json"],
                capture_output=True, text=True, timeout=30,
            )

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The screenshot stage automatically visits untrusted URLs from external feeds and writes resulting images to disk without guardrails. In this skill context, that is more dangerous because monitoring pipelines process attacker-influenced content at scale, which can be abused for SSRF-like network access, local resource probing, or storage abuse through repeated screenshot generation.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
84% confidence
Finding

The screenshot stage passes feed-derived URLs to an external browser automation CLI, causing the host to actively visit attacker-controlled links. While this is not shell injection, it can enable SSRF-style access to internal services, unexpected local-network browsing, or interaction with dangerous schemes depending on how the downstream 'openclaw browser screenshot' command validates URLs.

Content

Scanner excerpt · scripts/pipeline.py (reported line 263)May include surrounding context.

python
print(f"  Capturing: {item['title'][:60]}")
        try:
            # Use OpenClaw browser tool if available
            result = subprocess.run(
                ["openclaw", "browser", "screenshot", "--url", url, "--out", str(out_file)],
                capture_output=True, text=True, timeout=45,
            )

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
83% confidence
Finding

This markdown file describes a one-click pipeline that fetches data, captures screenshots, and generates reports, with outputs written under data/, but it does not include any user-facing warning about these filesystem changes or external site access. Because SQP-2 applies to markdown files when behaviours may affect user data or system integrity, the absence of any disclosure is a minor but valid finding.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

This code stage performs outbound HTTP requests to configured RSS feed URLs and writes the resulting launch data to raw_launches.json. While there are progress prints, they do not disclose the privacy/data-handling impact of contacting external services and storing fetched content, and the module docstring also does not warn about this behavior.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.