Your RSA-2048 keys break in 2030. Find every one of them before attackers do.
💧 Hex
Not in CISA KEV

CVE-2026-49755 — req

Fix: wojtekmach/req@84977e5

CVE-2026-49755 is a CWE-409 vulnerability in req. A fix is available for req — see the affected versions and patch details below.

Decompression bomb DoS in Req via auto-decoded archive and compressed response bodies

Also known asEEF-CVE-2026-49755GHSA-655f-mp8p-96gv
Published
Jun 8, 2026
Updated
Aug 20, 2026
Affected
1 pkg
Patched
1 / 1
Exploits
None indexed
Exploitation data as of Sep 28, 2026 · OSV.dev, NVD, FIRST.org (EPSS)

Exploitation Status

Proof-of-concept exploit code exists

  • CISA’s SSVC triage found public proof-of-concept exploit code for this CVE, though no confirmed active exploitation.

Exploitation and automatability from CISA’s SSVC triage for CVE-2026-49755.

EPSS Exploitation Probability

via FIRST.org ↗
0.7%probability of exploitation in next 30 days
Lower Risk0.00%
Lower risk than most CVEs51th percentile — riskier than 51% of all scored CVEsHighest risk

Probability of exploitation in the next 30 days, from FIRST.org EPSS.

Real-World Exposure

1 pkg affected
💧req

Real-time download stats are indexed for npm and PyPI packages. This vulnerability affects Hex packages — download data is not available via public APIs for these ecosystems.

Description

Summary

Req's default response pipeline auto-decodes archive and compressed bodies based on the server-supplied content-type (or URL extension) and materialises the full decompressed contents in memory with no size cap. An attacker who controls (or can redirect a victim into) an HTTP endpoint reached by Req.get!/1 can return a tiny "decompression bomb" that expands to many gigabytes on the client and exhausts the BEAM's memory.

Details

1. Archive auto-decoding. Req.Steps.decode_body/1 in lib/req/steps.ex dispatches on the response content-type (or URL extension) and calls Erlang's archive libraries with :memory, returning a [{name, bytes}] list of every entry fully decompressed in RAM: application/zip → :zip.extract(body, [:memory]), application/x-tar → :erl_tar.extract({:binary, body}, [:memory]), application/gzip / .tgz → :erl_tar.extract({:binary, body}, [:memory, :compressed]). No byte cap is enforced before decoding and no per-entry size limit is passed to :zip / :erl_tar.

2. content-encoding chaining. Req.Steps.decompress_body/1 walks the content-encoding header and chains :zlib / :brotli / :ezstd decoders, so a response advertising content-encoding: gzip, gzip, gzip, … inflates through multiple layers without bound.

3. Default-on, attacker-chosen decoder. Both steps are part of Req's default pipeline. The caller does not need to opt in, and the attacker chooses which decoder fires by setting content-type and content-encoding on their own server (or on any host reached via Req's automatic redirect following).

PoC

  1. Run an HTTP server that responds 200 with content-type: application/zip and a body that is a zip archive whose single entry is ~400 MB of zero bytes (compressed wire payload: a few hundred KB).
  2. From the victim process, call Req.get!(url) against that server (no special options, no opt-in to archive decoding).
  3. decode_body/1 dispatches on content-type, invokes :zip.extract(body, [:memory]), and the response body becomes [{~c"bomb.bin", <<400 MB of zero bytes>>}]. A sub-MB request produces hundreds of MB resident memory; layering gzip on the content-encoding path or increasing entry size scales arbitrarily.

Impact

Memory-exhaustion denial of service against any Elixir application that uses Req with its default step pipeline to fetch URLs influenced by an untrusted party, including webhook senders, link previews, OAuth/OIDC discovery clients, package mirrors, image proxies, and any Req.get!/1 call that may follow redirects to attacker-controlled hosts. No authentication is required; a single response can crash the BEAM and take down unrelated workloads on the same VM.

Affected Packages

1 total 1 fixed
EcosystemPackageVulnerable rangeFix
💧Hexreq≥ 0.1.0&&< 0.6.10.6.1mix deps.update req

Affected Products

1 product · 1 configurations
Application
reqwojtekmach
≥ 0.1.0 && < 0.6.1
range

Detection & mitigation playbook

Open-source dependency
  1. Detect

    Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for req, including transitive dependencies — a direct dependency you never call can still pull in a vulnerable version.

  2. Fix

    Update req to 0.6.1 or later, then make sure no transitive (indirect) dependency still pins the vulnerable range — O3 confirms CVE-2026-49755 is resolved across your whole dependency graph.

  3. Workarounds

    Cap what an attacker can consume: apply request size, rate and timeout limits in front of the affected component, and run it with memory and CPU limits so exhaustion degrades one worker rather than the whole service.

Frequently Asked Questions

### Summary Req's default response pipeline auto-decodes archive and compressed bodies based on the server-supplied `content-type` (or URL extension) and materialises the full decompressed contents in memory with no size cap. An attacker who controls (or can redirect a victim into) an HTTP endpoint reached by `Req.get!/1` can return a tiny "decompression bomb" that expands to many gigabytes on the client and exhausts the BEAM's memory. ### Details **1. Archive auto-decoding.** `Req.Steps.decode_body/1` in `lib/req/steps.ex` dispatches on the response `content-type` (or URL extension) and ca
O3 Security · Impact-Aware SCA

Is CVE-2026-49755 in your dependencies?

Find it across Hex, including transitive dependencies.

CVE-2026-49755: req DoS | O3 Security