
Offline Java tool that scans application jars to determine exposure to 14 Netty codec-http CVEs, identifying the exact patched version (4.1.137.Final/4.2.17.Final) despite inconsistent advisory boundaries.
Offline checker for 23 io.netty:netty-codec-http advisories (2025–2026) — the 14 CVEs in the
GitHub Advisory Database, plus 9 advisories that Netty published on 2026-09-10 only in its own
repository, which Dependabot cannot see.
It tells you which ones you are actually exposed to, and the single version that clears all of them:
4.1.138.Final / 4.2.18.Final.
⚠️ Correction to v0.1.x. Versions 0.1.x of this tool (and its README) said that
4.1.137.Final/4.2.17.Finalclears everything. That answer is out of date. It was correct for the 14 advisories that existed when it was written; the 2026-09-10 batch moved the target one patch release up. On4.1.137.Final/ you are still exposed to of the new advisories, including one rated (, below). If you upgraded because v0.1.x told you to, upgrade once more.
4.2.17.FinalGHSA-pvjx-v7vp-62vqSingle jar, zero runtime dependencies, fully offline, Java 17+.
14 CVEs in the GitHub Advisory Database (Dependabot alerts on these):
CVE-2025-58056 · CVE-2025-67735 · CVE-2026-33870 · CVE-2026-41417 · CVE-2026-42580 · CVE-2026-42581 · CVE-2026-42585 · CVE-2026-42587 · CVE-2026-50020 · CVE-2026-56746 · CVE-2026-59898 · CVE-2026-59899 · CVE-2026-59903 · CVE-2026-59921
9 repository-only advisories, published in netty/netty on 2026-09-10 (no CVE ID yet; Dependabot does not alert on these):
| Advisory | Severity | What | Fixed in |
|---|---|---|---|
GHSA-pvjx-v7vp-62vq | high | HttpServerCodec: unbounded per-connection queue via HTTP/1.1 pipelining → heap exhaustion | 4.1.138 / 4.2.18 |
GHSA-2g6j-r8q9-5hr8 | high (CVSS 7.3) | HttpServerCodec response desynchronization | 4.1.137 / 4.2.17 |
GHSA-2g37-3h88-55hc | medium | WebSocketServerExtensionHandler: unbounded per-connection queue via pipelining | 4.1.138 / 4.2.18 |
GHSA-3jrc-fchc-59pw | medium | Transfer-Encoding split across header fields bypasses the final-chunked check → request smuggling | 4.1.138 / 4.2.18 |
GHSA-hcvj-94mj-jp5c | medium | Incomplete validation of malformed Transfer-Encoding (bypass of an earlier fix) → request smuggling | 4.1.138 / 4.2.18 |
GHSA-j4mg-hqgv-34qc | medium | Whitespace after the digits in chunk-size is truncated → request smuggling | 4.1.138 / 4.2.18 |
GHSA-rq4j-fc47-9698 | medium | Control characters in the chunk-size line → request smuggling | 4.1.138 / 4.2.18 |
GHSA-h75q-xqrh-59rf | medium | RtspDecoder method token with a trailing control byte | 4.1.138 / 4.2.18 |
GHSA-rmcw-9fcq-wjq7 | medium | SpdySessionHandler accepts unlimited concurrent remote streams → OOM | 4.1.138 / 4.2.18 |
In the tool's output every one of these nine is tagged [Dependabot/全局库:未收录]
("not in the GitHub Advisory Database").
Dependabot alerts come from the GitHub Advisory Database. On 2026-09-10 Netty published a batch of
security advisories in its own repository (netty/netty → Security → Advisories). As of 2026-09-19,
none of the nine that affect netty-codec-http is in the GitHub Advisory Database —
gh api advisories/<GHSA-ID> returns 404 for every one of them, while a known entry
(GHSA-8c42-7qj2-3j46) returns 200 as a control. None has a CVE ID yet.
So a project that Dependabot reports as clean at 4.1.137.Final is still inside the affected
range of eight of them.
GHSA-pvjx-v7vp-62vq is the default-path one. It is in HttpServerCodec, the
request-decoder/response-encoder pair that essentially every Netty HTTP/1.1 server uses. A remote,
unauthenticated client pipelines many requests on one connection and does not read the responses;
the per-connection method queue grows without bound until the heap is exhausted. No special
configuration is required. Rated high; the advisory publishes no CVSS score.GHSA-2g6j-r8q9-5hr8 needs three things at once: HTTP/1.1 pipelining, a HEAD request in the
pipeline, and a client sending Expect: 100-continue. Only then can a response body be dropped for
one request and sent for another. It is rated high (CVSS 7.3), but it is not a default-path issue.
It was fixed in 4.1.137.Final / 4.2.17.Final, so the v0.1.x answer already covered it.3jrc, hcvj, j4mg, rq4j) are parser-differential
issues. They matter when Netty sits behind or in front of another HTTP component that parses the
same malformed message differently.2g37, h75q and rmcw only apply if you use WebSocket extensions (e.g.
WebSocketServerCompressionHandler), RtspDecoder, or SPDY respectively.Every Netty module is released under the same version number, so upgrading feels like a single decision. It isn't. Across these 23 advisories the 4.1-line fix versions land on 125 / 129 / 132 / 133 / 135 / 136 / 137 / 138 — eight different values. Follow any one advisory and you are still inside the affected range of others.
netty-codec-http2 declares netty-codec-http as a compile dependency with
<version>${project.version}</version> — the two versions are pinned to each other.
So if you upgraded to 4.1.136.Final because that is the version which clears the seven
netty-codec-http2 CVEs, you now run netty-codec-http 4.1.136.Final too. That is inside
CVE-2026-59903 (<= 4.1.136.Final) and all nine repository-only advisories. You need
4.1.138.Final. On the 4.2 line the HTTP/2 answer is 4.2.16.Final; this side needs 4.2.18.Final.
This is not a claim that the HTTP/2 advice was wrong — it answered for a different module. It is a claim that "one version number" hides the fact that you were answering for one module only.
<= 16 times and < 12 times.
The same 4.1.136.Final is therefore safe for CVE-2026-56746 (< 4.1.136.Final) and
affected for CVE-2026-59903 (<= 4.1.136.Final). Normalising the operator either way
gives a wrong answer, so each operator is kept exactly as published.GHSA-3jrc-fchc-59pw publishes only a lower bound (>=4.1.132.Final / >=4.2.12.Final).
Read literally, even the fixed 4.1.138.Final would be "affected". The generator adds the
published fixed version as an explicit upper bound for that one advisory only, prints the original
range next to it, and fails if any other range would be altered.pom.xml — on purposeIf you use Spring WebFlux, netty-codec-http arrives through
spring-boot-starter-webflux
-> spring-boot-starter-reactor-netty
-> reactor-netty-http
-> netty-codec-http
The artifactId never appears in your pom.xml. A pom-based check answers "I don't use it",
which is wrong. This tool reads the jars that actually ship.
java -jar netty-http-check.jar target/ # scan build output
java -jar netty-http-check.jar myapp.jar # Spring Boot fat-jar / war, nested jars included
java -jar netty-http-check.jar --version-of 4.1.137.Final # judge a version directly
| Code | Meaning |
|---|---|
0 | The scan finished, every file was actually read, and none of the 23 applies |
1 | Affected by at least one of the 23 |
2 | Could not judge (bad arguments, path missing, no netty-codec-http found, version not parseable) |
4 | Some file could not be read — not a zip, truncated, or an I/O failure |
🔴 2 is deliberately not 0: "nothing found" and "clean" must not look the same to a script.
🔴 4 was added on 2026-09-09. Before that, an unreadable file only produced a line on stdout
while the exit code stayed 0 — so in CI "I could not read it" silently meant "pass".
"I could not read it" and "you are safe" must be two different sentences. If something affected
is found, 1 takes priority over 4.
⚠️ A legitimately empty jar (a bare 22-byte EOCD record) is a real empty zip, not a broken
file, and does not trigger 4 — false alarms are what make real alarms get ignored.
netty-codec-http. Other Netty modules have their own
advisories (the 2026-09-10 batch also covers netty-codec-http2, -http3, -stomp, -smtp,
-mqtt and others); a clean result here says nothing about them. If you also run
netty-codec-http2, the tool says so and points at the cross-module problem above, but it does not
judge that module.high GHSA-pvjx-v7vp-62vq); they are printed as they are, not rolled up into a scary total.src/main/java/dev/mikko/nettyhttpcheck/RuleTable.java is generated, never hand-edited:
python tools/gen_rules.py --dry # run the assertions only
python tools/gen_rules.py # regenerate the table
Ten assertions must pass or nothing is written. Among them: the 14 global advisories are still
reviewed; the 2026-09-10 repository batch for netty-codec-http is still exactly these nine and
still absent from the GitHub Advisory Database (with a positive control that must return 200);
the computed single answer is still 4.1.138.Final / 4.2.18.Final and fetchable from Maven Central
(with a sentinel version that must 404); the old v0.1.x answer 4.1.137.Final / 4.2.17.Final
still hits GHSA-pvjx-v7vp-62vq; the lower-bound-only range is handled and no other range is
modified; the < / <= boundary case still flips; and the HTTP/2 answer from §4 still leaves a hole
on this side.
tools/recheck_before_publish.py re-checks the published claims before any write-up goes out; it exits
3 if the nine advisories appear in the GitHub Advisory Database, if 4.1.138.Final / 4.2.18.Final
disappear from Central, or if 4.1.139.Final / 4.2.19.Final appear (a newer release may mean newer
advisories).
Real-jar end-to-end checks live in tools/e2e_real_jars.py — they download actual jars from
Maven Central (including 4.1.137, 4.1.138, 4.2.17, 4.2.18) rather than fixtures, because
"works on a hand-built zip, fails on the real jar" is a real failure mode.
Apache License 2.0 — see LICENSE.