Redis
Summary
ExpandRedis is a high-performance, in-memory data structure server whose codebase encompasses the core server engine, embedded dependencies, extension modules, and supporting utilities. The audited surface spans the server's core infrastructure — including the ACL subsystem, event loop, networking primitives, AOF persistence, and cluster slot migration — alongside embedded dependencies such as jemalloc (memory allocator), Lua 5.1.5 (scripting engine), hiredis (client library), and HdrHistogram (latency tracking). The codebase also includes a vector similarity search module implementing HNSW graph-based indexing with SIMD-optimized distance functions, quantization strategies, and a filter expression evaluator. Build and CI infrastructure, development utilities, and example module code round out the reviewed scope, totaling well over 100,000 lines of C, Python, Ruby, and shell across several hundred files.
The codebase demonstrates mature, layered security engineering across its components. The ACL subsystem implements SHA256 password hashing with constant-time comparison via `time_independent_strcmp`, enforces granular command, key, and channel permissions through a selector model, and isolates cluster-internal authentication from the user namespace by restricting space characters in usernames. The embedded Lua interpreter has been hardened with three targeted modifications: bytecode loading is disabled in `ldo.c` to prevent crafted-bytecode sandbox escapes, the OS standard library is restricted to `os.clock`, and a readonly table mechanism protects critical tables from script modification. File persistence uses atomic temp-file-then-rename patterns with fsync, file descriptors are opened with CLOEXEC flags throughout, and jemalloc provides witness-based lock ordering, safety-check hooks for heap corruption detection, and a configurable sanitizer subsystem with guard pages and junk filling. The hiredis protocol parser validates array bounds and integer values, enforces TLS 1.2 minimum version, and the HNSW module's RDB serialization employs a 128-bit salted cryptographic accumulator to verify bidirectional link integrity.
The overall security posture of the Redis codebase is strong, reflecting years of production hardening across both the core server and its dependencies. Four findings were identified across the entire audit surface — one at low-severity and three at low-severity. The most significant is a heap buffer over-read in the vector sets module's RDB deserialization path, where projection matrix loading lacks size validation against the computed expected size, a notable oversight given that the same function correctly validates vector data sizes. A missing bounds check on HNSW node levels during deserialization presents an additional risk in the same module's RDB load path. In the hiredis client library, an integer type mismatch in the variadic command formatter `redisvFormatCommand` uses `int` to track buffer sizes that should be `size_t`, creating a theoretical heap buffer overflow for payloads exceeding 2GB. A low-severity insecure temporary file vulnerability exists in `install_server.sh`, where predictable `/tmp/${REDIS_PORT}.conf` paths in a root-privileged script create a classic symlink attack vector. These findings are narrowly scoped and do not indicate systemic weaknesses; the vast majority of the codebase — including the full jemalloc allocator, Lua interpreter, HdrHistogram library, core server ACL and persistence subsystems, and all CI/build infrastructure — produced zero findings.
Findings
4 issues identified
Heap Buffer Over-Read in RDB Deserialization of Projection Matrix
modules/vector-sets/vset.c:VectorSetRdbLoad
View Details
Description
When loading a vector set with a projection matrix from RDB, the projection matrix blob size is not validated (RedisModule_LoadStringBuffer called with NULL length parameter). The subsequent memcpy uses a computed matrix_size that may exceed the actual blob size, causing a heap buffer over-read. Additionally, the matrix_size computation (sizeof(float) * input_dim * output_dim) can overflow size_t when both dimensions are attacker-controlled via crafted RDB data, leading to a small allocation followed by out-of-bounds access in applyProjection().
Impact
Crash (DoS) from accessing unmapped memory during RDB load or subsequent VADD/VSIM operations. Potential information disclosure if over-read heap data is incorporated into projection matrix values returned via VEMB. Exploitable via diskless replication from a malicious master, which the module explicitly supports.
Recommendation
Capture the blob length from RedisModule_LoadStringBuffer and validate it matches the expected matrix_size. Add an integer overflow check before the matrix_size multiplication.
Fix
The fix adds two safeguards: (1) an integer overflow check using SIZE_MAX before computing matrix_size, preventing wrap-around allocation; (2) capturing the actual blob length from RedisModule_LoadStringBuffer and validating it matches the expected matrix_size before memcpy, preventing heap over-read from undersized blobs. Both error paths use the existing ioerr cleanup label.
modules/vector-sets/vset.c
Insecure Temporary File in Root-Privileged install_server.sh
utils/install_server.sh:149
View Details
Description
The install_server.sh script runs as root and creates a temporary file at a predictable path /tmp/${REDIS_PORT}.conf. Since REDIS_PORT defaults to 6379 and is numeric, the path is entirely predictable. A local attacker can create a symlink at this path pointing to a sensitive system file, causing root to overwrite it when the script runs.
Impact
Local privilege escalation via arbitrary file overwrite as root. An attacker can overwrite /etc/passwd, /etc/shadow, cron files, or init scripts by placing a symlink at the predictable temp file path before the script executes.
Recommendation
Replace the predictable temporary file path with mktemp to create a unique, unpredictable filename that atomically prevents symlink attacks.
Fix
mktemp creates a temporary file with a unique, random name and atomically ensures it does not already exist, preventing symlink race conditions. The || exit 1 ensures the script aborts if temp file creation fails.
utils/install_server.sh
Integer overflow in redisvFormatCommand leads to heap buffer overflow
hiredis.c:redisvFormatCommand
View Details
Description
The redisvFormatCommand function uses ‘int’ for totlen and pos variables that accumulate size_t values from bulklen() and hi_sdslen(). When formatting commands with very large binary arguments (via %b), totlen can overflow the signed 32-bit int range, causing hi_malloc to allocate an undersized buffer. Subsequent memcpy writes overflow the heap buffer.
Impact
Applications passing large binary data (>2GB aggregate) through the variadic format API could trigger a heap buffer overflow, potentially leading to arbitrary code execution. Requires attacker influence over command data sizes.
Recommendation
Change totlen and pos from int to size_t to match the actual data sizes being accumulated. Add an overflow check before the malloc allocation.
Fix
Changing totlen and pos from int to size_t prevents the integer overflow when accumulating large buffer sizes. This matches the types used by bulklen() and hi_sdslen(), and is consistent with how redisFormatCommandArgv handles the same computation.
deps/hiredis/hiredis.c
Missing HNSW node level bounds check during deserialization
modules/vector-sets/hnsw.c:1534
View Details
Description
hnsw_insert_serialized() extracts the node level as an 8-bit value (up to 255) from serialized parameters without validating it against HNSW_MAX_LEVEL (16). This allows crafted RDB data (via diskless replication or RESTORE) to create nodes with up to 256 layers, each allocating link arrays up to HNSW_MAX_M*4 pointers, causing ~32MB memory amplification per malicious node.
Impact
A malicious replication source or crafted RDB file can cause severe memory amplification during data loading, potentially triggering an OOM crash of the Redis server. The module explicitly supports async replication loading (REDISMODULE_OPTIONS_HANDLE_REPL_ASYNC_LOAD), making this a reachable attack surface.
Recommendation
Add a bounds check on the deserialized level value against HNSW_MAX_LEVEL before creating the node, rejecting values that cannot be produced through normal operation.
Fix
Adds a bounds check ensuring the deserialized node level does not exceed HNSW_MAX_LEVEL (16), matching the constraint enforced by random_level() during normal insertion. Nodes with higher levels cannot exist through legitimate operation and indicate corrupted or malicious serialized data.
modules/vector-sets/hnsw.c
Conclusion
ExpandThe Redis codebase exhibits exceptional code quality and security maturity across its core server, embedded dependencies, and extension modules. The architectural decisions consistently favor defense-in-depth: jemalloc’s multi-layered caching with witness-ranked lock ordering, the Lua sandbox’s three independent escape-prevention mechanisms, the ACL system’s separation of cluster and user authentication namespaces, and the HNSW module’s cryptographic integrity verification of serialized graph structures all reflect deliberate security engineering rather than incidental correctness. Memory management is handled with discipline throughout — Redis’s tracked allocator is properly integrated via shim headers in dependencies, overflow checks are present in allocation size computations, and bounds validation is applied at protocol parsing boundaries in both the server and client library.
The four findings identified represent isolated gaps in otherwise carefully written code rather than systemic vulnerabilities. The HNSW module’s missing projection matrix size validation (H-1) and absent node level bounds checking (M-3) in the RDB load path are the most pressing concerns, as the module explicitly opts into handling async replication loads, meaning a compromised replication master could deliver a malformed RDB payload that triggers a heap over-read or unbounded memory allocation. The hiredis integer type mismatch in redisvFormatCommand (M-2) is a latent vulnerability that becomes exploitable only with aggregate payloads exceeding 2GB, an uncommon but not impossible scenario in large-scale deployments. The insecure temporary file in install_server.sh (M-1) is a local privilege escalation vector on multi-user systems where the script is executed.
The codebase is well-suited for production deployment. All four identified fixes are minimal, targeted changes: adding a size validation check in the HNSW RDB loader following the pattern already used for vector data in the same function, introducing a bounds check on deserialized node levels, widening the int type to size_t in the hiredis command formatter, and replacing the predictable temporary file path with mkstemp in the installation script. No architectural changes are required. Future audit passes should prioritize complete coverage of the truncated files in src/cluster_asm.c and the remaining jemalloc source files, as well as the hdr_decode_compressed deserialization function declared but not implemented in the reviewed HdrHistogram headers.
On-Chain Verification
Compare these values with the on-chain attestation
Verify: download the markdown and compare the hash
sha256sum redis.md
Legal Disclaimer: This report covers the code submitted for analysis. It does not account for infrastructure, deployment configuration, third-party dependencies, or changes made after the audit date. Automated analysis may produce false positives or miss context-dependent vulnerabilities. audited.xyz provides this report “as is” without warranty of any kind.