CVE-2026-54399 is a denial-of-service vulnerability in the HTTP/1.1 message parser of Apache HttpComponents Core 5. A remote HTTP peer can cause excessive memory consumption by sending a message with an unusually large number of header fields or an excessively long header line. A vulnerable Java process may experience rising allocation rates, repeated garbage collection, severe latency, OutOfMemoryError, container termination, or complete loss of service availability. (Openwall)
Apache identifies the Maven artifact org.apache.httpcomponents.core5:httpcore5 as affected from the 5.0 alpha line through 5.4.2, as well as from the 5.5 alpha line through 5.5-beta1. Apache HttpComponents Core 5.4.3 introduces finite defaults for incoming HTTP/1 messages: a maximum line length of 8192 bytes and a maximum header count of 100. The 5.4.3 release notes and the project’s patch commit both document this change. (NVD)
The flaw is important, but it should not be overstated. Authoritative records describe an availability vulnerability, not remote code execution, authentication bypass, data disclosure, or integrity compromise. The CISA-ADP CVSS 3.1 assessment shown by NVD is 7.5 High, using the vector AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H. NVD had not supplied its own CVSS score when the record was reviewed. (NVD)
The first remediation step is straightforward: upgrade the affected component. The harder work is determining where that component runs and whether untrusted HTTP/1.1 requests or responses can actually reach its parser.
CVE-2026-54399 at a Glance
| Campo | Verified detail | Significado operacional |
|---|---|---|
| Vulnerabilidade | Uncontrolled resource consumption in an HTTP/1.1 message parser | Attacker-controlled headers can consume process memory |
| Produto | Apache HttpComponents Core 5 | A Java transport library, not Apache HTTP Server |
| Maven artifact | org.apache.httpcomponents.core5:httpcore5 | Search dependencies, packaged JARs, containers, SBOMs, and vendor software |
| Affected stable range | 5.0-alpha through 5.4.2 | Upgrade stable deployments to 5.4.3 or later |
| Affected development range | 5.5-alpha through 5.5-beta1 | Move to 5.5-beta2 or a later release if that branch is required |
| Gatilho | Excessive header count or excessive header-line length | Both many small fields and one very large field can matter |
| Vetor de ataque | Network | A remote HTTP peer can supply the triggering input |
| Privileges required | None in the CISA-ADP score | Application authentication might not protect the parser |
| User interaction | Nenhum | No user needs to click or open anything |
| Impacto primário | Availability loss | Heap pressure, latency, crashes, OOM kills, and service interruption |
| CWE | CWE-400, Uncontrolled Resource Consumption | The implementation lacked safe default resource bounds |
| CISA-ADP CVSS | 7.5 High | High availability impact with no documented confidentiality or integrity impact |
| Default correction | 100 headers and 8192 bytes per line | The parser now has finite default boundaries |
| Public exploitation status | CISA-ADP listed exploitation as none in its July 1, 2026 enrichment | This is a point-in-time assessment, not a future guarantee |
The official Apache advisory labels the issue “Important” and credits Henry Huang as the finder. The CVE was published on July 1, 2026. (Openwall)
Apache HttpCore Is Not Apache HTTP Server
The name creates an immediate triage trap.
Apache HTTP Server, commonly called httpd, is a standalone web server. Apache HttpComponents Core is a Java library containing low-level HTTP transport components for building client-side and server-side services. Apache documents both blocking Java I/O and non-blocking, event-driven Java NIO models. (Apache HttpComponents)
CVE-2026-54399 therefore does not mean that every server running Apache httpd is affected. Updating an Apache HTTP Server package does not replace a vulnerable httpcore5 JAR embedded in a Java application.
The reverse is also true. A service does not need to run Apache HTTP Server to be exposed. HttpCore may be embedded in:
- A custom Java HTTP server.
- A Java HTTP client.
- An API gateway or reverse proxy.
- A webhook delivery or validation service.
- A crawler, feed importer, or URL preview service.
- An artifact downloader.
- A cloud SDK or third-party integration SDK.
- A security scanner.
- A software update agent.
- A commercial application that bundles its dependencies.
- A Spring Boot fat JAR.
- A shaded or relocated JAR.
- A container image assembled from several application layers.
- A platform library brought in transitively through a higher-level component.
Apache describes HttpClient as an HTTP agent built on top of HttpCore, which is one reason teams may find the affected artifact without having declared it directly. (Apache HttpComponents)
The exact coordinates matter:
org.apache.httpcomponents.core5:httpcore5
Do not confuse them with:
org.apache.httpcomponents:httpcore
The latter is the older 4.x artifact line. Public dependency-scanner reports have already documented false-positive matching in which httpcore 4.4.16 was associated with Core 5 CVEs because of imprecise product mapping. That makes exact package identification essential. (GitHub)
What the Patch Actually Changed
The most useful technical evidence is the Apache source change.
Before the patch, the relevant defaults in Http1Config were:
private static final int INIT_MAX_HEADER_COUNT = -1;
private static final int INIT_MAX_LINE_LENGTH = -1;
The June 17, 2026 commit changed those values to:
private static final int INIT_MAX_HEADER_COUNT = 100;
private static final int INIT_MAX_LINE_LENGTH = 8192;
The commit message is explicit: “Use max line length of 8192 and max header count of 100 for incoming HTTP/1 messages by default.” The change modified only two constants in Http1Config.java, but the security effect is substantial because the default parser configuration moved from unbounded values to finite ones. (GitHub)
The Apache 5.4.3 release notes repeat the same correction and list it alongside a separate HTTP/2 HPACK header-list enforcement fix. (Apache Downloads)
The corrected 5.4.x source defines:
private static final int INIT_MAX_HEADER_COUNT = 100;
private static final int INIT_MAX_LINE_LENGTH = 8192;
It also notes that line length is measured in bytes rather than characters, which can matter when a nonstandard protocol charset is involved. (GitHub)
This is not merely a cosmetic default change. In an HTTP parser, a negative value used as “unlimited” gives the remote peer control over how much header state the receiver attempts to process and retain. A finite limit changes the failure mode from “keep allocating until another resource stops the process” to “reject the message when a defined protocol boundary is exceeded.”
How HTTP/1.1 Header Parsing Creates Memory Pressure

