T09 · Insecure Skill Coding Practices
- Location
scripts/route.py:194- Finding
Caller-Controlled Endpoint Permits Cleartext Intent Disclosure and Limited SSRF
- Content
View full analysis
Vulnerability Details
File Location:
scripts/route.py, lines 83, 194–195, and 230–231
Vulnerability Type: Arbitrary outbound HTTP(S) destination with insufficient transport and destination validation
Risk Level: MediumVulnerable Code
python with urllib.request.urlopen(request, timeout=timeout) as response: # noqa: S310 - fixed https endpoint status = response.status raw = response.read(MAX_RESPONSE_BYTES + 1)python parser.add_argument( "--endpoint", default=DEFAULT_ENDPOINT, help=f"handshake endpoint (default: {DEFAULT_ENDPOINT})", )python if not args.endpoint.startswith(("http://", "https://")): return fail("--endpoint must be an http(s) URL", EXIT_USAGE)The caller-controlled value is subsequently passed to the network function:
python status, payload = post_handshake(args.endpoint, intent, args.timeout)Inside
post_handshake(), the complete intent is serialized and sent to that endpoint:python body = json.dumps({"intent": intent}).encode("utf-8") request = urllib.request.Request( endpoint, data=body, method="POST", headers={ "Content-Type": "application/json", "Accept": "application/json", "User-Agent": USER_AGENT, }, )Technical Analysis
The Skill declares a fixed OracleNet handshake endpoint at
https://tooloracle.io/handshake. However,route.pyexposes an unrestricted--endpointoption and accepts both HTTPS and cleartext HTTP URLs.This creates two related security issues:
- Intent disclosure: The complete natural-language intent is posted to the selected destination. An HTTP destination exposes it to network interception, while an attacker-controlled HTTPS destination receives it directly.
- Limited server-side request forgery: A caller can direct the script to issue an HTTP POST from the agent's network context to l ...[truncated 2806 chars]
- Remediation
View remediation
Remediation Suggestions
-
Remove endpoint customization from the production client if it is not required:
python endpoint = DEFAULT_ENDPOINT -
Require the exact expected HTTPS origin and path:
python from urllib.parse import urlsplit parsed = urlsplit(args.endpoint) if ( parsed.scheme != "https" or parsed.hostname != "tooloracle.io" or parsed.port not in (None, 443) or parsed.path != "/handshake" or parsed.username is not None or parsed.password is not None ): return fail("endpoint must be https://tooloracle.io/handshake", EXIT_USAGE) -
If custom endpoints are an intentional development feature, place them behind an explicitly named option such as
--allow-custom-endpoint, require interactive or principal confirmation, and display a warning that the complete intent will leave the system. -
Reject loopback, private, link-local, multicast, reserved, and unspecified IP address ranges after DNS resolution. Revalidate every resolved address immediately before connection to reduce DNS-rebinding risk.
-
Disable redirects or validate every redirect target. In particular, reject HTTPS-to-HTTP redirects and redirects outside the approved origin.
-
Never permit cleartext HTTP for intents. Enforce
httpsrather than merely checking for eitherhttp://orhttps://. -
Update the source annotation so it accurately reflects endpoint policy. The existing “fixed https endpoint” comment should only remain if the endpoint is actually fixed and HTTPS-only.
-
Preserve the existing secret scanner as defense in depth, but clearly state that it is not a privacy filter. Require callers to submit only a minimal routing summary with sensitive identifiers removed.
-
