T09 · Insecure Skill Coding Practices
- Location
scripts/layout_caller.py:50- Finding
Server-Side Request Forgery Through Unrestricted Document URLs
- Content
View full analysis
str: """Download a file from a URL and return its base64 encoding.""" import httpx from lib import _http_timeout_from_env, DEFAULT_TIMEOUT timeout = _http_timeout_from_env("PADDLEOCR_DOC_PARSING_TIMEOUT", float(DEFAULT_TIMEOUT)) with httpx.Client(timeout=timeout) as client: resp = client.get(url) resp.raise_for_status() return base64.b64encode(resp.content).decode("utf-8") ``` The caller passes the user-controlled URL directly to this function: ```python if args.file_url: file_data = _fetch_as_base64(args.file_url) else: file_data = _read_as_base64(args.file_path) ``` ### Technical Analysis The `--file-url` argument is accepted without validating the URL scheme, hostname, destination port, or resolved IP address. The application then performs an HTTP request from the network context of the machine running the skill. An attacker can provide URLs targeting resources that are not directly accessible from the attacker's own network, including: - Loopback services such as `127.0.0.1` - Private network addresses - Link-local services - Cloud instance metadata endpoints - Internal administration or monitoring services The response is loaded into memory, Base64-encoded, and passed to `parse_document()`. When a supported-looking path or an explicit `--file-type` is provided, the downloaded content is subsequently submitted to the configured OCR endpoint. ### Attack Path 1. An attacker persuades the Agent to parse a crafted URL, for example an internal service URL or a cloud metadata URL. 2. The URL is accepted through `--file-url`. 3. `_fetch_as_base64()` makes the request from the Agent host without checking whether the resolved address is private, loopback, link-local, or otherwise ...[truncated 857 chars]- Remediation
View remediation