A basic HTTP/1.1 request looks harmless:
GET /health HTTP/1.1
Host: api.example.test
User-Agent: health-check
Accept: application/json
RFC 9112 defines an HTTP message as a start line, followed by zero or more field lines, an empty line, and an optional message body. It describes the normal parsing process as reading the start line, reading each header field line into a data structure until the empty line, and then using the parsed data to determine how the body should be handled. (Rastreador de dados da IETF)
The parser does more work than counting network bytes. Depending on implementation and integration, it may:
- Expand a receive or line buffer.
- Search for line endings.
- Validate the field syntax.
- Separate a field name from its value.
- Trim optional whitespace.
- Decode bytes to characters.
- Allocate field objects.
- Store those objects in a list, array, hash table, or message structure.
- Copy or normalize values.
- Preserve duplicate fields.
- Expose fields to later interceptors.
- Retain the complete field section until message dispatch.
RFC 9112 states that field-line contents are generally interpreted after the entire field section has been processed. This helps explain why meaningful resource consumption can occur before a route handler, authentication filter, controller, schema validator, or business rule gets an opportunity to reject the message. (Rastreador de dados da IETF)
Two separate dimensions are dangerous.
Excessive Header Count
An attacker can send many individually small fields:
X-Demo-000001: A
X-Demo-000002: A
X-Demo-000003: A
X-Demo-000004: A
X-Demo-000005: A
Each line is short, but each may produce parser work and a stored representation. If no header-count boundary exists, the field section can grow until some other limit is reached.
The cost is larger than the literal bytes shown on the wire. Each parsed field may involve:
- Object headers.
- References.
- Array or list capacity.
- Decoded strings.
- Backing byte or character arrays.
- Hashing or lookup structures.
- Temporary parsing buffers.
- Metrics and tracing metadata.
- Framework-specific wrappers.
The precise overhead depends on the JDK, garbage collector, compact-string behavior, parser path, and application framework. It is therefore incorrect to calculate exploitability using only the raw header bytes.
Excessive Header-Line Length
An attacker can instead send a small number of fields with very large values:
X-Large-Field: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA...
Without a finite line-length limit, the parser may repeatedly enlarge or copy a buffer while waiting for the terminating CRLF sequence.
The impact can differ from the many-field case. A large individual line may create:
- Large contiguous arrays.
- Repeated buffer-resizing operations.
- Temporary copies.
- High allocation bursts.
- Large string objects.
- Increased old-generation retention.
- Humongous allocations under some G1 configurations, depending on object size and region settings.
The public advisory does not specify one required heap layout, garbage collector, concurrency level, or exact message size. It simply establishes that excessive header count or header length can produce memory exhaustion in affected versions. Reports should preserve that level of precision rather than inventing a universal crash threshold. (Openwall)
Concurrency Multiplies the Cost
One abnormal message may produce measurable pressure. Multiple simultaneous messages can turn that pressure into an outage.
A conceptual model is:
aggregate parser pressure
≈ active parsing connections
× retained header state per connection
+ temporary allocation
+ garbage-collection overhead
This is not a predictive formula. It shows why several controls are independent:
- Per-line length limits.
- Per-message field-count limits.
- Total header-section size limits.
- Header-read timeouts.
- Per-source connection limits.
- Global concurrent connection limits.
- Application worker limits.
- JVM and container memory boundaries.
A large heap does not fix an unbounded parser. It may only allow the process to retain more attacker-controlled data before failure.
Why Application Authentication May Not Protect the Service
The CISA-ADP vector lists no privileges required. That does not necessarily mean every deployment exposes the parser to the open internet. It means the vulnerability itself does not require an authenticated application identity once an attacker can send input to the vulnerable parsing path. (NVD)
A common request-processing order looks like this:
TCP connection
-> optional TLS
-> HTTP start-line parsing
-> HTTP header parsing
-> request object creation
-> middleware or filters
-> route resolution
-> authentication
-> authorization
-> controller
-> business logic
If memory is consumed during header parsing, a bearer token requirement at the application layer can be irrelevant. The request may never reach the code that checks the token.
This is also why a route-specific rate limiter might not be enough. A limiter that runs after routing cannot protect work already performed by the transport parser.
Useful protections must exist at or before the vulnerable boundary:
- A corrected parser.
- A trusted edge that rejects oversized messages before forwarding them.
- Connection-level rate controls.
- Header read deadlines.
- Resource isolation.
HTTP Flexibility Does Not Require Unlimited Input
Real systems use headers for legitimate reasons:
- Cookies.
- Bearer tokens.
- Proxy authentication.
- Distributed tracing.
- Cache metadata.
- Content negotiation.
- Forwarding information.
- Digital signatures.
- Partner-specific metadata.
- Request correlation.
- Feature flags.
- Service-mesh identity.
- Large
Set-Cookieresponses. - Federated identity protocols.
A fixed policy that is too small can break production traffic. That compatibility risk may explain why some libraries historically allowed applications to configure limits themselves.
The absence of one universal value does not justify an unlimited default.
A mature HTTP resource policy should consider at least four independent boundaries:
| Boundary | What it limits | Security value |
|---|---|---|
| Maximum header-line length | One field line | Stops a single field from growing without limit |
| Maximum header count | Number of fields | Stops thousands of short fields |
| Maximum total header-section size | Aggregate field bytes | Stops combinations that stay below individual limits but remain excessive |
| Header read timeout | Time spent waiting for the field section | Limits slow or incomplete header delivery |
Apache’s 5.4.3 change directly sets finite defaults for the first two dimensions. Edge platforms and application infrastructure should still enforce total-size, connection, concurrency, and timing policies.
Where the Vulnerable Parser Can Appear
The obvious deployment is a server accepting requests. It is not the only one.
Request-Side Server Exposure
A direct path may look like:
untrusted client
-> TCP or TLS listener
-> vulnerable HttpCore HTTP/1 parser
-> application
An indirect path may look like:
untrusted client
-> CDN
-> cloud load balancer
-> ingress
-> vulnerable Java service
The service can remain exposed if every upstream hop forwards a message that exceeds the safe capacity of the backend parser.
An upstream component may materially reduce exposure when it:
- Terminates the incoming HTTP connection.
- Parses the complete field section.
- Enforces a lower field-count or size policy.
- Rejects before forwarding.
- Cannot be bypassed.
- Applies the same policy to every relevant listener.
The existence of a CDN is not enough. Teams need the actual configuration and route map.
Response-Side Client Exposure
HttpCore is a foundation for client-side as well as server-side HTTP services. Apache’s RequesterBootstrap API exposes setHttp1Config, which means HTTP/1 protocol configuration also applies to requester behavior. (Apache HttpComponents)
A response-side path may look like:
user supplies a callback URL
-> Java worker connects to the URL
-> attacker-controlled server returns abnormal response headers
-> vulnerable HttpCore parser processes the response
This matters for:
- Webhook verification.
- Webhook delivery.
- URL preview services.
- RSS importers.
- Package downloaders.
- Document rendering systems.
- Server-side browsers.
- Open proxy features.
- Cloud integration brokers.
- Artifact mirrors.
- Security testing tools.
- User-configurable upstream APIs.
- Applications with SSRF.
- Clients that follow attacker-influenced redirects.
A service can have no public listening port and still parse data controlled by a remote attacker.
This is one of the most frequently missed conditions in dependency triage. Engineers see “HTTP parser,” inspect inbound routes, find a protected gateway, and close the issue. The same library may be processing responses from destinations selected by users.
Protocol Translation
The protocol visible to the external client may not be the protocol used by the backend:
browser -> CDN: HTTP/2
CDN -> origin load balancer: HTTP/1.1
origin load balancer -> Java service: HTTP/1.1
CVE-2026-54399 can matter in this architecture because HttpCore receives HTTP/1.1 after translation.
A different environment may do the reverse or preserve HTTP/2 deeper into the stack. The correct method is to identify the protocol at every hop rather than assuming that the public endpoint’s negotiated protocol describes the backend.
Alternate and Bypass Routes
A protected public hostname can coexist with unprotected paths:
partner client
-> private load balancer
-> Java integration service
compromised internal workload
-> service mesh
-> Java service
monitoring provider
-> direct origin address
-> Java listener
user-controlled URL
-> outbound requester
-> malicious response
Other routes worth checking include:
- Staging environments.
- Disaster-recovery systems.
- Administrative interfaces.
- Health-check ports.
- NodePort services.
- Host-network bindings.
- Legacy DNS names.
- Development tunnels.
- VPN listeners.
- Direct cloud load-balancer addresses.
- Internal service discovery names.
- Customer-dedicated endpoints.
- Regional deployments with different edge policies.
The correct finding is not “the main website has a WAF.” It is “every route to the vulnerable parser has been identified, and the enforcement point for each route is known.”
Affected Versions and Upgrade Decisions
NVD records the Apache-provided affected package data as:
org.apache.httpcomponents.core5:httpcore5
Affected ranges:
5.0-alpha through 5.4.2
5.5-alpha through 5.5-beta1
The default status outside those ranges is listed as unaffected in the CNA data. (NVD)
For stable production deployments, use:
Apache HttpComponents Core 5.4.3 or later
For a system intentionally following the 5.5 prerelease branch, move beyond 5.5-beta1. Apache announced 5.5-beta2 alongside the fixed stable release. (Apache Downloads)
Do not move a stable production system to a beta release only because its version number appears newer. The corrected stable branch exists.
Vendor Backports
A commercial vendor or Linux distribution may backport the correction while retaining an older upstream-looking version.
For example, a package string may contain 5.4.2 but include a vendor revision that carries the two-line fix. Conversely, an application repository may declare 5.4.3 while an old production image still contains 5.4.2.
Use the following evidence order:
- Vendor security advisory.
- Vendor-fixed package revision.
- Installed package metadata.
- Final JAR manifest.
- SBOM associated with the deployed image.
- Container filesystem evidence.
- Runtime classpath or class-loading evidence.
- Source dependency declaration.
Do not manually replace JARs inside vendor-managed products unless the vendor supports the procedure. Unapproved replacement can break compatibility, signing, supportability, and future upgrades.
Find httpcore5 in Maven
Search the resolved dependency tree:
mvn -q dependency:tree \
-Dincludes=org.apache.httpcomponents.core5:httpcore5
A direct dependency might appear as:
com.example:gateway-service:jar:1.0.0
\- org.apache.httpcomponents.core5:httpcore5:jar:5.4.2:compile
A transitive dependency might appear as:
com.example:webhook-worker:jar:1.0.0
\- com.vendor:integration-sdk:jar:7.4.0:compile
\- org.apache.httpcomponents.core5:httpcore5:jar:5.4.2:compile
Review the runtime scope separately:
mvn -q dependency:tree \
-Dscope=runtime \
-Dincludes=org.apache.httpcomponents.core5:httpcore5
Inspect the effective POM when a BOM or parent project manages the version:
mvn -q help:effective-pom > effective-pom.xml
grep -n "httpcore5" effective-pom.xml
Questions to answer include:
- Is the dependency direct or transitive?
- Which parent dependency introduced it?
- Did dependency conflict resolution select a different version?
- Is it compile, runtime, provided, test, or optional?
- Does a plugin copy test dependencies into the final image?
- Does a higher-level SDK require a specific API version?
- Does the final artifact contain more than one copy?
A source dependency tree is useful evidence, but it is not proof of what currently runs.
Find httpcore5 in Gradle
Use the runtime classpath:
./gradlew dependencyInsight \
--dependency httpcore5 \
--configuration runtimeClasspath
Review the complete configuration when needed:
./gradlew dependencies \
--configuration runtimeClasspath
O dependencyInsight output should identify:
- The selected version.
- The component that requested it.
- Conflict-resolution decisions.
- Dependency constraints.
- Version alignment.
- Rejected versions.
Also inspect custom configurations used by the application. A project may have configurations such as:
productionRuntimeClasspath
integrationRuntime
serverDistribution
shadowRuntimeElements
A finding in testRuntimeClasspath normally has less immediate production impact, but verify that test tools are not copied into a release image and that externally accessible test environments are not built from the same artifact.
Inspect Spring Boot Fat JARs
Spring Boot commonly stores dependencies under BOOT-INF/lib.
unzip -l application.jar | \
grep -E 'BOOT-INF/lib/httpcore5-[^/]+\.jar'
Example result:
BOOT-INF/lib/httpcore5-5.4.2.jar
That proves the JAR is present in that application archive. It does not prove the archive is the one running in production.
Calculate and record a checksum:
sha256sum application.jar
Compare it with:
- The CI artifact.
- The release manifest.
- The container layer.
- The deployed image digest.
- The running pod’s image.
Inspect Containers
For a local, authorized image:
docker run --rm \
--entrypoint sh \
your-image:tag \
-c "find / -type f -name 'httpcore5-*.jar' 2>/dev/null"
Record the immutable digest:
docker image inspect your-image:tag \
--format '{{index .RepoDigests 0}}'
Inside a Kubernetes deployment, first identify the configured image:
kubectl get deployment webhook-worker \
-n production \
-o jsonpath='{.spec.template.spec.containers[*].image}{"\n"}'
Tags are mutable. A report should prefer:
registry.example.test/webhook-worker@sha256:...
over:
registry.example.test/webhook-worker:latest
The digest ties the vulnerability evidence to a specific artifact.
Detect Shaded or Relocated Copies
A shaded JAR may remove the original filename while retaining the classes.
Search the archive:
jar tf application.jar | \
grep 'org/apache/hc/core5/http/config/Http1Config'
A matching class proves that relevant code is present but may not reveal the exact upstream version.
Other useful evidence includes:
META-INF/mavenmetadata.pom.properties.- License and notice files.
- Build provenance.
- Source maps.
- Dependency-reduction POMs.
- Class-level checksums.
- Vendor SBOMs.
- Shading plugin configuration.
Search for multiple copies. An application may contain 5.4.3 directly while a vendor SDK bundles 5.4.2 inside a shaded namespace.
Separate Package Presence from Runtime Reachability
A good triage record answers several independent questions.
| Pergunta | Strong evidence | Weak evidence |
|---|---|---|
| Is the artifact present? | Runtime SBOM, final JAR listing, container filesystem | Repository keyword search |
| Is the version affected? | Resolved version or vendor backport advisory | Filename without provenance |
| Does the process load it? | Runtime classpath, class-loading data, normal stack trace | JAR present somewhere in image |
| Does it parse HTTP/1.1? | Construction code, bootstrap configuration, runtime behavior | Process has an open TCP port |
| Can an untrusted request reach it? | Hop-by-hop route and protocol map | Public DNS entry |
| Can an untrusted response reach it? | URL control and redirect analysis | Service has no inbound public listener |
| Are edge limits complete? | Configuration plus bypass-route review | “We use a CDN” |
| Is the fix deployed? | Running digest and runtime JAR version | Merged pull request |
A dependency scanner answers the first two questions reasonably well. It usually cannot answer the rest without application and runtime context.
Safe Validation Workflow

