T09 · Insecure Skill Coding Practices
Error
- Location
- SKILL.md:96
- Finding
- Unrestricted Target URL Enables Server-Side Request Forgery<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:96-106` **Vulnerability Type**: Unrestricted outbound request / SSRF **Risk Level**: High ### Vulnerable Code ```python def probe_cors(url: str, origin: str, method: str = 'GET') -> dict: """Send a single CORS probe and return response headers.""" result = subprocess.run( ['curl', '-sI', '-X', method, url, '-H', f'Origin: {origin}', '-H', 'Content-Type: application/json', '--max-time', '10', '--user-agent', 'CorsAuditor/1.0'], capture_output=True, text=True ) ``` ### Technical Analysis The user-controlled `url` is passed directly to `curl` without validating its scheme, hostname, port, resolved IP address, or network destination. The skill explicitly advertises support for probing any supplied URL. Using an argument array prevents conventional shell metacharacter injection, but it does not prevent server-side request forgery. An attacker can supply URLs targeting loopback interfaces, private address ranges, link-local services, cloud metadata endpoints, or internal hostnames accessible from the agent's execution environment. The code also does not explicitly restrict curl to HTTP and HTTPS protocols. Although the `-I` option limits normal HTTP probes to response headers, those headers can still disclose internal software, service availability, authentication behavior, routing information, and CORS configuration. ### Attack Path 1. An attacker persuades a user or automated agent to audit an attacker-selected target. 2. The attacker supplies an internal URL, such as a loopback address, private service hostname, or link-local metadata endpoint. 3. `probe_cors()` passes the URL directly to `curl`. 4. The request originates from the environment running the skill rather than from the attacker. 5. The internal service's status code and response headers are parsed and included in the audit result. 6. The attacker uses the results for in ...[truncated 655 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions - Accept only `http` and `https` URLs. - Reject URLs containing embedded credentials. - Resolve the hostname before connecting and reject loopback, private, link-local, multicast, unspecified, and reserved IPv4 and IPv6 addresses. - Revalidate the destination immediately before connection to reduce DNS-rebinding risk. - Explicitly restrict curl protocols, for example with `--proto =http,https`. - Keep redirects disabled. If redirects are later enabled, validate every redirect destination using the same policy. - Apply an outbound network allowlist or egress firewall so the process cannot reach metadata services or private networks. - Require explicit user confirmation before probing a destination outside an approved domain list. - Place an option terminator before the URL and use a validated canonical URL as the final positional argument. ]]>
