T05 · Unauthorized Access and Privilege Escalation
Error
- Location
- scripts/cliento.py:18
- Finding
- Unrestricted URL Fetching Enables SSRF and Local File Disclosure## Vulnerability Details **File Location**: `scripts/cliento.py:18-36` **Vulnerability Type**: Server-Side Request Forgery and unrestricted local resource access **Risk Level**: High ### Vulnerable Code ```python def request(url, payload=None, method="GET"): req = urllib.request.Request(url, method=method) if payload: req.add_header('Content-Type', 'application/json') data = json.dumps(payload).encode('utf-8') else: data = None try: with urllib.request.urlopen(req, data=data) as response: return response.read().decode('utf-8') except urllib.error.URLError as e: if hasattr(e, 'read'): return e.read().decode('utf-8') return str(e) def register(url): html = request(url) print(html) # Raw html output for the agent to parse ``` The associated workflow in `SKILL.md:22-24` passes a user-provided URL to this function: ```markdown When the user provides a Cliento URL to register: 1. Verify the URL is safe, then fetch the raw HTML by executing `python3 scripts/cliento.py register <URL>`. 2. Parse the embedded Next.js JSON (inside `<script id="__NEXT_DATA__" type="application/json">`) to extract the Company ID, available services, and barbers. ``` ### Technical Analysis The `register` command passes an externally supplied URL directly to `urllib.request.urlopen` without enforcing an allowed scheme, hostname, port, resolved address, or redirect destination. The documentation asks the agent to verify safety, but the executable security boundary does not perform that validation. Depending on the handlers enabled by Python's `urllib`, this can permit both HTTP requests to internal services and retrieval of non-HTTP resources such as `file:` URLs. Automatic HTTP redirects also create a validation-bypass risk if only the initial URL is inspected outside the script. The response body is returned ...[truncated 1134 chars]
- Remediation
- ## Remediation Suggestions - Enforce an explicit allowlist of required HTTPS Cliento hostnames inside `cliento.py`. - Reject all schemes other than HTTPS, including `file`, `ftp`, and `data`. - Reject URLs containing user information, custom ports, or other unnecessary components. - Resolve the hostname before connecting and reject loopback, private, link-local, multicast, unspecified, and reserved IP ranges for both IPv4 and IPv6. - Disable automatic redirects or validate the scheme, hostname, port, and resolved destination at every redirect hop. - Consider DNS rebinding protections by connecting only to the validated address while preserving the expected TLS hostname. - Add connection/read timeouts and strict response-size limits. - Return a clear validation error rather than relying on agent-side inspection. - Add tests for local-file URLs, localhost, private addresses, IPv6 literals, encoded hostnames, alternate ports, and redirect-based bypasses.