Do not validate a memory-exhaustion vulnerability by attempting to exhaust production memory.
A safe, defensible workflow produces enough evidence to confirm exposure and remediation without reproducing the full denial of service.
Step One, Confirm the Exact Package
Collect:
groupId
artifactId
resolved version
dependency scope
introducing dependency
build identifier
Reject findings that refer only to a generic product CPE when the actual Maven coordinate is different.
Step Two, Confirm the Deployed Artifact
Record:
application checksum
container digest
deployment name
namespace or environment
pod start time
JAR path
JAR version
This prevents the ticket from being closed based on a source update that never reached production.
Step Three, Identify the Parser Role
Determine whether HttpCore is used as:
- A server parser.
- A client response parser.
- Both.
- An unused transitive dependency.
- A test-only dependency.
- A vendor-internal component with an unknown call path.
Search for construction APIs such as ServerBootstrap, RequesterBootstrap, Http1Config, and framework-specific factories.
Apache exposes setHttp1Config on both the server and requester bootstrap APIs, supporting separate review of request-side and response-side paths. (Apache HttpComponents)
Step Four, Map Every Network Hop
Document:
source
-> CDN
-> WAF
-> load balancer
-> ingress
-> service mesh
-> sidecar
-> application
-> HttpCore parser
For each hop, record:
- Incoming protocol.
- Outgoing protocol.
- Whether it terminates the connection.
- Maximum field count.
- Maximum line length.
- Maximum total header bytes.
- Header read timeout.
- Connection limits.
- Whether malformed messages are rejected.
- Whether an alternate route bypasses it.
Step Five, Review Outbound Destinations
For an HttpCore requester, determine who controls:
- The initial URL.
- DNS results.
- Redirect targets.
- Proxy settings.
- Webhook endpoints.
- Artifact locations.
- Integration base URLs.
- Imported document references.
- Image or metadata URLs.
Review whether destination validation is repeated after redirects. A safe initial URL can redirect to a different host.
Step Six, Verify Existing Limits
An affected application may already supply finite custom values.
Inspect code and configuration for:
Http1Config.custom()
.setMaxHeaderCount(...)
.setMaxLineLength(...)
A custom limit can reduce exposure, but it does not remove the need to upgrade. Framework construction paths, alternate clients, or future refactoring may use the vulnerable unlimited defaults elsewhere.
Step Seven, Test Boundaries in a Lab
In an isolated environment:
- Send a normal request or response.
- Test a field count below the policy limit.
- Test one field over the policy limit.
- Test a line below the length limit.
- Test one line over the length limit.
- Confirm early rejection.
- Confirm the process remains responsive.
- Confirm memory returns to baseline.
- Confirm a normal request succeeds afterward.
- Repeat for the response parser when relevant.
The goal is to verify a boundary, not discover how much traffic is required to crash the service.
Step Eight, Preserve the Evidence
Attach:
- Dependency output.
- Artifact checksum.
- Image digest.
- Runtime version.
- Network path diagram.
- Edge configuration.
- Lab test input dimensions.
- Rejection result.
- Memory graph.
- Normal post-test health check.
- Post-upgrade version proof.
Authorized AI-assisted validation can help maintain this evidence chain. For example, Penligente presents workflows around scoped security testing, finding verification, traceable evidence, and retesting. For a denial-of-service issue, the useful automation target is version confirmation, path mapping, bounded validation, and remediation evidence—not destructive production traffic. (Penligente)
Safe Educational PoC, Local Parser Model Only
The following example does not exploit Apache HttpCore. It opens no socket, accepts no target, sends no HTTP traffic, and cannot be used for remote scanning.
It models the difference between an unbounded design that stores every field and a bounded design that rejects before the field collection grows beyond a fixed policy.
The demonstration has hard local limits. Its memory output reflects Python object allocation, not Apache HttpCore performance and not Java heap behavior.
from __future__ import annotations
import tracemalloc
from dataclasses import dataclass
from typing import Iterable
MAX_HEADER_COUNT = 100
MAX_LINE_LENGTH = 8192
# Hard safety limits for the local demonstration.
DEMO_MAX_FIELDS = 2_000
DEMO_MAX_VALUE_LENGTH = 512
@dataclass(frozen=True)
class ParsedHeader:
name: str
value: str
def generate_local_headers(
count: int,
value_length: int,
) -> Iterable[bytes]:
"""
Generate a bounded sequence of local HTTP-like field lines.
This function does not use a network connection.
"""
if not 0 <= count <= DEMO_MAX_FIELDS:
raise ValueError("count exceeds the demonstration limit")
if not 1 <= value_length <= DEMO_MAX_VALUE_LENGTH:
raise ValueError("value_length exceeds the demonstration limit")
value = b"A" * value_length
for index in range(count):
yield b"X-Demo-%04d: " % index + value + b"\r\n"
yield b"\r\n"
def parse_without_limits(
lines: Iterable[bytes],
) -> list[ParsedHeader]:
"""
Toy example of the dangerous design pattern.
It is not Apache source code.
"""
parsed: list[ParsedHeader] = []
for raw_line in lines:
if raw_line == b"\r\n":
break
name_bytes, separator, value_bytes = raw_line.partition(b":")
if not separator:
raise ValueError("malformed field line")
parsed.append(
ParsedHeader(
name=name_bytes.decode("ascii"),
value=value_bytes.strip().decode("ascii"),
)
)
return parsed
def parse_with_limits(
lines: Iterable[bytes],
) -> list[ParsedHeader]:
"""
Toy example that rejects before storing excessive state.
"""
parsed: list[ParsedHeader] = []
for raw_line in lines:
if raw_line == b"\r\n":
break
# Check the raw line before decoding and storing it.
if len(raw_line) > MAX_LINE_LENGTH:
raise ValueError("field line exceeds the configured limit")
# Check count before appending another object.
if len(parsed) >= MAX_HEADER_COUNT:
raise ValueError("field count exceeds the configured limit")
name_bytes, separator, value_bytes = raw_line.partition(b":")
if not separator:
raise ValueError("malformed field line")
parsed.append(
ParsedHeader(
name=name_bytes.decode("ascii"),
value=value_bytes.strip().decode("ascii"),
)
)
return parsed
def measure(label: str, parser) -> None:
tracemalloc.start()
try:
result = parser(
generate_local_headers(
count=DEMO_MAX_FIELDS,
value_length=DEMO_MAX_VALUE_LENGTH,
)
)
outcome = f"accepted {len(result)} fields"
except ValueError as exc:
outcome = f"rejected input: {exc}"
current, peak = tracemalloc.get_traced_memory()
tracemalloc.stop()
print(f"{label}: {outcome}")
print(f"{label}: current Python allocation: {current:,} bytes")
print(f"{label}: peak Python allocation: {peak:,} bytes")
if __name__ == "__main__":
measure("unbounded toy parser", parse_without_limits)
print()
measure("bounded toy parser", parse_with_limits)
Run it locally:
python3 safe_header_limit_demo.py
The expected qualitative outcome is:
- The unbounded toy parser creates objects for all 2,000 fields.
- The bounded parser rejects after reaching 100 stored fields.
- Memory figures vary by Python release and platform.
- The numbers cannot be translated into an Apache crash threshold.
What the PoC Demonstrates
It demonstrates that:
- A field count is also a resource count.
- Parsing creates more state than raw network bytes.
- Early rejection reduces retained state.
- Count and line-length limits solve different problems.
- The parser should apply a limit before appending the next object.
What the PoC Does Not Demonstrate
It does not prove that:
- A specific service loads HttpCore.
- A specific version is vulnerable.
- A proxy forwards the abnormal message.
- An application can be crashed remotely.
- A certain number of fields causes Java OOM.
- A vendor package lacks a backport.
- A production endpoint is exploitable.
Those conclusions require version, runtime, path, and configuration evidence.
Upgrade with Maven
For a direct dependency:
<dependency>
<groupId>org.apache.httpcomponents.core5</groupId>
<artifactId>httpcore5</artifactId>
<version>5.4.3</version>
</dependency>
If the version is controlled centrally:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.apache.httpcomponents.core5</groupId>
<artifactId>httpcore5</artifactId>
<version>5.4.3</version>
</dependency>
</dependencies>
</dependencyManagement>
Recheck resolution:
mvn -q dependency:tree \
-Dscope=runtime \
-Dincludes=org.apache.httpcomponents.core5:httpcore5
Inspect the final artifact after building:
unzip -l target/*.jar | grep 'httpcore5-'
A dependency-management override can be unsafe when a higher-level library expects another version’s APIs. Run integration tests for:
- Connection pooling.
- TLS.
- Proxy handling.
- Request retries.
- Response parsing.
- Persistent connections.
- Redirects.
- Authentication.
- Async processing.
- Backpressure.
- Error handling.
- Shutdown behavior.
Apache describes 5.4.3 as a maintenance release containing several fixes, including a backpressure regression correction and connection-pool work in addition to the HTTP parser changes. Test the release as a whole rather than assuming only two constants changed operational behavior. (Apache Downloads)
Upgrade with Gradle
For a direct Kotlin DSL dependency:
dependencies {
implementation(
"org.apache.httpcomponents.core5:httpcore5:5.4.3"
)
}
A constraint can control transitive selection:
dependencies {
constraints {
implementation(
"org.apache.httpcomponents.core5:httpcore5:5.4.3"
) {
because(
"CVE-2026-54399 affects earlier HttpCore 5 versions"
)
}
}
}
Confirm the selected runtime component:
./gradlew dependencyInsight \
--dependency httpcore5 \
--configuration runtimeClasspath
Dependency constraints do not update shaded copies inside unrelated artifacts. Inspect the package output and container image as well.
Configure Explicit HTTP/1 Limits
Apache’s corrected version provides finite defaults, but explicit configuration can make an organization’s policy visible and testable.
The official Http1Config.Builder API exposes setMaxHeaderCount e setMaxLineLength. (Apache HttpComponents)
import org.apache.hc.core5.http.config.Http1Config;
final Http1Config http1Config = Http1Config.custom()
.setMaxHeaderCount(100)
.setMaxLineLength(8192)
.build();
The values above match the corrected Apache defaults. A deployment may choose different finite values after measuring legitimate traffic.
Server Configuration
Apache’s server bootstrap accepts an Http1Config object. (Apache HttpComponents)
import org.apache.hc.core5.http.config.Http1Config;
import org.apache.hc.core5.http.impl.bootstrap.HttpServer;
import org.apache.hc.core5.http.impl.bootstrap.ServerBootstrap;
final Http1Config http1Config = Http1Config.custom()
.setMaxHeaderCount(100)
.setMaxLineLength(8192)
.build();
final HttpServer server = ServerBootstrap.bootstrap()
.setListenerPort(8080)
.setHttp1Config(http1Config)
.register("/health", (request, response, context) -> {
response.setCode(200);
})
.create();
This snippet only demonstrates configuration placement. A production service still needs appropriate TLS, lifecycle handling, routing, logging, exception handling, and shutdown procedures.
Requester Configuration
Apache’s requester bootstrap also accepts HTTP/1 configuration. (Apache HttpComponents)
import org.apache.hc.core5.http.config.Http1Config;
import org.apache.hc.core5.http.impl.bootstrap.HttpRequester;
import org.apache.hc.core5.http.impl.bootstrap.RequesterBootstrap;
final Http1Config http1Config = Http1Config.custom()
.setMaxHeaderCount(100)
.setMaxLineLength(8192)
.build();
final HttpRequester requester = RequesterBootstrap.bootstrap()
.setHttp1Config(http1Config)
.create();
This is especially relevant to webhook, crawler, import, and proxy services that parse responses from external systems.
How to Choose a Safe Limit
The corrected defaults are a strong baseline, not proof that 100 and 8192 are ideal for every service.
Measure legitimate traffic by:
- Route.
- Client class.
- Identity provider.
- Partner.
- Browser or mobile application.
- Internal service.
- Authentication mechanism.
- Geographic region.
- Edge path.
Useful measurements include:
header count
largest field line
total encoded field bytes
cookie bytes
authorization bytes
forwarding-field bytes
tracing-field count
response Set-Cookie count
Consider percentiles rather than only the largest observed message. One malformed client can distort the maximum.
A practical policy process is:
- Measure representative traffic.
- Identify legitimate outliers.
- Remove unnecessary duplication.
- Select a finite boundary with operational margin.
- Alert near the boundary.
- Test known high-header workflows.
- Document exceptions.
- Review the policy after identity, proxy, or tracing changes.
Avoid creating a global exception because one legacy integration sends an oversized header. When possible, isolate that integration on a dedicated route with a separately documented policy.
Legitimate Traffic That Can Break After Tightening Limits
Cookies
Browsers can accumulate cookies across application migrations, domain changes, A/B tests, and legacy features. One large Cookie line may exceed a field-line boundary even when the number of fields is small.
Test:
- New sessions.
- Long-lived sessions.
- Users with migrated accounts.
- Multiple subdomain cookies.
- Failed logout paths.
- Applications behind shared parent domains.
Bearer Tokens
JWTs may grow because of:
- Large group lists.
- Role claims.
- Tenant metadata.
- Embedded permissions.
- Certificate chains.
- Duplicate identity claims.
A token that requires an unusually large header should prompt a design review rather than an automatic increase.
Integrated Authentication
Kerberos and SPNEGO negotiation can create large Authorization ou WWW-Autenticar values. Enterprise applications using those mechanisms need targeted testing.
Forwarding Fields
Proxies may append addresses to X-Forwarded-For or add multiple forwarding and tracing fields. Long chains can produce excessive state.
Trusted proxies should normalize forwarding information and discard attacker-supplied values rather than appending indefinitely.
Distributed Tracing
Instrumentation layers may add:
traceparenttracestate- Baggage fields
- Vendor correlation headers
- Debug metadata
Baggage is particularly worth reviewing because applications sometimes allow business context to grow without a clear protocol budget.
Response Cookies and Authentication Challenges
HttpCore clients can receive large response fields from:
- Identity providers.
- Proxy authentication.
- Partner platforms.
- Redirect chains.
- Web applications returning many cookies.
Response-side compatibility testing should not be skipped.
Temporary Mitigations When Upgrading Takes Time
Compensating controls can reduce risk while a corrected build moves through change control. They should not become permanent substitutes for patching.
Reject Excessive Headers at a Trusted Edge
A CDN, WAF, reverse proxy, API gateway, or ingress controller may support limits for:
- Individual field size.
- Total header bytes.
- Field count.
- Header read timeout.
- Concurrent connections.
- Requests per source.
- Incomplete request rate.
The exact setting names and semantics vary by product and release.
A vendor-neutral policy model might look like:
# Illustrative policy only.
# Translate into settings supported by the deployed platform.
http1_limits:
request:
max_field_count: 100
max_field_line_bytes: 8192
max_total_field_bytes: 32768
header_read_timeout_seconds: 10
response:
max_field_count: 100
max_field_line_bytes: 8192
max_total_field_bytes: 32768
connection_limits:
max_connections_per_source: 50
max_concurrent_header_parses: 1000
The total-byte and connection values are examples, not Apache recommendations. Use observed traffic and platform capacity to select real values.
Close Bypass Paths
An edge policy is incomplete if the origin remains directly reachable.
Revisão:
- Firewall rules.
- Security groups.
- Cloud load-balancer addresses.
- Origin DNS.
- Internal listener bindings.
- Partner networks.
- VPN routes.
- Service-mesh ingress.
- Staging systems.
- Disaster-recovery environments.
- NodePort and host-port services.
- Development tunnels.
- Management interfaces.
Restrict Outbound Requesters
For client-side exposure:
- Allow only required URL schemes.
- Restrict destinations to the intended trust model.
- Resolve and validate IP addresses.
- Revalidate destinations after redirects.
- Limit redirect count.
- Block loopback and link-local destinations unless explicitly needed.
- Restrict cloud metadata endpoints.
- Set connection and read timeouts.
- Enforce response-header boundaries.
- Separate user-controlled fetchers from critical processes.
These controls also improve SSRF resistance, but they do not replace the parser upgrade.
Limit Blast Radius
Useful containment controls include:
- Container memory limits.
- JVM maximum heap sizing.
- Multiple replicas.
- Failure-domain separation.
- Pod anti-affinity.
- Load-balancer health checks.
- Circuit breakers.
- Per-tenant queues.
- Worker isolation.
- Restart backoff.
- Connection pool limits.
A memory limit may cause an affected process to be killed earlier. That protects the node but not service availability.
Detection and Monitoring
CVE-2026-54399 does not have one reliable network signature. Detection should correlate HTTP, JVM, container, and infrastructure signals.
HTTP and Edge Metrics
Measure:
request header count
request header bytes
maximum request field line
response header count
response header bytes
maximum response field line
header parsing duration
header rejection count
connections closed before routing
Useful abnormal patterns include:
- Sudden increases in header count.
- Repeated generated field names.
- Large field values.
- A rise in HTTP 400 or 431 responses.
- Connection resets during field parsing.
- Requests that never reach a route.
- Large response headers from user-controlled upstreams.
- Many short-lived connections.
- A growing number of incomplete field sections.
- Rejections clustered around one service or listener.
A 431 response is not required for safe rejection. A parser or intermediary may return 400, close the connection, produce a framework exception, or translate the error into 502.
JVM Metrics
Monitor:
- Current heap usage.
- Old-generation occupancy.
- Allocation rate.
- Young collection frequency.
- Full collection frequency.
- Garbage-collection pause time.
- Percentage of time spent in GC.
OutOfMemoryError.- Thread count.
- Direct-buffer use.
- Process CPU.
- Request latency.
- Request throughput.
- Health-check failures.
Memory exhaustion may look like progressive collapse:
allocation rises
-> young GC increases
-> surviving objects reach old generation
-> full GC becomes frequent
-> latency rises
-> useful throughput falls
-> process fails or is killed
A safe initial JVM inspection command is:
jcmd <pid> GC.heap_info
A class histogram may provide more detail:
jcmd <pid> GC.class_histogram
Diagnostic commands can affect a busy process. Use them under an approved operational procedure.
Kubernetes Signals
Check pod state:
kubectl get pods -n production
Inspect a pod:
kubectl describe pod \
-n production \
webhook-worker-abc123
Look for:
Reason: OOMKilled
Exit Code: 137
Restart Count: increasing
Retrieve the previous instance’s logs:
kubectl logs \
-n production \
webhook-worker-abc123 \
--previous
An OOM kill does not prove exploitation of this CVE. Other causes include:
- Ordinary memory leaks.
- Traffic spikes.
- Large request bodies.
- Decompression.
- Caches.
- Image processing.
- Large query results.
- Batch jobs.
- Incorrect resource limits.
- JVM misconfiguration.
Correlate the time of the failure with header metrics, parser errors, destination logs, deployment history, and connection counts.
Safe Structured Logging
Avoid logging full headers. They may contain:
- Session cookies.
- Bearer tokens.
- Personal data.
- Internal topology.
- Authentication challenges.
- Digital signatures.
- API keys.
- Correlation identifiers.
A safer event is:
{
"event": "http_message_rejected",
"protocol": "HTTP/1.1",
"direction": "response",
"reason": "header_count_limit",
"service": "webhook-verifier",
"listener_or_client": "outbound-requester",
"remote_trust_zone": "user-controlled",
"header_count": 101,
"largest_field_line_bytes": 412,
"route_resolved": false
}
Record dimensions, not secrets.
Detection Signals and False Positives
| Sinal | Por que é importante | Common alternative cause | Useful correlation |
|---|---|---|---|
| Rapid heap increase | Indicates immediate memory pressure | Cache warm-up, large bodies, batch work | Header metrics, allocation rate, connection count |
| Full GC increase | Heap is under sustained pressure | Memory leak, undersized heap | Old-gen occupancy, release changes |
OutOfMemoryError | JVM allocation failed | Any heap or native memory problem | Stack trace, parser activity, traffic timeline |
OOMKilled | Container exceeded memory limit | Any process memory growth | Previous logs, pod metrics, request data |
| HTTP 431 increase | Edge or server rejects large headers | Large cookies or identity tokens | Client population, field name, field size |
| HTTP 400 increase | Parser rejects malformed input | Bots, client defects, invalid Host fields | Parser reason and route-resolution state |
| Connection reset before routing | Failure occurred early | TLS error, network timeout | Protocol-stage telemetry |
| High field count | Directly relevant to the CVE | Enterprise proxy metadata | Route baseline and trust zone |
| Long field line | Directly relevant to the CVE | JWT, cookie, Kerberos | Field name and redacted length |
| Large upstream response fields | Client-side exposure signal | Legitimate partner behavior | Destination ownership and redirects |
| Restart loop | Repeated availability failure | Bad deployment or health check | OOM events and inbound traffic |
| No application access log | Request may have failed before routing | Logging outage or sampling | Edge connection records |
Resposta a incidentes
First Hours
- Confirm whether an affected
httpcore5version is running. - Identify whether the process acts as a server, requester, or both.
- Preserve proxy, JVM, pod, and load-balancer telemetry.
- Capture the running image digest.
- Identify every HTTP/1.1 route.
- Apply temporary finite header limits at trusted entry points.
- Restrict direct-origin and alternate-listener access.
- Review outbound user-controlled destinations.
- Begin a corrected build.
- Avoid destructive reproduction.
Do not restart every affected process before collecting evidence unless availability requirements make an immediate restart necessary. Restarts can erase previous-container logs, transient parser errors, and useful runtime information.
Within One Day
- Deploy 5.4.3 or a later supported version.
- Verify all running instances use the corrected image.
- Search for multiple copies of
httpcore5. - Confirm explicit or corrected default limits.
- Validate request and response paths separately.
- Test legitimate large-header workflows.
- Review
httpcore5-h2for the related HTTP/2 issue. - Add temporary memory and parser alerts.
- Contact vendors for bundled commercial products.
- Document any backport exceptions.
Within One Week
- Add dependency policy to CI.
- Generate release-specific SBOMs.
- Tie SBOMs to image digests.
- Standardize HTTP resource limits.
- Create a bounded regression test.
- Document protocol translation.
- Remove unnecessary listeners.
- Review user-controlled outbound fetchers.
- Add incident runbooks for parser-level DoS.
- Confirm staging and disaster-recovery systems are remediated.
Validate the Remediation
A strong post-fix validation contains several independent proofs.
Version Proof
Show that the deployed process contains:
httpcore5-5.4.3.jar
or a later supported version, or a documented vendor backport.
Configuration Proof
Show either:
- The corrected defaults are in use.
- Explicit finite values are configured.
Path Proof
Show that:
- Every relevant request route reaches a corrected parser.
- Every relevant requester uses a corrected parser.
- Old deployments and alternate listeners are removed.
- Edge controls remain in place.
Behavior Proof
In an isolated environment:
- A normal message succeeds.
- A message below the boundary succeeds.
- A message slightly above the boundary is rejected.
- The process remains healthy.
- Memory returns to baseline.
- A normal message succeeds after rejection.
Compatibility Proof
Test:
- Cookies.
- JWTs.
- SSO.
- Kerberos.
- Partner signatures.
- Tracing.
- Forwarding headers.
- Proxy authentication.
- Large
Set-Cookieresponses. - Redirects.
Operational Proof
Confirm:
- No old image digest remains deployed.
- Autoscaling templates use the fixed image.
- Rollback manifests do not point to vulnerable releases.
- Disaster-recovery artifacts are updated.
- New alerts produce actionable evidence.
Prevent Dependency Regression
A corrected dependency can return through:
- A BOM downgrade.
- A copied service template.
- A vendor SDK.
- An emergency branch.
- An old Docker layer.
- A release rollback.
- A shaded command-line utility.
- A test tool copied into production.
- An outdated internal artifact mirror.
A simple CI check can inspect the resolved runtime tree:
#!/usr/bin/env bash
set -euo pipefail
dependency_tree="$(
mvn -q dependency:tree \
-Dscope=runtime \
-Dincludes=org.apache.httpcomponents.core5:httpcore5
)"
printf '%s\n' "$dependency_tree"
if grep -Eq \
'httpcore5:jar:(5\.[0-3]\.|5\.4\.[0-2](:|$)|5\.5-(alpha|beta1))' \
<<<"$dependency_tree"; then
echo "Affected Apache HttpCore version detected" >&2
exit 1
fi
This is illustrative. Text parsing of Maven output can be fragile. A production policy should use machine-readable dependency data when available and account for vendor backports.
An exception record should contain:
dependency_exception:
component: "org.apache.httpcomponents.core5:httpcore5"
detected_version: "5.4.2-vendor4"
vendor_backport: true
advisory_reference: "internal-or-vendor-advisory-id"
evidence_checksum: "sha256:..."
environments:
- production
owner: "platform-security"
review_date: "2026-10-01"
Exceptions without evidence or expiration become permanent blind spots.
Common Triage Mistakes
Confusing HttpCore with Apache HTTP Server
The vulnerable component is a Java library. Updating httpd does not update the affected Maven artifact.
Treating Every httpcore Finding as the Same Product
Core 4 and Core 5 use different Maven coordinates. Confirm the exact package before escalating or suppressing.
Treating Dependency Presence as Exploitability
Presence establishes patch relevance. It does not establish that attacker-controlled HTTP/1.1 reaches the parser.
Looking Only at Inbound Ports
A requester can parse attacker-controlled response headers. Webhook, crawler, import, SSRF, and proxy workflows are relevant.
Assuming Authentication Protects Parsing
Headers must normally be parsed before an application can authenticate the request.
Trusting a CDN Without Checking Bypass Routes
Direct origins, partner listeners, private load balancers, staging, and service-mesh routes may not share the public edge’s controls.
Closing the Ticket After Merging a Pull Request
The corrected dependency must reach the running artifact.
Relying on Container Memory Limits
A memory limit contains node-level damage but may make the affected service fail sooner.
Testing by Crashing Production
The expected vulnerability impact is denial of service. A successful destructive test creates the harm under investigation.
Configuring Only Total Header Bytes
The vulnerability description identifies both header count and header length. Track and limit both.
Configuring Only Header Count
One very large field can remain dangerous.
Configuring Only Line Length
A message can contain many short fields.
Raising Limits Globally for One Client
Use route-specific or partner-specific policies when possible.
Logging Full Headers During Investigation
Security telemetry should not become a credential leak.
Ignoring Error-Path Visibility
Requests rejected during parsing may never appear in application access logs.
CVE-2026-54428 and the HTTP/2 Path
Apache disclosed CVE-2026-54428 in the same period. It affects the HTTP/2 artifact:
org.apache.httpcomponents.core5:httpcore5-h2
The official advisory describes a memory-exhaustion condition in the HPACK decoder. Oversized compressed header blocks could be processed before HTTP/2 SETTINGS acknowledgement caused the configured header-list size limit to be applied. Apache identifies 5.4.2 and earlier and 5.5-beta1 and earlier as affected. (SecLists)
The two issues share a resource-consumption theme but affect different protocol paths:
| CVE | Protocol | Artifact | Root condition |
|---|---|---|---|
| CVE-2026-54399 | HTTP/1.1 | httpcore5 | Unlimited default header count and line length |
| CVE-2026-54428 | HTTP/2 | httpcore5-h2 | Header-list limit not enforced early enough during connection initialization |
A deployment can contain both artifacts. A public connection may use HTTP/2 at the edge and HTTP/1.1 at the backend. An internal service mesh may use HTTP/2 while a legacy partner route uses HTTP/1.1.
The practical response is to map protocols per hop and inspect both packages. Penligent’s CVE-2026-54428 analysis provides a separate treatment of the HPACK and SETTINGS timing issue. Apache’s advisory remains the authoritative source for affected versions and the vulnerability description. (Penligente)
What HTTP/2 Rapid Reset Adds to the Risk Model
CVE-2023-44487, known as HTTP/2 Rapid Reset, is technically different. It abuses HTTP/2 stream cancellation rather than HTTP/1.1 header parsing.
NVD describes it as server resource consumption caused by quickly resetting many streams, and records that it was exploited in the wild from August through October 2023. CISA published an alert urging organizations to apply relevant vendor updates and mitigations. (NVD)
Rapid Reset matters here because it demonstrates a broader principle: availability vulnerabilities below application business logic can become serious even when they do not execute code or steal data.
The three issues differ:
| Vulnerabilidade | Attacker-controlled resource | Expensive receiver behavior | Main response |
|---|---|---|---|
| CVE-2026-54399 | HTTP/1.1 field count and line length | Parsing, allocation, and field retention | Upgrade HttpCore and enforce finite HTTP/1 limits |
| CVE-2026-54428 | Compressed HTTP/2 field blocks | HPACK decoding before effective limit enforcement | Atualização httpcore5-h2 and verify decoded-size controls |
| CVE-2023-44487 | Rapid stream creation and cancellation | Stream creation, processing, and cleanup | Apply implementation patches and stream-rate controls |
The common defensive principle is early resource accounting. The receiver should stop processing when a defined budget is exceeded, before the input creates disproportionate internal state.
A Realistic Exposure Case
Consider a fictional multi-tenant webhook platform.
Its dependency scanner reports:
org.apache.httpcomponents.core5:httpcore5:5.4.2
CVE-2026-54399
The platform team initially lowers the priority because:
- The public API is behind a CDN.
- The CDN limits total request-header size.
- Every API route requires authentication.
- The worker containing HttpCore does not expose a public port.
The application actually has two distinct paths:
Public API:
client
-> CDN
-> API gateway
-> application server
Webhook verifier:
customer-configured URL
-> Java requester
-> customer-controlled response
The public request path may be substantially protected when:
- The CDN terminates the connection.
- It enforces finite field limits.
- The origin cannot be reached directly.
- Every alternate route uses the same controls.
Authentication is not the reason it is protected; early rejection at the edge is.
The verifier is different. A customer controls the destination server and therefore controls the HTTP response. The verifier parses the response through the affected httpcore5 version.
A complete remediation plan would:
- Confirm the vulnerable JAR is inside the verifier’s deployed image.
- Confirm HttpCore handles the outbound response.
- Review redirects and proxy behavior.
- Upgrade to 5.4.3 or later.
- Set explicit response parser limits.
- Configure connection and read timeouts.
- Restrict destinations according to the product’s trust model.
- Add response-header metrics.
- Test a slightly over-limit response in an isolated lab.
- Confirm ordinary customer endpoints remain compatible.
- Verify the corrected image digest in every region.
The dependency scanner found the package. Runtime and trust-boundary analysis found the meaningful exposure.
Prioritization Guidance
CVE-2026-54399 deserves higher priority when:
- An affected version runs in production.
- The process directly accepts untrusted HTTP/1.1.
- Users control destinations fetched by the process.
- The deployment is multi-tenant.
- The affected service is availability-critical.
- Edge limits are absent or unknown.
- An origin can bypass the edge.
- Memory headroom is low.
- The service handles many concurrent connections.
- The process shares a node with critical workloads.
- Restart behavior could create a crash loop.
- Parser-stage telemetry is absent.
httpcore5-h2is also affected.- The upgrade is technically simple.
Priority may be lower when:
- The dependency is conclusively test-only.
- The final production artifact does not contain it.
- The process does not use the affected parser.
- No untrusted request or response path exists.
- A supported vendor backport is installed.
- Every route is protected by verified lower limits.
Lower priority should not become permanent acceptance without evidence. A future feature, redirect behavior, listener change, or copied service template can make a previously unreachable parser reachable.
Operational and Compliance Impact
An availability-only CVE can still affect security and compliance obligations.
Potential consequences include:
- API downtime.
- Failed authentication flows.
- Lost webhook delivery.
- Delayed payment or order processing.
- Monitoring blind spots.
- Control-plane interruption.
- Customer SLA breaches.
- Incident-response activation.
- Autoscaling cost.
- Container restart storms.
- Loss of audit evidence during an outage.
- Reduced availability of security tooling itself.
A compliance record should avoid claiming confidentiality compromise unless separate evidence supports it. The correct issue description is an availability risk with possible operational and contractual consequences.
Useful remediation evidence includes:
- Affected asset inventory.
- Risk owner.
- Corrected version.
- Deployment date.
- Image digest.
- Configuration limits.
- Lab validation results.
- Monitoring changes.
- Exception documentation.
- Vendor advisory when applicable.
Long-Term Parser Security Lessons
CVE-2026-54399 is a narrow bug, but the design lesson applies far beyond HttpCore.
Every Parser Needs a Resource Budget
Define limits for:
- Input bytes.
- Elements.
- Individual element size.
- Nesting depth.
- Decompressed size.
- Parsing duration.
- Concurrent parser state.
- Retention duration.
- Retry count.
- Redirect count.
“Unlimited” should be a deliberate, reviewed exception.
Limits Must Be Applied Before Growth
A check performed after fully parsing and storing a structure is too late. The parser should account for a field before allocating or appending additional state.
Raw Bytes Are Not the Full Cost
Encoded input can expand into:
- Decoded characters.
- Objects.
- Indexes.
- Compression state.
- Temporary buffers.
- Framework wrappers.
- Logs and metrics.
Security limits should consider retained and decoded state, not only wire size.
Edge and Origin Policies Should Agree
A gateway that accepts more than the origin can safely parse creates a downstream failure risk. An origin that accepts far more than the edge needs creates unnecessary bypass exposure.
Outbound HTTP Is an Attack Surface
A client response parser receives untrusted data whenever the remote server is untrusted, compromised, user-selected, or influenced through redirects or SSRF.
Runtime Provenance Matters
A dependency ticket should tie together:
source
-> build
-> artifact
-> image
-> deployment
-> process
Without that chain, neither exposure nor remediation can be proven.
Frequently Asked Questions
What is CVE-2026-54399 in plain English?
- It is a denial-of-service vulnerability in Apache HttpComponents Core 5’s HTTP/1.1 parser.
- A remote HTTP peer can send too many header fields or an excessively long field line.
- The parser can consume enough memory to slow down, crash, or be terminated.
- The affected Maven artifact is
org.apache.httpcomponents.core5:httpcore5. - The direct documented impact is availability loss. (Openwall)
Is CVE-2026-54399 remote code execution?
- No authoritative Apache, CVE, or NVD record describes it as remote code execution.
- The documented weakness is uncontrolled resource consumption.
- The CISA-ADP score assigns High availability impact and no confidentiality or integrity impact.
- Reports should not claim code execution, secret theft, or privilege escalation without separate evidence. (NVD)
Which versions are affected?
- Apache identifies the 5.0 alpha through 5.4.2 range as affected.
- Apache also identifies 5.5 alpha through 5.5-beta1 as affected.
- Apache HttpComponents Core 5.4.3 contains the corrected finite defaults.
- Vendor packages may use backported fixes, so verify the vendor revision rather than comparing only the upstream version. (NVD)
What changed in version 5.4.3?
- The default maximum HTTP/1 header count changed from unlimited to 100.
- The default maximum HTTP/1 line length changed from unlimited to 8192 bytes.
- Apache’s release notes describe these values as defaults for incoming HTTP/1 messages.
- The source commit changes the two constants from
-1to finite values. (GitHub)
How do I know whether my application is truly exposed?
- Confirm the exact
httpcore5version in the deployed runtime. - Determine whether the process uses HttpCore for HTTP/1 request or response parsing.
- Map every CDN, gateway, load balancer, ingress, service-mesh, partner, internal, and direct-origin path.
- Review whether users control URLs or upstream servers contacted by an HttpCore requester.
- Check custom parser limits.
- Use a bounded isolated test rather than a production memory-exhaustion attempt.
Can a WAF or reverse proxy mitigate the issue?
- It can reduce request-side exposure when it parses and rejects excessive headers before forwarding.
- It cannot protect routes that bypass it.
- It does not automatically protect an outbound HttpCore requester.
- Product-specific settings for field count, line length, total bytes, timeout, and connection limits must be verified.
- Treat edge filtering as defense in depth, not a replacement for upgrading.
Should I test the CVE against production?
- Do not attempt to exhaust memory in production.
- The expected successful outcome of exploitation is a denial of service.
- Use version evidence, runtime evidence, path analysis, and configuration evidence for production triage.
- Perform behavioral boundary tests only in an isolated environment with explicit authorization.
- Test slightly above the configured limit rather than attempting maximum load.
What should I monitor?
- Header count and header bytes.
- Largest field-line size.
- Parser rejection events.
- Connections terminated before route resolution.
- JVM heap occupancy and allocation rate.
- Garbage-collection frequency and pause time.
OutOfMemoryError.- Kubernetes
OOMKilled. - Container restarts.
- Large response headers from untrusted upstreams.
- HTTP 400, 431, 502, and connection-reset trends.
Do I also need to check CVE-2026-54428?
- Yes, when the deployment includes
org.apache.httpcomponents.core5:httpcore5-h2. - CVE-2026-54428 affects the HTTP/2 HPACK decoder rather than the HTTP/1.1 parser.
- The affected version ranges overlap.
- A service may use HTTP/1.1 and HTTP/2 on different hops.
- Inventory both artifacts and map the protocol at every connection boundary. (SecLists)
What evidence proves the fix is complete?
- A corrected runtime JAR or supported vendor backport.
- The immutable deployed image digest.
- Confirmation that all replicas and regions use that image.
- Finite parser limits.
- Bounded request-side and response-side test results.
- Stable memory during rejection.
- Successful legitimate high-header workflows.
- Updated monitoring.
- Removal or remediation of old images, rollback manifests, staging systems, and alternate listeners.
Closing Assessment
CVE-2026-54399 is not complicated because the code change is large. It is complicated because HTTP libraries can sit in more places than vulnerability scanners can see.
The Apache correction is clear: replace unlimited HTTP/1 default header boundaries with a maximum of 100 fields and 8192 bytes per line, and upgrade affected deployments to 5.4.3 or later. (GitHub)
A complete response should follow a disciplined chain:
identify the exact artifact
-> confirm the deployed version
-> determine the parser role
-> map request and response paths
-> upgrade
-> enforce finite limits
-> test bounded rejection
-> confirm compatibility
-> preserve remediation evidence
Do not prove a denial-of-service vulnerability by causing a production denial of service. Prove that the vulnerable component is gone, the parser has finite boundaries, abnormal input is rejected early, legitimate traffic still works, and every relevant runtime path has been accounted for.

