Skip to content

security: harden Redis ACL validation safety - #19

Merged
man4ish merged 1 commit into
mainfrom
security/redis-acl-validation-safety
Sep 18, 2026
Merged

man4ish merged 1 commit into
mainfrom
security/redis-acl-validation-safety

Conversation

@man4ish

@man4ish man4ish commented Sep 18, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Adds scripts/redis_acl_safety.py, a framework that structurally prevents the failure class behind the 2026-09-18 production Redis FLUSHALL incident: explicit, independently-reverified environment classification (DISPOSABLE/PRODUCTION/UNKNOWN), fresh-connection-per-identity with unconditional close on any AUTH failure, hard identity assertion via ACL WHOAMI, a narrow production command allowlist plus a dangerous-command denylist, and no public accessor for the underlying redis-py client.
  • Adds tests/test_redis_acl_safety.py, which reproduces the actual incident sequence (failed AUTH leaving a connection authenticated as default) against a genuinely disposable Redis instance, and covers command-gate parsing, identity mismatch, authentication-failure shapes, disposable-only destructive proof, unknown-environment strictness, and the raw-client bypass surface.

Test plan

  • pytest -q tests/test_redis_acl_safety.py — 86 passed, 0 failed
  • Full repository suite — 475 passed, 23 skipped, 0 failed
  • No production Redis touched to build or test this

🤖 Generated with Claude Code

On 2026-09-18, production Redis was accidentally FLUSHALL'd during ad
hoc redis-exporter ACL negative testing: Redis's `default` user was
enabled with nopass, so a connection was already authenticated as
`default` the instant it opened; an explicit AUTH to a named identity
with the wrong password failed but did not deauthenticate the
connection, and subsequent commands -- including FLUSHALL -- executed
with default's unrestricted permissions instead of failing.

Adds scripts/redis_acl_safety.py, a small framework that makes this
failure class structurally impossible for any caller that uses it:
explicit, independently-reverified environment classification
(DISPOSABLE requires a live nonce round-trip, never inferred from a
hostname/port/empty-env-var; UNKNOWN is treated at least as strictly
as PRODUCTION everywhere); every authenticated session is a brand-new
connection that is closed unconditionally on any AUTH failure before a
second command can reach the wire; identity is asserted via ACL WHOAMI
before any validation command runs, with no warning-only fallback; a
narrow production command allowlist plus a hard dangerous-command
denylist (FLUSHALL, FLUSHDB, SHUTDOWN, DEBUG, CONFIG SET, ACL
mutations, MIGRATE/RESTORE/SWAPDB/REPLICAOF/SLAVEOF, ...); and no
public method that exposes the underlying redis-py client.

tests/test_redis_acl_safety.py reproduces the actual incident sequence
against a genuinely disposable Redis instance (started fresh via
Docker for the test session, mirroring tests/_redis_integration_guard.py's
existing no-implicit-default / no-production-port conventions), proves
this framework survives it, and covers command-gate parsing (case,
bytes, subcommand splitting), identity mismatch, authentication
failure shapes, disposable-only destructive proof via
DisposableNegativeTestGate, unknown-environment strictness, and the
raw-client bypass surface. 86 tests, all passing; full existing suite
unaffected (475 passed, 23 skipped, 0 failed).

No production Redis was touched to build or test this.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@man4ish
man4ish merged commit 5eac8e3 into main Sep 18, 2026
1 of 2 checks passed
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