SSRF in DocumentProcessingToolkit: agent document/URL tool fetches arbitrary URLs with no filtering
Summary
OWL's DocumentProcessingToolkit exposes an extract_document_content tool that fetches a caller-supplied document path or URL server-side, with no scheme, host, or IP filtering. The tool argument is controlled by the agent's LLM, so untrusted content the agent reads (indirect prompt injection from a web page or search result) can steer it into fetching internal-only services or cloud instance-metadata endpoints, whose response is returned into the agent context. Confirmed against the real toolkit methods: an internal URL was fetched and its body returned.
Details
owl/utils/document_toolkit.py fetches the URL with no validation:
# _is_webpage (~line 153): the only gate
requests.head(url, allow_redirects=True, timeout=10)
# _download_file (~line 271):
requests.get(url, stream=True)
# _extract_webpage_content (~line 259): crawl4ai AsyncWebCrawler.arun(url=...)There is no scheme/host/IP filtering anywhere in the file (no is_global, 127.0.0.1, 169.254, or private-range check). extract_document_content (~line 60) is registered as a FunctionTool on the agents in the shipped examples (examples/run*.py), and document_path is an LLM-chosen argument. The agent system prompt instructs the model to take URLs from web-search results and visit them, so an attacker who controls a page/snippet the agent reads supplies the internal URL (indirect prompt injection).
Impact
An attacker who can influence content the OWL agent reads (a web page, a search result) can drive the extract_document_content tool to fetch internal-only services and cloud instance-metadata endpoints, exfiltrating their contents into the agent context (and onward). This is an indirect-prompt-injection-mediated SSRF: the tool argument is LLM-controlled, and the fetch has no filtering.
Remediation
In _is_webpage, _download_file, and _extract_webpage_content, resolve the URL host and reject loopback, private, link-local, unique-local, and reserved ranges plus cloud-metadata hostnames before any request; enforce an http/https allowlist; and disable or re-validate redirects (pin the validated IP). Treat tool-supplied URLs as untrusted regardless of the agent that produced them.
Source: camel-ai/owl