Skip to content
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
fix(security): unbounded response body read can lead to memory ex
The HTTP client reads the entire remote body into memory via `response.content` with no maximum size checks. A malicious endpoint can return a very large payload and cause excessive memory usage or process termination (DoS).

Affected files: http.py

Signed-off-by: tuanaiseo <[email protected]>
  • Loading branch information
tuanaiseo committed Apr 2, 2026
commit d49b6106661e082c927bb68230379c49043e1c42
33 changes: 32 additions & 1 deletion feedparser/http.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
";q=0.2,*/*"
";q=0.1"
)
MAX_RESPONSE_BYTES: int = 10 * 1024 * 1024


def get(url: str, result: dict[str, typing.Any]) -> bytes:
Expand All @@ -52,6 +53,7 @@ def get(url: str, result: dict[str, typing.Any]) -> bytes:
url,
headers={"Accept": ACCEPT_HEADER},
timeout=10,
stream=True,
)
except requests.RequestException as exception:
result["bozo"] = True
Expand All @@ -69,6 +71,35 @@ def get(url: str, result: dict[str, typing.Any]) -> bytes:
if modified:
result["modified"] = modified
result["modified_parsed"] = _parse_date(modified)
content_length = result["headers"].get("content-length")
if content_length is not None:
try:
if int(content_length) > MAX_RESPONSE_BYTES:
result["bozo"] = True
result["bozo_exception"] = ValueError("response body exceeds maximum size")
response.close()
return b""
except ValueError:
pass

result["href"] = response.url
result["status"] = response.status_code
return response.content

body = bytearray()
try:
for chunk in response.iter_content(chunk_size=8192):
if not chunk:
continue
body.extend(chunk)
if len(body) > MAX_RESPONSE_BYTES:
result["bozo"] = True
result["bozo_exception"] = ValueError("response body exceeds maximum size")
return b""
except requests.RequestException as exception:
result["bozo"] = True
result["bozo_exception"] = exception
return b""
finally:
response.close()

return bytes(body)