Oct 8, 2026·6 min read·2 visits
Unauthenticated Server-Side Request Forgery (SSRF) bypass in Docling via DNS Rebinding, URL parsing inconsistencies, and Playwright subresource fetching, allowing internal resource scanning and AWS metadata exfiltration.
An SSRF guard bypass vulnerability in the Docling document conversion engine allows unauthenticated attackers to bypass internal IP access controls. The vulnerability exists due to a DNS rebinding Time-of-Check Time-of-Use (TOCTOU) condition, URL authority parsing inconsistencies, and unvalidated network requests triggered during headless browser page rendering.
The Docling document conversion engine, maintained under the Docling Project, is designed to parse complex document formats like PDF, DOCX, and HTML, converting them into machine-readable structures optimized for LLMs and AI pipelines. When parsing documents, Docling supports downloading remote resources (such as embedded images and assets) and rendering dynamic HTML templates. This network functionality introduces an attack surface that must be strictly isolated to prevent access to the host's internal network infrastructure.
To restrict outgoing connections, Docling implemented safety checks designed to block requests targeting local interfaces, loopback addresses, private networks, and link-local ranges. This validation process was primarily managed by the validate_url_safety utility within the resource loader. However, design flaws within the validation mechanism, structural mismatches in external URL parsers, and unconstrained headless browser subresource loading allowed attackers to bypass these restrictions.
The vulnerability is classified under CWE-918 (Server-Side Request Forgery) and CWE-367 (Time-of-Check to Time-of-Use Race Condition). By exploiting this flaw, attackers can force the server to query internal networks, perform port scanning, interact with unauthenticated local administrative APIs, or access cloud provider metadata endpoints (such as AWS IMDS).
The root cause of this vulnerability lies in the division between the validation step and the connection initialization step, creating three primary exploitation vectors.
The safety guard validate_url_safety resolved the target URL's hostname using Python's standard socket.gethostbyname(). It checked if the resulting IP was a private or restricted address. If the IP was public, validation succeeded. However, when the client connection was subsequently established using the requests library, urllib3 executed an entirely separate DNS resolution request via the operating system's resolver. This gap between the validation (Time-of-Check) and the actual fetch (Time-of-Use) allowed an attacker-controlled DNS nameserver to return a public IP address during the validation phase, and immediately return a private loopback or link-local IP (such as 127.0.0.1 or 169.254.169.254) when the client initiated the TCP handshake.
There was an authority parsing disagreement between Python's built-in urllib.parse module and the HTTP parsing engine within requests/urllib3. For example, a malformed URL incorporating backslashes within the authority section, such as http://127.0.0.1:8080\\@1.1.1.1/, was parsed by urllib.parse as having the host 1.1.1.1 (which is a valid public IP). Conversely, when urllib3 processed the connection, it parsed the authority boundaries differently, stripped the backslashes, and established a direct connection to 127.0.0.1:8080. This allowed malformed input to pass the safety check while still connecting to restricted internal targets.
When Docling rendered dynamic HTML pages using Playwright (Chromium) via HTMLBackendOptions(render_page=True), the browser instance was allowed to query subresources (such as images, stylesheets, and scripts) over active HTTP/HTTPS connections. While static image URLs resolved directly in Python went through validation filters, Playwright's outgoing browser requests were unconstrained. This allowed the browser to establish direct TCP connections to internal endpoints while parsing malicious HTML templates, completely bypassing the Python-based URL validation layer.
To resolve the DNS rebinding window, the maintainers implemented single-resolution pinning. The hostname is resolved exactly once during the validation stage using a wrapper around socket.getaddrinfo. The connection pool is then pinned directly to this validated IP literal, ensuring that no secondary DNS resolution can be performed during the connection phase. For HTTPS connections, server hostname verification and SNI headers are injected manually to preserve TLS authenticity without triggering further lookups.
To prevent the Playwright browser bypass, the browser is placed strictly in offline mode (offline=True). Network request routing is intercept-mapped back to the secure Python adapter using Playwright's interception framework:
# Intercept Playwright requests and route them through the secure Python fetcher
async def _route_request(route: Route) -> None:
url = route.request.url
try:
# Outgoing requests are checked against the exact same single-resolution adapter
response_data = await fetch_remote_with_pinning(url)
await route.fulfill(status=200, body=response_data)
except Exception:
await route.abort("failed")This ensures that all browser-driven subresource lookups undergo the identical strict validation checks applied to standalone image requests, mitigating both DNS rebinding and parser bypass vectors.
An attacker can exploit this vulnerability to extract AWS EC2 or Kubernetes metadata credentials. This attack scenario requires the Docling service to run on an environment where enable_remote_fetch is enabled, and where the host has access to local cloud service endpoints.
The attacker configures a custom nameserver for a domain under their control (e.g., rebind.attacker.test). The DNS daemon is configured to rotate its responses based on query history:
93.184.216.34 (Example public address).169.254.169.254 (AWS IMDSv1 Endpoint).The attacker submits a document payload containing an external resource source designed to trigger a backend retrieve action:
<img src="http://rebind.attacker.test/latest/meta-data/iam/security-credentials/admin-role" />When Docling receives this payload, it calls the validate_url_safety routine, which queries rebind.attacker.test. The DNS server returns the public IP address 93.184.216.34. The validation engine checks this address, determines that it resides in a globally routable range, and passes the validation step.
Immediately following validation, the requests HTTP engine initiates a TCP connection to the same URL. Because urllib3 performs its own host resolution, a second DNS query is sent to rebind.attacker.test. This second response returns 169.254.169.254. The HTTP client establishes a connection to the internal cloud metadata service and retrieves the local IAM role security credentials, exposing them to the execution context.
The security impact of CVE-2026-105743 is assessed as Medium (CVSS 4.0). Under normal configurations, the vulnerability does not lead directly to remote code execution (RCE) on the host machine. However, the exact impact depends on the environment hosting the Docling document conversion engine.
If Docling is deployed in cloud-native environments (such as Amazon Web Services, Google Cloud Platform, or Microsoft Azure), an attacker can fetch instance metadata. This access allows the recovery of temporary identity credentials, potentially facilitating privilege escalation to external cloud infrastructure if permissions are overly permissive.
Additionally, the ability to bypass the internal IP isolation boundaries allows attackers to execute an internal port scan. Host-local databases, key-value stores (such as Redis or Memcached), and microservices running on administrative interfaces (like Kubernetes Kubelet APIs) can be accessed and mapped through blind SSRF vectors or visual rendering techniques.
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:L/I:N/A:N| Product | Affected Versions | Fixed Version |
|---|---|---|
docling docling-project | >= 2.91.0, < 2.132.0 | 2.132.0 |
docling-slim docling-project | >= 2.91.0, < 2.132.0 | 2.132.0 |
| Attribute | Detail |
|---|---|
| Vulnerability ID | CVE-2026-105743 |
| CWE ID | CWE-918 (Server-Side Request Forgery), CWE-367 (TOCTOU) |
| CVSS Base Score | 4.0 (Medium) |
| Attack Vector | Network (AV:N) |
| Attack Complexity | High (AC:H) |
| Exploit Status | Proof of Concept (PoC) |
| CISA KEV Status | Not Listed |
The web application fetches a remote resource without sufficiently validating the destination URI.
Docling, a tool for parsing and processing diverse document formats, is vulnerable to arbitrary file read, arbitrary file write, and potential remote code execution (RCE) in versions 2.94.0 through 2.131.0. The vulnerability occurs when applications configure Docling to use the Tectonic engine for rendering TikZ diagrams into images. Because the compilation did not restrict hazardous TeX primitives or sandbox the environment, an attacker can supply crafted documents containing malicious TikZ definitions to access or modify local files and execute arbitrary commands under the privileges of the processing application.
A technical analysis of CVE-2026-105742 (GHSA-p3fw-7699-7926), a sensitive information disclosure vulnerability in the Docling document processing library. Vulnerable versions of Docling indiscriminately forward custom HTTP headers, such as authentication tokens, to arbitrary third-party origins and during cross-origin redirects while fetching remote image assets from untrusted HTML and EPUB documents.
CVE-2026-106121 is a Denial of Service (DoS) vulnerability in the RabbitMQ Java Client library (amqp-client) affecting versions prior to 5.37.0. The vulnerability resides in the legacy, custom JSON-RPC parsing class com.rabbitmq.tools.json.JSONReader. When parsing malformed or truncated payloads ending within a quoted string or single-line comment, the parser's scanner enters an infinite loop. This occurs because the loop lacks an exit condition for the end-of-input sentinel character returned by the iterator, leading to either CPU exhaustion or a JVM crash from an OutOfMemoryError.
An authenticated Regular Expression Denial of Service (ReDoS) vulnerability in TryGhost Ghost (CMS) versions 4.0.0 through 6.66.x. An attacker with administrator privileges can upload crafted content import archives containing pathological directory names or migration patterns, triggering exponential backtracking in the Node.js V8 engine.
CVE-2026-105645 is a regular expression denial of service (ReDoS) vulnerability affecting Ghost, an open-source Node.js content management system. The vulnerability exists within directory import handlers and the external media inliner, allowing authenticated administrators to trigger catastrophic backtracking in the V8 JavaScript engine, resulting in infinite loops, 100% CPU utilization, and total denial of service.
A Stored Cross-Site Scripting (XSS) and Unrestricted Upload of File with Dangerous Type vulnerability in Ghost CMS (versions 4.0.0 to 6.66.x) allows remote attackers to execute arbitrary JavaScript in the context of an administrator's session. The flaw lies in the content import subsystem, which extracted and stored SVG files without sanitization or binary verification.