Skip to content

Security: fix high-severity vulnerabilities (v0.11.6) - #38

Merged
mack42 merged 1 commit into
mainfrom
security/high-fixes-0.11.6
Jul 16, 2026
Merged

Security: fix high-severity vulnerabilities (v0.11.6)#38
mack42 merged 1 commit into
mainfrom
security/high-fixes-0.11.6

Conversation

@mack42

@mack42 mack42 commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Fixes the eight High findings from the security audit. Version bumped to 0.11.6. cargo check is clean (no warnings); 84 unit tests + all integration tests pass except the two pubsub integration tests in the untracked WIP tests/ dir that fail identically on main (pre-existing, unrelated).

Findings addressed

7. Non-constant-time password comparison (timing attack). requirepass checks (AUTH, HELLO, HTTP bearer) now compare fixed-length SHA-256 digests in constant time (verify_secret), and ACL hash matching uses a non-short-circuiting constant_time_eq. Neither length nor prefix leaks via timing.

8. RESP parser pre-allocation amplification. Aggregate parsing (array/map/set/push) previously reserved up to MAX_MULTIBULK_LEN (1M) slots from a tiny header, amplified ~32× by nesting. Pre-reservation is now capped at PREALLOC_CAP (1024) and the container grows lazily; the declared length is still validated against MAX_MULTIBULK_LEN.

9. Missing timeouts (slow-loris). Added a 10 s TLS-handshake timeout, a 15 s HTTP header-read timeout, and a 30 s RESP idle timeout that reaps connections which are mid-command (partial buffer) or not yet authenticated, while leaving idle authenticated pooled connections alone.

10. HTTP body-size limit + auth backoff. Request bodies are bounded at 64 MB via Limited (413 on excess), and a 250 ms delay is applied after a failed HTTP auth attempt.

11. Negative-count unbounded Vec in *RANDMEMBER/*RANDFIELD. SRANDMEMBER/ZRANDMEMBER/HRANDFIELD now cap the negated count at 1,000,000 and guard i64::MIN negation with checked_neg.

12. Forged probabilistic headers (via plain SET). is_cms/is_topk now validate that the declared width × depth dimensions fit the actual buffer (checked arithmetic), so a forged blob is rejected as WRONGTYPE instead of driving out-of-bounds reads; TopKState::from_bytes bounds its num_items pre-allocation.

13. BF.RESERVE ~512 MB per call. The computed byte count is validated against the 256 MB cap before allocation.

14. BITCOUNT empty-string underflow. Guarded so the ranged path can't compute len - 1 on an empty value.

Tests

Added unit tests for constant-time comparison (test_constant_time_eq, test_verify_secret) and forged-header rejection (test_forged_cms_header_rejected, test_forged_topk_header_rejected).

Notes / residuals

  • The RESP idle timeout intentionally spares idle authenticated connections; a client that trickles bytes slower than the 30 s window is not reaped by idle-timeout alone (bounded by the 1 GB query-buffer cap from A5: Redis Functions (FCALL) #5). A per-command deadline would be a stronger follow-up.
  • HTTP auth backoff is per-request (the HTTP path is stateless), not a per-IP lockout.

Medium/Low findings remain out of scope for this PR.

Address the eight High findings from the security audit.

- Auth: constant-time password/hash comparison for requirepass (AUTH,
  HELLO, HTTP bearer) and ACL hashes, via SHA-256-digest comparison that
  leaks neither length nor prefix.
- Parser: cap aggregate pre-allocation (PREALLOC_CAP) so a tiny/nested
  multibulk header can't force a huge up-front Vec reservation.
- Timeouts: 10s TLS handshake timeout, 15s HTTP header-read timeout, and
  a 30s RESP idle timeout that reaps partial/pre-auth connections while
  leaving idle authenticated clients alone.
- HTTP: bound request bodies at 64MB (413 on excess) and add a 250ms
  delay on failed auth to slow brute force.
- *RANDMEMBER/*RANDFIELD: cap negative-count magnitude and guard
  i64::MIN negation to prevent unbounded allocation.
- Probabilistic: reject forged CMS/TopK values whose declared dimensions
  don't fit the buffer (OOB/OOM), and cap BF.RESERVE allocation.
- BITCOUNT: guard the empty-string length underflow.

Adds regression tests for constant-time comparison and forged-header
rejection.
@mack42 mack42 self-assigned this Jul 16, 2026
@mack42
mack42 merged commit f5b3b46 into main Jul 16, 2026
1 check failed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant