June 11, 2025·4 min read·engineeringvalkeysecuritypersistencetooling

Valkey repairs filename handling in its AOF checker

Valkey 8.1.2 fixes CVE-2025-27151 in valkey-check-aof. The patch validates a path before copying it into a fixed-size buffer and also corrects maintenance-command behavior.

A recovery utility has to validate its own inputs before it can validate a database file. In valkey-check-aof, the filename passed on the command line reached a copy into a fixed-size stack buffer without the required length check. Valkey 8.1.2, released today, fixes that problem as CVE-2025-27151. Maintainers assign high urgency and recommend updating as soon as possible when the tool is used.

The correction in pull request 2146 is small. It rejects a path whose bounded measured length exceeds PATH_MAX, before copying the path and deriving its directory. The defect is in the checker executable's handling of its filename argument. Describing it as a remotely triggered database-command flaw would misidentify both the input and the affected program.

I prefer Valkey for compatible Redis semantics, but the operational value of that choice includes the utilities distributed with the server. A recovery binary is part of the installation even when applications never call it. Keeping it current matters to the people who inspect persistence files.

A valid copy needs room for the terminator

The released checker source declares a temporary filename buffer with PATH_MAX + 1 bytes. One extra byte permits a terminating zero after a path of maximum permitted length. The subsequent copy includes that terminator, so checking only that an argument exists cannot establish that the destination is large enough.

The new check uses strnlen with a bound one byte beyond PATH_MAX. That permits it to distinguish an acceptable path from an excessive one without scanning arbitrarily far to determine the full length. When the result exceeds the permitted path length, the checker reports an error and follows its invalid-arguments path.

The ordering is the relevant property. Validation occurs before the memcpy, and the destination's capacity accounts for the same terminator that the copy includes. The patch does not rely on the filesystem rejecting the filename later. An invalid path can already cause trouble during userspace preparation, before a file-opening operation gets a chance to refuse it.

There is a reason the tool makes a temporary copy. The implementation comments explain that glibc's dirname may modify its argument. Deriving the directory therefore needs mutable storage separate from the original filename. A sensible reason for copying a string still leaves the copy responsible for proving that its destination can hold it.

This is also why the correction is about an argument rather than the contents of an AOF record. A file can be well formed while the supplied filename exceeds the program's temporary buffer. Conversely, rejecting an excessive path says nothing about whether the file at an acceptable path contains valid persistence data. These validations happen at different stages.

The utility remains a separate maintenance operation

The checker accepts ordinary checking and repair-related modes. Its usage describes --fix and a timestamp truncation option as well as a filename. The security check runs after argument selection, so the selected path receives the same validation regardless of which supported form supplied it. There is no requirement to use a special invocation to activate the protection.

For a normal inspection, the command retains its familiar shape.

valkey-check-aof appendonly.aof

That example describes invocation syntax, not a claim that a particular installation uses that filename. The checker dispatches to different verification routines according to the detected input type, including multipart AOF and an RDB preamble. Filename validation occurs before that dispatch, which keeps the correction independent of the later format-specific verification.

The urgency statement is appropriately conditional on use of the tool. An inventory limited to the running server version can miss a copied utility used by a recovery procedure. The executable performing the operation needs the correction, so the relevant version is the checker actually invoked. That follows directly from where the patch lives.

Diagnostic output needs correct escaping

The same release includes a MONITOR escaping correction. Its string-formatting path groups printable characters to reduce copying, but printable quotes and backslashes still need escaping. The patch excludes those characters from the grouped fast path so they receive the intended special handling.

The regression test sends an argument containing several special characters and checks the resulting monitor representation. This establishes a useful boundary between the bytes supplied to a command and the text used to display those bytes. An optimization that copies printable chunks cannot assume every printable character is safe inside the output format's quoting rules.

For an operator inspecting a command stream, correct representation is part of diagnostic accuracy. Mis-escaped output can make argument boundaries or literal backslashes ambiguous. The fix changes how the server reports commands, independently of the AOF checker's filename validation.

The release also fixes sampling in sparse hash tables. The sampler requests fewer entries when the table is sparse and changes how scan starting points are chosen. That addresses high CPU consumption while selecting a random element in a skewed layout. It is another case where the amount of work depends on an internal representation that is invisible in a command's arguments.

Paused clients need the correct resumption path

Pull request 2117 restricts CLIENT UNBLOCK when the target's blocking type lacks a timeout callback. A client paused by CLIENT PAUSE is one such case. Attempting timeout-based unblocking previously risked a panic, while error-based unblocking could deliver an unexpected error to an ordinary command.

The correction returns zero when that kind of unblocking is inappropriate. CLIENT UNPAUSE remains the operation for releasing the pause. The distinction expresses why a client stopped by a server-wide processing policy is different from a command waiting for a key to become ready.

I find these maintenance fixes relevant for the same reason as the checker correction. Operational commands often execute when a service is already in a less ordinary state. Their implementations need accurate distinctions between input formats, diagnostic representations and the reason a client is blocked. Valkey 8.1.2 supplies concrete corrections in each of those paths, with the checker vulnerability determining its stated upgrade urgency.