T09 · Insecure Skill Coding Practices
- Location
scripts/cache_doc.py:137- Finding
Redirect Validation Bypass and Unbounded Remote Content Caching
- Content
View full analysis
Vulnerability Details
File Location:
scripts/cache_doc.py, lines 137-156
Vulnerability Type: Redirect-based trust-boundary bypass, limited SSRF, cache poisoning, and resource exhaustion
Risk Level: MediumVulnerable Code
python def fetch_html(url: str) -> str: req = urllib.request.Request(url, headers={'User-Agent': USER_AGENT}) with urllib.request.urlopen(req, timeout=20) as resp: charset = resp.headers.get_content_charset() or 'utf-8' return resp.read().decode(charset, errors='replace') def main() -> int: parser = argparse.ArgumentParser(description=DESCRIPTION) parser.add_argument('--url', required=True, help=PATH_HELP) parser.add_argument('--root', default=str(default_root()), help=ROOT_HELP) args = parser.parse_args() parsed = validate_url(args.url) root = Path(args.root).expanduser().resolve() html_body = fetch_html(args.url) extractor = TextExtractor() extractor.feed(html_body)Technical Analysis
validate_url()restricts the initially supplied URL to HTTPS ondocs.openclaw.ai. It also rejects user information, explicit ports, direct IP addresses, query strings, fragments, and path traversal. These are appropriate safeguards for the original request.However,
urllib.request.urlopen()follows HTTP redirects automatically. Only the initial URL is validated; neither intermediate redirect targets nor the final response URL are passed throughvalidate_url(). Consequently, an accepted official documentation URL can redirect to a host outside the allowlist, including an attacker-controlled host or a private-network service.The function also calls
resp.read()without a maximum response size and does not validate the response content type. An unintended endpoint can therefore return an excessively large response or arbitrary content. The response is subsequently converted to text and persistently written ...[truncated 2429 chars]- Remediation
View remediation
Remediation Suggestions
- Disable automatic redirects and process each redirect explicitly.
- Apply
validate_url()to every intermediate and final redirect target. - Require every destination to use HTTPS and exactly match the
docs.openclaw.aiallowlist. - After opening the response, validate
resp.geturl()before reading or caching any content. - Set a small maximum redirect count to prevent redirect loops.
- Read the response incrementally and enforce a strict byte limit. Abort the request if the limit is exceeded.
- Allow only expected textual media types, such as
text/htmland optionallytext/plain. - Reject unsupported or missing content types unless an explicit, documented exception is required.
- Write cache entries atomically through a temporary file that is renamed only after all validation and parsing succeed.
- Mark cached text as untrusted external data and ensure Agents do not interpret instructions embedded in documentation pages as authoritative Skill instructions.
