February 24, 2026·6 min read·engineeringvalkeysecurityprotocolnetworking

Valkey 9.0.3 repairs request state and protocol boundaries

Valkey 9.0.3 addresses response injection and two denial-of-service flaws. Its advisories disagree about some fixed versions, so the release needs a more precise reading than its security checklist provides.

An empty request could leave Valkey with the wrong idea of how to parse the next request. The subsequent input could then trigger an assertion and terminate the server. Authentication did not protect this path because the defect occurred while processing incoming protocol data. The failure described in CVE-2026-27623 is a state-management error across requests, with a server-wide consequence.

The Valkey 9.0.3 release, published on GitHub on February 24, lists that fix alongside Lua response injection and a malformed cluster-bus packet crash. The bundled release notes at the 9.0.3 tag carry a February 23 heading. GitHub records publication at 04:06 UTC on February 24. This post uses the GitHub publication date and preserves that distinction.

The fixed-version information also needs care. The Lua advisory names 9.0.2 as patched even though 9.0.3 lists the vulnerability under its security fixes. For the cluster-bus flaw, the advisory names 9.0.3 while the CVE record names 9.0.2. Those disagreements prevent a confident claim that all three flaws first became fixed in the same release. They do not diminish the release's explicit recommendation to apply its security fixes as soon as possible.

Empty requests retained the wrong parser state

The request-parser advisory describes CVE-2026-27623 as a pre-authentication denial of service. Valkey failed to reset networking state after an empty request. A later request could then appear to violate an internal invariant, causing the process to abort. The advisory credits NVIDIA Networking Security researchers Daniel Bransky and Eliya Cohen.

The repair is concrete in the 9.0.3 networking implementation. The empty-inline-request branch resets the client and explicitly clears the request type before returning. Omitting the explanatory comment, that branch is:

if (c->read_flags & READ_FLAGS_INLINE_ZERO_QUERY_LEN) {
    resetClient(c);
    c->reqtype = 0;
    return PARSE_OK;
}

The same file clears reqtype after resetting a client whose multibulk request length is nonpositive. These assignments make the request-type reset visible at the paths that finish processing those inputs. Calling a general reset function and assuming it restores every parser-specific field would miss the explicit state transition in the fixed code.

An assertion is useful when the implementation encounters a condition that should be impossible. Here, stale state let network input produce that condition. The distinction matters because rejecting a malformed request and aborting a server have different scopes. Rejecting the request concerns the connection, while aborting interrupts every client served by the process. Valkey's advisory describes the second outcome.

Both the advisory and the CVE-2026-27623 record identify versions starting at 9.0.0 and before 9.0.3 as affected. Both name 9.0.3 as fixed. This flaw therefore supplies an unambiguous reason for affected 9.0 installations to move beyond 9.0.2, regardless of the disagreements surrounding the other vulnerabilities.

Lua errors could alter the response stream

CVE-2025-67733 affects the opposite direction of protocol processing. The Lua error-reply advisory says error handling did not handle null characters properly. A malicious user could use scripting commands to inject arbitrary information into the response stream for a client. The possible consequences include corrupt or tampered data returned to other users of that same connection.

The connection qualification is significant. The advisory does not describe an ability to rewrite replies on every connection to the server. It identifies a shared response stream as the place where one user's output can affect another user's view. Any design that shares a connection across callers must therefore consider whether an untrusted scripting result can alter the structure of what later callers receive.

This is also why an error message belongs within a protocol's correctness requirements. Error text can contain data influenced by a caller, but the bytes still pass through a client parser. If that parser receives a stream whose structure no longer matches the intended reply, application code can draw conclusions from data that the server did not intend to return as that operation's result. Returning an error does not excuse the server from preserving its response format.

Valkey remains my default where Redis semantics are wanted. Its protocol compatibility matters because existing clients and operational habits can carry over. That preference makes errors in the response stream particularly relevant to me. Compatibility is useful only if a client can continue to interpret responses according to the protocol, including when a script fails.

The Lua advisory lists affected versions as 9.0.1 and below in its affected-version field. Its patched-version field names 9.0.2, 8.1.6, 8.0.7, and 7.2.12. The CVE-2025-67733 record gives the same fixed versions and describes the 9.0 affected range as starting at 9.0.0 and ending before 9.0.2. Meanwhile, the 9.0.3 release includes this CVE in its security list.

Listing a fix in 9.0.3 does not by itself establish that 9.0.2 lacked it. The advisory and CVE record explicitly say otherwise. An account of this release should preserve that information instead of converting the release checklist into an unsupported first-fixed-version claim. The advisory provides no additional mitigation for the Lua flaw.

Cluster-bus extensions needed bounds checks

The cluster-bus advisory identifies CVE-2026-21863 as an out-of-bounds read in packet processing. Before reading a cluster-bus ping extension, the implementation did not validate that the extension lay within the packet's buffer. An invalid packet could consequently cause an access outside allocated memory and terminate the Valkey process. The advisory credits 0x Kato with the discovery.

This defect has a different access condition from the client-request parser bug. An attacker must be able to reach the cluster-bus port. The advisory recommends keeping that port away from end users and protecting it with its own network ACLs. Access controls for application clients cannot be assumed to describe who can send traffic to this separate port.

The buffer boundary is the important mechanism. A packet can carry an indication that an extension exists without supplying a valid extent for the receiver to read. The receiver must establish that the claimed data fits within the bytes it actually has. Otherwise, a packet's internal description becomes permission to read beyond that packet. The advisory identifies exactly that missing validation here.

For this CVE, the published version statements conflict directly. The GitHub advisory says versions through 9.0.2 are affected and lists 9.0.3 as patched. It also lists 8.1.6, 8.0.7, and 7.2.12 as patched. The CVE-2026-21863 record instead says 9.0.2 fixes the issue and marks the 9.0 affected range as ending before 9.0.2. Its fixed versions for the other branches match the advisory.

Neither statement should disappear from an upgrade discussion. An operator reading the CVE record alone could judge a 9.0.2 installation fixed, while an operator reading the GitHub advisory would judge it affected. The 9.0.3 release also lists the cluster-bus fix. For an affected deployment on the 9.0 branch, adopting 9.0.3 avoids relying on the disputed status of 9.0.2. The linked sources allow that decision to be checked against the project's current guidance.

ACL transitions and reply flushing also receive fixes

The release includes a crash fix for MODULE UNLOAD when ACL rules reference a module command and subcommand. Another change fixes an assertion during ACL LOAD when the current user loses channel permissions. These entries concern administrative transitions in which existing permission references interact with changing server state. They are separate from the vulnerabilities that occur while handling network input.

The final listed bug fix addresses replies that sometimes failed to flush when I/O threads were busy. Its significance is observable at the client. A server may have processed a request but still leave the client waiting if the reply does not flush. The release note does not provide a latency measurement or establish that every delayed response had this cause, so neither conclusion follows from the entry.

My preference for Valkey includes its continued development of multithreaded I/O. That makes the reply-flushing fix relevant alongside the parser repair. Concurrency changes must preserve the client's ability to receive a response, and networking state must remain valid between requests. These fixes address concrete failures in those obligations without changing the semantics an application expects from its key-value operations.

For deployment decisions, 9.0.3 is the new security release to examine on this branch. The parser flaw has a consistent 9.0.3 fixed-version statement across its advisory and CVE record. The Lua sources name 9.0.2, and the cluster-bus sources disagree between 9.0.2 and 9.0.3. Keeping those statements attached to their individual CVEs lets an operator compare the installed build with the newest available release without silently resolving contradictory security metadata.