Redis is designed to be accessed by trusted clients inside trusted environments, yet hundreds of thousands of Redis servers answer on public IP addresses. Unit 42 counted more than 307,000 Redis systems communicating publicly over a two-week period in 2023 while tracking the P2PInfect worm, and a single unauthenticated FLUSHALL or CONFIG SET is enough to destroy data or plant files on the host. Redis now has real controls: protected mode, per-user ACLs since Redis 6, TLS on client, replication and cluster links, and hardened defaults for dangerous commands. This guide explains how to combine them into a safe deployment: network exposure, the default user, ACL design, TLS, command and scripting risk, persistence, monitoring and patching. It is written for platform engineers, SREs and security architects running Redis open source or community editions, and for anyone assessing a managed Redis service.
Key takeaways
- Never expose Redis directly. The Redis security model assumes the application mediates all untrusted access. Bind to private interfaces, firewall port 6379 and the cluster bus, and keep protected mode on.
- Fix the default user first. Out of the box the default user is
on nopass ~* &* +@all: every connection is authenticated with full rights. Give it a strong password or switch it off, and create named users. - Key patterns are not a sandbox. ACL key patterns do not restrict keyspace-wide commands, so a user limited to
~tenant1:*with+@allcan still runFLUSHALL. Remove@dangerous,@adminand scripting where not needed. - TLS is optional and per channel. Client, replication (
tls-replication) and cluster bus (tls-cluster) encryption are enabled separately, and Redis must be built with TLS support. - Lua scripting is an attack surface. CVE-2025-49844, a Lua use-after-free rated CVSS 10.0, and CVE-2022-0543, a Debian packaging Lua sandbox escape in the CISA KEV catalogue, both run through scripting. Patch, and deny
@scriptingto users who do not need it.
The Redis security model and its attack surface
Redis's own documentation is explicit: it is not a good idea to expose a Redis instance to the internet, or to any environment where untrusted clients can reach its TCP port or UNIX socket. Untrusted access should always be mediated by an application layer that validates input and decides what operations to run. The reason is the command set. A client with full rights can delete everything with FLUSHALL, change the working directory and dump file name with CONFIG SET dir and dbfilename to write RDB files to arbitrary paths (which the documentation describes as a route to compromising the host), make the instance a replica of an attacker's server with REPLICAOF, or load native code with MODULE LOAD.
| Abuse path | Commands or feature | ATT&CK technique | Primary control |
|---|---|---|---|
| Internet-exposed instance found and accessed | Port 6379, default user with no password | T1190 Exploit Public-Facing Application | Bind, firewall, protected mode, default user off |
| Password guessing | AUTH, HELLO | T1110 Brute Force | Long random passwords, network allow-lists, ACL LOG monitoring |
| Writing files to the host | CONFIG SET dir, dbfilename, SAVE | T1190 (follow-on host compromise) | enable-protected-configs no, deny @admin, run as unprivileged user |
| Loading attacker code | MODULE LOAD, rogue replication with REPLICAOF | T1190 | enable-module-command no, deny @admin and @dangerous |
| Script engine exploits | EVAL, EVALSHA, FCALL | T1190 | Patch, deny @scripting |
| Data wiping or ransom notes | FLUSHALL, FLUSHDB, SWAPDB | T1485 Data Destruction | Explicit -flushall -flushdb -swapdb, backups |
| Cryptomining on the host after compromise | Any of the above | T1496 Resource Hijacking | All of the above plus host monitoring |
| Sniffing passwords and cached data | Unencrypted RESP traffic, including AUTH | T1040 Network Sniffing | TLS on all channels |
Redis is often used as a cache for session tokens, API responses and rate-limit counters, so a read-only compromise can still yield credentials. Treat Redis data according to its most sensitive key, not its role as "just a cache". See the Database Security Guide for the general data store baseline.
Safe network exposure
- bind: the shipped
redis.confusesbind 127.0.0.1 -::1, listening on loopback only. Add only the private interface addresses your application servers use. Never usebind * -::*on a host with a public address. - protected-mode yes: available since Redis 3.2.0 and on by default. When the default user has no password, the server only accepts connections from 127.0.0.1, ::1 and Unix sockets. It is a safety net for mistakes, not an access control: it switches off as soon as a default password is set, and administrators can disable it.
- Firewall both ports: clients use 6379 by default; Redis Cluster nodes also listen on a cluster bus port, by default the command port plus 10000. The current
redis.confwarns that the cluster bus has no authentication of its own, so any host that reaches it can speak the cluster protocol. Restrict it to cluster members only. - Unix sockets for co-located clients: where the application runs on the same host,
port 0plus a Unix socket with tight file permissions removes the TCP listener entirely. - Kubernetes and containers: use NetworkPolicy to allow only the application pods, avoid LoadBalancer or NodePort Services for Redis, and do not publish 6379 on Docker hosts. See the Network Segmentation Guide.
- Connection limits:
maxclients(10000 by default) caps concurrent connections; set it from capacity planning so a flood degrades predictably.
Authentication and ACL design
Redis offers two authentication methods. The legacy requirepass sets one shared password for the default user, sent with AUTH. ACLs, introduced in Redis 6 and recommended by the project, add named users with their own passwords, command rights, key patterns and Pub/Sub channel patterns. Users are defined in redis.conf or, preferably, an external file named by aclfile and reloaded with ACL LOAD (the two methods cannot be mixed).
ACL rule reference
| Rule | Meaning | Security note |
|---|---|---|
on / off | Enable or disable the user | off blocks new logins only; existing connections keep working, so also CLIENT KILL USER |
>password / #<sha256> | Add a password, or a SHA-256 hash of one | Use hashes in the ACL file so cleartext passwords are not stored; a user can hold several passwords for rotation |
nopass | Any password works | On the default user, every new connection is authenticated with no AUTH at all |
+@category / -@category | Allow or deny command categories (@read, @write, @admin, @dangerous, @scripting) | +@all also grants future module commands; other categories never include module commands |
+command|subcommand | Allow a single subcommand, e.g. +config|get | Prefer this to granting whole admin commands |
~pattern, %R~, %W~ | Key patterns; read-only and write-only patterns since Redis 7.0 | Do not limit commands that take no key arguments, such as FLUSHALL |
&pattern, resetchannels | Pub/Sub channel access | From 7.0, acl-pubsub-default is resetchannels, so new users get no channels by default |
(rules) | Selectors: additional permission sets (7.0) | A command is allowed if the root rules or any selector match, so audit selectors as carefully as root rules |
Recommended user layout
- default: set
off(after all clients use named users) or give it a long random password and minimal rights. Clients that never send AUTH then fail closed. - Application users: one per service, built from
-@allupwards: the categories or commands the code uses, its own key prefix (~orders:*) and channels. Add explicit-flushall -flushdb -swapdbif you start from broader categories. - Replication user: the master needs only
+psync +replconf +pingfor replicas; configure replicas withmasteruserandmasterauth. - Sentinel user: the documented minimal rule set covers
MULTI,SLAVEOF,PING,EXEC,SUBSCRIBE,CONFIG|REWRITE,ROLE,PUBLISH,INFO,CLIENT|SETNAME,CLIENT|KILLandSCRIPT|KILL, with channel__sentinel__:helloand no keys. - Operations and monitoring: a read-only monitoring user (
+info +ping +client|list +slowlog|get +latencystyle rights, no key access) and a separate administrator user used only from a bastion.
Rename-command, the older way to hide CONFIG or FLUSHALL, is deprecated in favour of ACL rules. Use ACL DRYRUN to test whether a user can run a command before deployment. Redis passwords are credentials for machines; store them in a secrets manager rather than in application images or source. See the Secrets Management Guide and the Database Credential and Access Security Guide.
TLS for clients, replicas and the cluster bus
TLS support must be compiled in (make BUILD_TLS=yes); many distribution and container builds include it, but verify. Configure a certificate, key and CA bundle with tls-cert-file, tls-key-file and tls-ca-cert-file (or tls-ca-cert-dir).
| Channel | Directive | Default behaviour | Recommended setting |
|---|---|---|---|
| Client connections | tls-port, port | tls-port is in addition to the plain port | port 0 and tls-port 6379 so no plaintext listener remains |
| Client certificates | tls-auth-clients | Mutual TLS required on the TLS port | Keep yes where you can issue client certificates; optional or no only with ACL passwords |
| Protocol versions | tls-protocols | Library defaults | "TLSv1.2 TLSv1.3" |
| Replication | tls-replication | Replicas connect to the master without TLS | yes on every replica; also governs Sentinel connections |
| Cluster bus | tls-cluster | Not encrypted | yes, with a dedicated per-cluster CA |
The current redis.conf adds two settings worth checking in your version: tls-auth-clients-user CN, which maps a client certificate's CN to a Redis user of the same name, and tls-expected-peer-name, which checks a peer's certificate name on server-to-server links. Without peer name checks, any certificate from the trusted CA can impersonate a master or cluster peer, which is why a dedicated CA per cluster matters when you use a shared organisational CA elsewhere. TLS reduces throughput per instance, so load test; Redis 8.0 added I/O threading with TLS. See the mTLS Guide and the How TLS Works Guide.
Dangerous commands, scripting and modules
- Protected configs and commands:
enable-protected-configs,enable-debug-commandandenable-module-commandacceptno,yesorlocal. Keep them atnosodiranddbfilenamestay immutable at runtime andDEBUGandMODULEare blocked. Load required modules fromredis.confat start-up. - Admin commands: deny
@adminand@dangerousto application users; that removesCONFIG,REPLICAOF,MONITOR,SAVE,SHUTDOWN,ACLand similar. - Scripting: Redis advises that Lua scripts must not be composed from untrusted strings. For users who do not need scripting, deny
@scripting(coveringEVAL,EVALSHA, their read-only variants andFCALL). This is the main compensating control the Redis advisory for CVE-2025-49844 points to: limit which identities can run Lua. - Expensive commands:
KEYS,SORTon large inputs and unboundedSMEMBERSorHGETALLcan stall a single-threaded instance. DenyKEYSand useSCAN; the documentation notes thatSORTis not randomised and can hit quadratic worst cases with crafted input. - Injection: the RESP protocol uses length-prefixed, binary-safe strings, so classic injection is not possible through normal client libraries. The risk is application code that builds key names or scripts from user input without validation.
Persistence, data protection and host hardening
- Run unprivileged: Redis does not need root. Run it as a dedicated
redisuser that owns only its data directory, so aCONFIGor module abuse cannot write elsewhere. - Encrypt at rest: RDB snapshots and AOF files contain the full dataset in clear. Encrypt the volume, restrict file permissions on
dir, and encrypt and access-control backup copies. See the Encryption Guide. - Expiry and minimisation: set TTLs on session tokens and cached personal data, and avoid caching data you would not store in a database with the same controls. See the Data Security Guide.
- Logs:
hide-user-data-from-log yeskeeps key names and values out of server logs where those could carry personal data. - Recovery: keep tested backups outside the instance's reach; wiping an exposed Redis and leaving a ransom note is a common outcome of exposure. See the Data Extortion Without Encryption Guide.
Where identity fits
Every Redis user except an operator's break-glass account is a non-human identity: application services, replicas, Sentinel, exporters and automation. The weak points are the classic NHI ones: one requirepass value shared by every service, passwords that never rotate because changing them needs coordinated restarts, and the nopass default user left on. ACLs fix the first two: per-service users, multiple passwords per user for zero-downtime rotation (add the new hash, roll clients, remove the old), and certificate-to-user mapping where you run mTLS. See the Non-Human Identity (NHI) Guide.
Rolling out ACLs and TLS on a live deployment
- Inventory: list instances, versions, listening addresses, whether protected mode and
requirepassare set, and which applications connect (CLIENT LISTshows addresses and the user per connection). - Patch: move to a fixed release for CVE-2025-49844 (open source 8.2.2, 8.0.4, 7.4.6, 7.2.11 or later per the Redis advisory). Check that Debian or Ubuntu packages include the CVE-2022-0543 fix.
- Close exposure: restrict
bindand firewall rules before anything else; it is the fastest risk reduction and rarely breaks legitimate clients. - Create named users in an ACL file: start each from
-@all, add what the service uses (test withACL DRYRUNin staging), and keep the default user working for now. - Migrate clients: switch services to their named users in waves. Watch
ACL LOGfor denied commands and keys, and fix rules rather than widening to+@all. - Lock the default user: once
CLIENT LISTshows no connections asdefault, set itoffor give it a random password and no rights. - Enable TLS: add
tls-portalongsideport, move clients, enabletls-replicationandtls-cluster, then setport 0. - Rollback: keep the previous ACL file and use
ACL LOADto revert in seconds; re-enable the plainportif a TLS migration fails. Never roll back by disabling protected mode.
Choosing an approach: a single cache behind one application can rely on loopback or a private subnet, one ACL user and volume encryption. Shared or multi-tenant Redis needs per-tenant users with key prefixes and explicit keyspace-command denials, TLS, and preferably separate instances for tenants that do not trust each other, because ACLs do not isolate memory or CPU. Managed services take over patching and often TLS, but default user, ACLs, network exposure and data retention usually stay with you.
Detection and measurement
| Signal | Source | What it can indicate |
|---|---|---|
| Authentication failures and denied commands or keys | ACL LOG (in memory, acllog-max-len 128 entries by default) | Password guessing, misconfigured clients, a compromised service probing its limits |
| New client addresses or users | CLIENT LIST sampled by the exporter | Access from unknown sources |
| Configuration or replication changes | Change in CONFIG GET dir, dbfilename, INFO replication role | File-write or rogue-replication attacks |
| Script activity | INFO commandstats for eval, evalsha, fcall; unknown scripts | Exploitation attempts against the Lua engine (an indicator listed in the CVE-2025-49844 advisory) |
| Crashes with Lua stack traces, unexpected files in the data or config directory | Server log, host file integrity monitoring | Exploitation or post-exploitation activity |
| Sudden key count drop or CPU spike | INFO keyspace, host metrics | Data destruction or cryptomining after compromise |
Because ACL LOG lives in memory and is capped, poll it into your SIEM. KPIs that show the programme is working:
- External exposure: Redis instances reachable from the internet, from external attack surface scans (target zero).
- Default user status: percentage of instances with the default user
offor password-protected without+@all. - Named-user coverage: percentage of client connections authenticated as a service-specific user.
- TLS coverage: instances with
port 0,tls-replication yesand, for clusters,tls-cluster yes. - Patch latency: days from a Redis security advisory to the fixed release in production.
Framework mapping
| Redis control | NIST SP 800-53 Rev. 5 | NIST CSF 2.0 | ISO/IEC 27001:2022 Annex A | CIS Controls v8.1 |
|---|---|---|---|---|
| Bind, firewall, protected mode, cluster bus isolation | SC-7 | PR.PS-01 | A.8.20 | Control 12 |
| Named users, default user off, password hashes | IA-5, AC-3 | PR.AA-01 | A.8.5 | Control 6 |
| Least-privilege ACL categories and key patterns | AC-6 | PR.AA-05 | A.5.15 | Control 6 |
| TLS on client, replication and cluster links | SC-8 | PR.DS-02 | A.8.24 | Control 3 |
| Volume encryption of RDB and AOF, TTLs | SC-28 | PR.DS-01 | A.8.24 | Control 3 |
| Protected configs, module and debug commands blocked | CM-6, CM-7 | PR.PS-01 | A.8.9 | Control 4 |
| ACL LOG collection and monitoring | AU-2, AU-12, SI-4 | DE.CM-01 | A.8.15 | Control 8 |
Common failure patterns
- Protected mode switched off to "fix" connectivity: the error message when a remote client is refused tempts administrators to set
protected-mode norather than add a password, leaving an open instance. - Debian-packaged Redis left unpatched: P2PInfect, reported by Unit 42 in July 2023, spread through CVE-2022-0543, a Lua sandbox escape specific to Debian packaging, on exposed instances. The flaw is in the CISA KEV catalogue.
- Key prefixes treated as tenant isolation: a tenant user with
~tenant1:* +@allcan still runFLUSHALLand wipe every tenant. - TLS on clients only: client traffic is encrypted, but replicas sync the full dataset to another region over plaintext because
tls-replicationwas never set. - Shared password everywhere: one
requirepassin dozens of application configs and container images, never rotated, so one leaked image exposes every cache. - Cache assumed to be harmless: session tokens, OAuth access tokens and API responses with personal data sit in Redis with no TTL, no encryption at rest and unencrypted backups.
Practitioner checklist
- Confirm no Redis instance or cluster bus port is reachable from the internet or from networks beyond its clients.
- Keep
protected-mode yesand bind only to the private interfaces the application uses. - Turn the default user
offor remove itsnopassand+@all; create one ACL user per service in anaclfilewith hashed passwords. - Deny
@admin,@dangerousand@scriptingto application users unless a documented need exists, and add explicit-flushall -flushdb -swapdb. - Keep
enable-protected-configs,enable-debug-commandandenable-module-commandatno. - Enable TLS with
port 0,tls-protocols "TLSv1.2 TLSv1.3",tls-replication yesandtls-cluster yes, using a dedicated CA. - Run Redis as an unprivileged user, encrypt volumes holding RDB and AOF files, and protect backups.
- Patch to a release fixed for CVE-2025-49844 and verify CVE-2022-0543 on Debian-based builds.
- Poll
ACL LOG,CLIENT LISTand configuration state into the SIEM and alert on changes todir,dbfilenameand replication role. - Store Redis passwords in a secrets manager and rotate them using multiple passwords per user.
Standards and references
- Redis: Security
- Redis: ACL
- Redis: TLS
- Redis: Security advisory CVE-2025-49844
- Redis: Self-documented redis.conf
- CISA: Known Exploited Vulnerabilities Catalog
- NIST: SP 800-53 Rev. 5
- Palo Alto Networks Unit 42: P2PInfect, a new peer-to-peer worm targeting Redis
Related NHI Mgmt Group resources: Kafka Security Guide · Database Security Guide · Database Credential and Access Security Guide · Secrets Management Guide · mTLS Guide