T09 · Insecure Skill Coding Practices
- 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: MediumVulnerable 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 intoAutomationEngine.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_automationimplementation 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_automationpackage 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]- The manifest authorizes network access to every domain through
- Remediation
View remediation
Remediation Suggestions
-
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.
- Replace
-
Validate parsed destinations
- Permit only
httpandhttps. - Reject URLs containing embedded credentials or malformed hostnames.
- Restrict ports to those required by the skill.
- Normalize hostnames before applying policy.
- Permit only
-
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.
-
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.
-
Harden input controls
- Add a reasonable
maxLengthconstraint to thequeryproperty. - 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.
- Add a reasonable
-
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.
-
