CVE-2026-82677 Overview
CVE-2026-82677 is a double free vulnerability in Valkey 9.1.0, an open-source in-memory data structure store. The flaw resides in the moduleTimerHandler function within src/module.c, part of the Module Timer Subsystem. When a module timer callback invokes ValkeyModule_StopTimer() on the currently firing timer, the handler then attempts to free the same timer object again, resulting in memory corruption ([CWE-119]). The vulnerability requires high privileges and user interaction to exploit, but a public proof-of-concept exists.
Critical Impact
An authenticated attacker with the ability to load or interact with modules can trigger a double free in the Valkey server, potentially leading to memory corruption and process instability.
Affected Products
- Valkey 9.1.0
- Valkey deployments using modules that register timers via the Module Timer Subsystem
- Downstream distributions packaging vulnerable Valkey releases
Discovery Timeline
- 2026-08-31 - CVE-2026-82677 published to NVD
- 2026-08-31 - Last updated in NVD database
Technical Details for CVE-2026-82677
Vulnerability Analysis
The vulnerability is a double free ([CWE-119]) in the Valkey module timer dispatch loop. Valkey exposes an API that lets modules schedule callbacks to run after a delay. Timers are tracked in a radix tree keyed by expiration time. When a timer fires, moduleTimerHandler invokes the registered callback, then removes the timer entry from the radix tree and calls zfree(timer).
If the callback itself calls ValkeyModule_StopTimer() on the currently firing timer, that API removes the radix tree entry and frees the timer object during the callback. Control then returns to moduleTimerHandler, which still holds the freed pointer and performs a second zfree on it. Additional mutations of the tree from within the callback can also invalidate ri.key, compounding the memory safety issue.
Root Cause
The root cause is a lifetime and ownership violation between moduleTimerHandler and callback-driven timer cleanup paths. The handler assumes exclusive ownership of the timer object across the callback boundary, but the exposed ValkeyModule_StopTimer() API allows the callback to free the same object mid-flight.
Attack Vector
Exploitation requires an attacker to influence a loaded module whose timer callback triggers ValkeyModule_StopTimer() on its own firing timer. The attack can be initiated over the network but requires high privileges and user interaction, which limits practical exploitability. Successful exploitation causes heap corruption in the Valkey process, most commonly resulting in denial of service.
memcpy(&expiretime, ri.key, sizeof(expiretime));
expiretime = ntohu64(expiretime);
if (now >= expiretime) {
+ /* Preserve the timer ID before invoking the callback. The callback
+ * may call ValkeyModule_StopTimer() on the currently firing timer,
+ * which removes the radix-tree entry and frees the timer object.
+ * Also, other tree mutations in the callback can invalidate ri.key. */
+ ValkeyModuleTimerID current_id;
+ memcpy(¤t_id, ri.key, sizeof(current_id));
+
ValkeyModuleTimer *timer = ri.data;
ValkeyModuleCtx ctx;
moduleCreateContext(&ctx, timer->module, VALKEYMODULE_CTX_TEMP_CLIENT);
selectDb(ctx.client, timer->dbid);
timer->callback(&ctx, timer->data);
moduleFreeContext(&ctx);
- raxRemove(Timers, (unsigned char *)ri.key, ri.key_len, NULL);
- zfree(timer);
+
+ /* Skip cleanup if the callback already stopped this timer. */
+ void *live = NULL;
+ if (raxFind(Timers, (unsigned char *)¤t_id, sizeof(current_id), &live) && live == timer) {
+ raxRemove(Timers, (unsigned char *)¤t_id, sizeof(current_id), NULL);
+ zfree(timer);
+ }
} else {
/* We call ustime() again instead of using the cached 'now' so that
* 'next_period' isn't affected by the time it took to execute
Source: Valkey commit b349fe2. The patch preserves the timer ID before the callback runs, then verifies the timer still exists in the radix tree before removing and freeing it.
Detection Methods for CVE-2026-82677
Indicators of Compromise
- Unexpected Valkey process crashes or restarts with SIGABRT or SIGSEGV originating from zfree or heap allocator assertions.
- Heap allocator diagnostics such as jemalloc <jemalloc>: Invalid dallocx() or glibc double free or corruption messages in Valkey logs.
- Module load events for third-party modules that register timers via ValkeyModule_CreateTimer and internally invoke ValkeyModule_StopTimer.
Detection Strategies
- Run Valkey under AddressSanitizer in staging to surface double-free calls in moduleTimerHandler before production deployment.
- Monitor server logs for repeated crash-restart cycles correlated with module timer activity, which can indicate exploitation attempts or triggering conditions.
- Audit installed Valkey modules and inventory those that use the timer API; flag any module whose callbacks call ValkeyModule_StopTimer on the firing timer.
Monitoring Recommendations
- Alert on Valkey process termination and unclean restarts through your host telemetry pipeline.
- Track MODULE LOAD and MODULE UNLOAD commands and correlate them with subsequent instability.
- Forward Valkey and system logs to a central data lake for pattern analysis across the fleet.
How to Mitigate CVE-2026-82677
Immediate Actions Required
- Apply commit b349fe2821e3998534b1454c1b64a478daf8c6b7 from the Valkey repository or upgrade to a Valkey release that includes it.
- Restrict MODULE LOAD privileges to trusted administrators by enforcing ACLs and disabling module loading for untrusted clients.
- Review all loaded third-party modules and remove those not required for production workloads.
Patch Information
The fix is delivered in commit b349fe2821e3998534b1454c1b64a478daf8c6b7 via Pull Request #4211, which addresses Issue #4200. The patch preserves the timer ID before the callback executes, then uses raxFind to confirm the timer still exists before calling raxRemove and zfree. This eliminates the double free when a callback stops its own timer.
Workarounds
- Disable or unload any Valkey modules whose timer callbacks may invoke ValkeyModule_StopTimer on the currently firing timer until the patch is applied.
- Restrict network access to the Valkey port so that only trusted application servers can authenticate and issue module-related commands.
- Enforce Valkey ACLs to remove the MODULE command category from all non-administrative users.
# Restrict the MODULE command family via Valkey ACL
valkey-cli ACL SETUSER default -@module
valkey-cli ACL SETUSER admin on >STRONG_PASSWORD ~* +@all
# Verify the patched commit is present in your build
git -C /path/to/valkey log --oneline | grep b349fe2821e3998534b1454c1b64a478daf8c6b7
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

