You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Browse filesBrowse the repository at this point in the historyBrowse files
committed
security(url-reader): enforce size limit via streaming body cap (SEC-022)
web_url_read's size limit was advisory only: the HEAD Content-Length preflight
is non-fatal, so a server using chunked encoding, a failing/absent HEAD, or a
GET body larger than its reported Content-Length could make the unbounded
`await response.text()` buffer the whole body into memory (DoS). Read the
response body via a bounded stream that counts decompressed bytes and cancels
the reader once URL_READ_MAX_CONTENT_LENGTH_BYTES is exceeded, returning the
existing content-too-large message before any conversion or cache write. The
same bounded read caps the !response.ok error-body snippet. HEAD preflight is
kept as a cheap early-out; the streaming cap is authoritative.
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Codex <noreply@openai.com>
Copy file name to clipboardExpand all lines: CONFIGURATION.md
+3-1Lines changed: 3 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -57,7 +57,7 @@ Self-hosting SearXNG with JSON output enabled remains the recommended setup. The
57
57
| Variable | Required | Default | Description |
58
58
|---|---|---|---|
59
59
|`URL_READ_MAX_CHARS`| No | — | Default maximum characters returned by `web_url_read` when the caller omits `maxLength`. Explicit `maxLength` always wins. Invalid values are ignored. |
60
-
|`URL_READ_MAX_CONTENT_LENGTH_BYTES`| No |`5242880`| Maximum `Content-Length` allowed by the `web_url_read`HEAD preflight before downloading a page. Invalid values fall back to the default. HEAD failures are non-fatal and the GET proceeds. |
60
+
|`URL_READ_MAX_CONTENT_LENGTH_BYTES`| No |`5242880`| Maximum decompressed response-body bytes `web_url_read`will read while streaming a page. A HEAD `Content-Length` preflight may reject oversized pages before GET, but the streaming cap is authoritative. Invalid values fall back to the default. |
61
61
|`CACHE_TTL_MS`| No |`86400000`| URL cache TTL in milliseconds. Invalid or non-positive values fall back to the default (24 hours). |
62
62
|`CACHE_MAX_ENTRIES`| No |`500`| Maximum number of cached URLs. When the cache exceeds this size, the least frequently used entry is evicted, with oldest entry used as the tie-breaker. Invalid or non-positive values fall back to the default. |
63
63
@@ -129,6 +129,8 @@ For direct URL-reader requests without a proxy, DNS answers are validated before
129
129
130
130
When a URL-reader proxy is configured (`URL_READER_HTTP_PROXY`, `URL_READER_HTTPS_PROXY`, `HTTP_PROXY`, or `HTTPS_PROXY`), the proxy performs DNS resolution. Client-side DNS-answer validation cannot inspect proxied resolutions, so proxied deployments should rely on proxy, firewall, and egress controls.
131
131
132
+
`URL_READ_MAX_CONTENT_LENGTH_BYTES` is enforced while streaming the response body, including chunked responses and responses whose GET body is larger than the HEAD `Content-Length` value. The limit is measured after transparent response decompression.
133
+
132
134
Set `MCP_HTTP_ALLOW_PRIVATE_URLS=true` only when internal URL reads are intentional for your deployment. This also allows hostnames that DNS-resolve to private/internal addresses.
Copy file name to clipboardExpand all lines: SECURITY.md
+4Lines changed: 4 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -94,6 +94,10 @@ The server auto-detects system CA bundles on Linux and macOS for outbound HTTPS
94
94
95
95
The `web_url_read` tool manually follows redirects (up to 5 hops). Each intermediate URL is validated against the private-IP blocklist before the request is made. On the direct no-proxy path, each redirect hop also goes through DNS-answer validation before connecting.
96
96
97
+
### URL Reader Size Limits
98
+
99
+
`web_url_read` enforces `URL_READ_MAX_CONTENT_LENGTH_BYTES` while streaming the response body. The HEAD `Content-Length` check remains as a cheap early rejection path, but the streaming cap is authoritative and also applies when the server omits `Content-Length`, uses chunked transfer encoding, or sends more data than it reported. The cap is measured after undici's transparent Content-Encoding decompression, which bounds the in-memory content size used for HTML-to-Markdown conversion.
0 commit comments