T09 · Insecure Skill Coding Practices
- Location
SKILL.md:240- Finding
Unvalidated API-Provided Download URL Enables Server-Side Request Forgery
- Content
View full analysis
Vulnerability Details
File Location:
SKILL.md:240-242
Vulnerability Type: Unvalidated remote URL / server-side request forgery
Risk Level: Mediumpython pdf = requests.get(result["redacted_file_url"]).content with open("contract_redacted.pdf", "wb") as f: f.write(pdf)Technical Analysis
The example workflow performs an HTTP GET request to
redacted_file_url, whose value is supplied by the remote API. It does not validate the URL scheme, hostname, resolved address, or redirect destinations. Python Requests follows redirects by default.Consequently, a compromised or malicious API response could direct an agent running this workflow to an arbitrary network destination, including loopback, link-local, private-network, or cloud metadata services. The code also omits request timeouts, HTTP status validation, response-size limits, and content-type validation before writing the response to disk.
The fixed output name prevents direct path traversal through the API response, but the code can still overwrite an existing
contract_redacted.pdffile in the working directory.Attack Path
- The agent uploads a legal document and polls the DeepRead API for redaction results.
- The API endpoint, account, or upstream response is compromised or otherwise returns attacker-controlled result data.
- The result reports a completed job and supplies a malicious
redacted_file_url, such as a loopback, private-network, link-local, or attacker-controlled URL. - The agent calls
requests.get()on that URL and follows redirects by default. - The agent accesses the selected network resource and writes its response body to
contract_redacted.pdf.
Impact Assessment
Exploitation could cause the agent host to interact with services that are not directly reachable by the attacker, including internal administrative services or cloud metadata endpoints. This may expose information through observable request behavior or returned content and ...[truncated 442 chars]
- Remediation
View remediation
Remediation Suggestions
- Parse the returned URL and require the
httpsscheme. - Allowlist the exact hostname or hostnames authorized to serve DeepRead output files.
- Disable redirects with
allow_redirects=False, or validate every redirect target before following it. - Resolve the destination and reject loopback, link-local, private, multicast, unspecified, and reserved IP ranges for both IPv4 and IPv6.
- Defend against DNS rebinding by validating the address actually used for the connection, not only an earlier DNS lookup.
- Add explicit connection and read timeouts.
- Call
raise_for_status()before consuming the response. - Stream the response while enforcing a strict maximum size.
- Validate the expected PDF content type and, where appropriate, the file signature.
- Write to a securely created output file and avoid overwriting an existing file without explicit user approval.
- Prefer returning file content through a fixed, authenticated API endpoint rather than accepting an arbitrary URL from job-result data.
- Parse the returned URL and require the
