# Ecosystem matrix

One page that answers "is this component affected, and what fixes it". Use it after
[inventory](07-Inventory) has told you what is installed: the matrix supplies the decision, the
inventory supplies the facts.

## 1. The exposure rule

**Compression is not exposure. Decompression is exposure.**

A service that emits `Content-Encoding: br` in its responses is generally not vulnerable unless it
also decodes Brotli from an untrusted source. A service that never advertises Brotli compression can
still be vulnerable, because its HTTP client decompresses `br` responses automatically.

| Data path | Example | Risk |
|---|---|---|
| Inbound request bodies | a client sends `Content-Encoding: br` and the application or framework decompresses it | critical |
| Outbound responses | a Node.js application calls `fetch()` against a malicious or compromised server that answers with `br` | critical |
| Uploaded archives | a user uploads a `.br` file and the backend decompresses it | critical |
| Gateway decompression | Envoy or Istio is configured to decompress request bodies before forwarding | critical |
| Queues and object storage | a worker consumes attacker-influenced compressed objects | high |
| Build and deploy pipelines | a build step decompresses externally sourced Brotli archives | high |
| Service-to-service calls | one internal service sends Brotli to another | medium to high, depends on the trust boundary |

Measured on the three hosts of the field run: the web tier compressed only, and the reachable path
was outbound libcurl from PHP — 164 files with `CURLOPT_ENCODING` on the largest host. That is what
this rule looks like in practice; see the [field cases](04-Field-Cases).

## 2. Core library

| Component | Vulnerable | Fixed | Evidence |
|---|---|---|---|
| Google Brotli, `libbrotli`, `libbrotlidec` | 1.0.3 – 1.2.0 | 1.0.10, 1.1.1 or 1.2.1 | brief, measured |

The same package name appears in every other row of this page: the difference is whether the
component bundles its own copy or links the system one.

## 3. JavaScript runtimes

| Component | Vulnerable | Fixed | Notes |
|---|---|---|---|
| Node.js 26.x | before 26.12.1 | 26.12.1 | current line |
| Node.js 24.x | before 24.22.1 | 24.22.1 | LTS |
| Node.js 22.x | before 22.23.4 | 22.23.4 | LTS maintenance |
| Node.js 20.x, 23.x, 25.x and older | all versions | no official fix | migrate to a supported line |
| Bun | 1.0.21 – 1.4.3 | 1.4.4 | standalone executables must be rebuilt |

Node.js bundles the decoder and exposes it through `node:zlib`; its built-in `fetch()` also
decompresses Brotli responses automatically, so a client-only Node.js application is a relevant
attack surface too. There is no complete workaround: the runtime upgrade is the fix.

## 4. Python

| Package | Vulnerable | Fixed |
|---|---|---|
| `Brotli` | 1.2.0 and earlier | 1.2.1 |
| `brotlicffi` | 1.2.0.x and earlier | 1.2.1.0 |

Python exposure is usually indirect: HTTP libraries and frameworks pull Brotli support in through
dependencies such as `httpx[brotli]`, `requests`/`urllib3` integrations, `aiohttp`, or scraping
frameworks. A pinned dependency keeps the vulnerable build after the system library is patched.

## 5. Service mesh and proxies

| Component | Vulnerable when | Fixed |
|---|---|---|
| Envoy | the Brotli decompressor is enabled | 1.36.12, 1.37.8, 1.38.6, 1.39.3, 1.40.0 |
| Istio | Brotli decompression is enabled, commonly through an `EnvoyFilter` | 1.29.9, 1.30.6, 1.31.2 |

Istio's own advisory describes the issue as a buffer overflow in the Brotli decompressor that can
disclose memory, crash the proxy or allow code execution, and advises upgrading any deployment with
Brotli decompression enabled. A control-plane upgrade alone does not fix a data plane that still
runs an old Envoy: check the proxy version, not the CRD version.

## 6. .NET

Microsoft shipped out-of-band updates. Practical exposure is where an application enables request
decompression or configures an HTTP client to decompress Brotli responses automatically.

| Release line | Fixed runtime |
|---|---|
| .NET 8 | 8.0.33 |
| .NET 9 | 9.0.22 |
| .NET 10 | 10.0.14 |
| .NET 11 preview | 11.0.0-rc.3.26522.148 |

## 7. Operating-system packages

Distribution packages carry backported fixes, so the version string does not have to reach 1.2.1.
A package whose upstream number still looks vulnerable can be fully patched — and a rebuild can
carry the vulnerable code with a fresh revision. The packaged changelog decides.

| Distribution | Package | Fixed | Advisory |
|---|---|---|---|
| Debian 12 bookworm | `brotli`, `libbrotli1` | 1.0.9-2+deb12u1 | DLA-4855-1 |
| Debian 13 trixie | `brotli`, `libbrotli1` | 1.1.0-2+deb13u1 | DSA-6582-1 |
| Debian unstable | `brotli` | 1.2.0-4.1 | Debian tracker |
| Ubuntu 26.10 | `brotli` | 1.2.0-4ubuntu0.1 | Ubuntu security notice |
| Ubuntu 26.04 LTS | `brotli`, `libbrotli1` | 1.2.0-3ubuntu0.1 | Ubuntu security notice |
| Ubuntu 24.04 LTS | `brotli`, `libbrotli1` | 1.1.0-2ubuntu0.1 | Ubuntu security notice |
| Ubuntu 22.04 LTS | `brotli` | 1.0.9-2ubuntu0.1 | Ubuntu security notice |
| Ubuntu 20.04 and older | `brotli` | not fixed in the reviewed sources | migration or a supported vendor build |

Measured on the hosts of the field run — the numbers below come from `dpkg-query` and the packaged
changelog, not from an advisory:

| Host OS | Installed (vulnerable) | Fixed package | Pocket |
|---|---|---|---|
| Ubuntu 26.04 LTS | `1.2.0-3build1` | `1.2.0-3ubuntu0.1` | `resolute-security` |
| Ubuntu 24.04 LTS | `1.1.0-2build2` | `1.1.0-2ubuntu0.1` | `noble-security` |
| Debian 12 | `1.0.9-2+b6` | `1.0.9-2+deb12u1` | `bookworm-security` |

## 8. What this repository covers, and what it does not

| Row of this page | Covered by `detect.sh` | Covered by `remediate.sh` | Needs another tool |
|---|---|---|---|
| `libbrotli1` on Debian and Ubuntu | yes | yes | — |
| Debian and Ubuntu container images | no | no | image rebuild and rescan |
| Node.js, Bun, Python, .NET | version is reported | no | runtime upgrade, artifact rebuild |
| Envoy, Istio | no | no | proxy upgrade or decompressor removal |
| Statically linked and vendored copies | no | no | binary inventory and rebuild |

The boundary is deliberate: the tool proves the package path and the running processes on a host.
Everything outside it is handled by the [remediation playbooks](08-Remediation-Playbooks) and
verified by hand.

Next: [Inventory](07-Inventory) — how to find every copy before deciding anything.
