DEV Community

SorrelThorncroft
SorrelThorncroft

Posted on

CVE-2026-97205: An 8-Bit Counter and 256 Pending AIO Operations

CVE-2026-97205: An 8-Bit Counter and 256 Pending AIO Operations

The NGINX use-after-free fixed in 1.30.6 and 1.31.7 is a textbook case of a counter that needed a bound and never got one. CVE-2026-97205 requires aio enabled together with SSI pages that use include virtual commands, and its root cause is a single byte.

The mechanism

When aio is on, file operations for a request become asynchronous. Each pending asynchronous operation on that request increments a counter in the request structure. That counter is eight bits wide, and nothing checks it before incrementing.

At 256 pending operations the counter wraps to zero. Once the counter reads zero, NGINX concludes that no asynchronous work remains for the request and is free to release it. The operations themselves are still outstanding, and they still hold pointers into the memory that was just returned to the pool. That is the use-after-free.

F5 rates the flaw 9.2 Critical on CVSS v4.0, matching the other two memory bugs in the release, and credits a researcher it names as Cyberlanc3r.

Why SSI makes it reachable

Reaching 256 pending operations on a single request is not something a normal client can arrange by issuing one request. SSI changes that. A page containing include virtual commands causes NGINX to issue subrequests, and those subrequests can run their included requests in parallel. A page with enough includes, on a server with aio enabled, can plausibly drive the pending count toward the wrap.

The dependency on both aio and SSI is why this flaw is not a default-configuration problem. aio is off unless configured, and SSI processing requires the ssi directive on the location. Deployments that serve static content with aio but never enable SSI are outside the affected pattern.

Affected versions

The advisory range is 0.8.11 through 1.31.6, a span that covers more than a decade of releases. Any of those versions with aio and SSI in combination is the targeting condition.

Impact

Use-after-free in a worker process gives an attacker a corrupted heap in a process that handles traffic. The immediate effect can be a crash, which is a denial of service, or memory corruption that in the right layout becomes code execution. Because the freed object is a request structure rather than a fixed global, and because the outstanding operations still write through their pointers, the corruption is not a single deterministic write.

For an operator the distinction that matters is availability versus integrity. A worker that crashes on a crafted SSI request is recoverable: NGINX respawns workers and the service continues degraded. A worker whose heap has been shaped by an attacker is a different problem, and it is the one the 9.2 score reflects.

Remediation

Upgrade to 1.30.6 or 1.31.7.

F5's workaround is direct: turn aio off, or stop serving SSI pages. Either removes one half of the precondition pair. Turning aio off is the safer of the two for a busy static-content server, because it eliminates the asynchronous code path rather than trying to audit every SSI page.

For deployments that genuinely need both, the interim control is to restrict who can request SSI-processed content, so that the expensive include graph is not reachable from untrusted clients. That reduces exposure without pretending the bug is fixed.

Verifying exposure

Run nginx -T and look for aio on; in any location or server block. For each occurrence, check whether ssi on; appears in the same or an enclosing context, and whether the served pages contain include virtual directives. A location with aio but no SSI is not exposed to this flaw.

The bug does not produce a visible signature. A scanner that fingerprints NGINX version 1.30.5 cannot tell whether aio and SSI are in use, which is why the configuration review is the only reliable test.

Sources

Top comments (0)