Back to skill

Security audit

Openclaw Web Automation

Security checks for vulnerabilities and agentic risk

Overview

The skill appears to be a public webpage automation helper, but it does not enforce its stated public-site-only network boundary.

Review this skill before installing if your runtime can reach internal services. It should be used only in an environment where unrestricted outbound requests are acceptable, or after adding validation that allows only http/https public destinations and blocks localhost, private IP ranges, link-local metadata endpoints, unsafe redirects, and unexpected automation scripts.

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
manifest.json:9
Finding

Unrestricted Network Scope Without Public-Address Validation

Content
View full analysis

Vulnerability Details

File Location: manifest.json:9-12
Related Locations: runner.py:16-24, schemas/input.json:5-10
Vulnerability Type: Server-Side Request Forgery (SSRF) / Missing Network-Destination Validation
Risk Level: Medium

Vulnerable Code

manifest.json:9-12:

json
"permissions": {
  "browser": false,
  "network_domains": ["*"]
}

runner.py:16-24:

python
query = str(inputs.get("query", ""))
if not query:
    return {"ok": False, "error": "missing 'query' in inputs"}

parsed = parse_query_to_run(query)
engine = AutomationEngine(_REPO_ROOT)
script_dir = resolve_script_dir(_REPO_ROOT, parsed.script_dir)

result = engine.run(script_dir, parsed.inputs)

schemas/input.json:5-10:

json
"properties": {
  "query": {
    "type": "string",
    "description": "Natural-language request, e.g. 'check yahoo.com for the word finance'"
  }
}

Technical Analysis

The skill documentation limits its operation to public websites, but this boundary is not enforced by the supplied implementation:

  • The manifest authorizes network access to every domain through network_domains: ["*"].
  • The input schema accepts an unrestricted natural-language string.
  • The runner passes the query through parse_query_to_run() and into AutomationEngine.run() without validating the resulting URL, scheme, hostname, resolved IP address, port, or redirects.
  • There are no explicit controls rejecting loopback, private, link-local, reserved, multicast, or cloud-metadata destinations.

This creates a potential SSRF or confused-deputy condition if the delegated openclaw_automation implementation accepts arbitrary URLs. An attacker may be able to make the runtime issue requests to services that are inaccessible from the attacker's own network position.

The external openclaw_automation package was not included in the reviewed project, so its internal protections could not be verified. The finding is therefore based on the absence ...[truncated 1479 chars]

Remediation
View remediation

Remediation Suggestions

  1. Restrict network permissions

    • Replace network_domains: ["*"] with the narrowest practical domain allowlist.
    • If arbitrary public websites are a functional requirement, enforce a dedicated public-internet egress policy rather than unrestricted destination access.
  2. Validate parsed destinations

    • Permit only http and https.
    • Reject URLs containing embedded credentials or malformed hostnames.
    • Restrict ports to those required by the skill.
    • Normalize hostnames before applying policy.
  3. Validate resolved addresses

    • Resolve every hostname and reject loopback, private, link-local, multicast, unspecified, reserved, and other non-public address ranges for both IPv4 and IPv6.
    • Explicitly deny known cloud metadata destinations.
    • Perform this enforcement in the network request layer rather than relying solely on natural-language parsing.
  4. Secure redirects and DNS handling

    • Revalidate the destination after every redirect.
    • Limit redirect depth.
    • Pin validated DNS resolutions where supported or otherwise mitigate DNS rebinding and time-of-check/time-of-use inconsistencies.
  5. Harden input controls

    • Add a reasonable maxLength constraint to the query property.
    • Prefer extracting a structured URL field and validating it against a strict schema before execution.
    • Reject requests that cannot be unambiguously classified as public-site operations.
  6. Add security tests

    • Test loopback, RFC 1918, link-local, IPv6-local, integer/hexadecimal IP representations, redirect chains, user-information URL syntax, alternate ports, and DNS-rebinding scenarios.
    • Verify that all such requests fail before any network connection is made.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • 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
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (4)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
87% confidence
Finding

The skill invokes a local Python script via a shell command, but the manifest does not declare any explicit tool or permission boundaries. That mismatch increases the risk that an agent may execute shell or environment-capable actions without clear scoping, review, or policy enforcement, especially because the command embeds user-controlled query text.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The manifest describes a narrowly scoped capability—fetching public pages and extracting summaries or keywords—but grants network access to all domains via a wildcard. This violates least privilege and creates unnecessary attack surface: if the runner or downstream logic is abused, compromised, or later expanded, it could contact arbitrary endpoints rather than only the intended public targets.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
86% confidence
Finding

The runner accepts an unrestricted natural-language query, converts it into a structured automation request, and immediately executes it via the automation engine. In a skill specifically designed for web automation, this creates a prompt-to-action path where ambiguous or adversarial user input can trigger unintended browsing or data retrieval behavior without an explicit confirmation, policy gate, or user-facing disclosure.

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

python
"--query",
        args.query,
    ]
    proc = subprocess.run(cmd, cwd=root, capture_output=True, text=True)
    if proc.returncode != 0:
        print(proc.stderr.strip() or proc.stdout.strip())
        return proc.returncode

Static analysis

No suspicious patterns detected.