What this check reads
In redis.conf (whichever of /etc/redis/redis.conf or /etc/redis.conf exists) it looks for an uncommented requirepass <value> (HASPW) or any user ... / aclfile ... line (HASACL). Either one on its own is the PASS: the check does not judge the strength of the password or the scope of the ACL. It also reads the last bind line; if any address is not loopback (127.0.0.1, ::1, -::1, localhost) it sets EXTB=1, which is what turns the no-credential case from a WARN into a FAIL.
When it applies
Runs only when Redis is detected (HAS_RD=1: a redis-server binary, a running redis-server, or a config at /etc/redis/redis.conf / /etc/redis.conf). It needs one of those two config paths (RDCONF) - anywhere else gives WARN - and root/sudo to read it, otherwise SKIP. This is a config-file check: a password set at runtime with CONFIG SET requirepass and never persisted with CONFIG REWRITE is not seen, and an included file is not followed. Whether the FAIL or the softer WARN branch fires depends on the last bind line: any non-loopback address makes it FAIL.
What each result means
| Result | When | What it means |
|---|---|---|
| SKIP | Redis not installed | Nothing was checked. No redis-server binary, process or config file was found. |
| WARN | `redis.conf` not found at the two standard paths | Redis is present but its config was never read, so the credential is unconfirmed rather than known to be missing. |
| PASS | `requirepass` or ACL configured | Redis asks callers for a credential. How strong or how scoped it is falls outside this check. |
| FAIL | No auth and bound beyond loopback | Anyone who can reach the port has full access, including writing files to disk through CONFIG SET. |
| WARN | No auth, loopback only | No remote attacker can reach it directly, but any local process or an SSRF bug in your application can. Set requirepass anyway. |
| SKIP | Root needed to read the config | Nothing was read. The config file is there but was unreadable, so no conclusion is drawn. |
Why it matters
Redis has no authentication by default. An unauthenticated Redis reachable from the network allows data theft, FLUSHALL, and historically remote code execution via CONFIG SET dir/dbfilename to write SSH keys or cron files, and via the MODULE LOAD primitive. Redis docs: "Redis is designed to be accessed by trusted clients inside trusted environments". Even loopback-only Redis is reachable by any local process and by SSRF from a web app. Redis 6+ recommends ACL users over the single requirepass.
Why it fails, and when it is wrong
- Runtime
CONFIG SET requirepasswithoutCONFIG REWRITEis invisible to this file-based check. Useredis-cli CONFIG GET requirepassto see the live value. - Config at a non-standard path (Docker, Snap,
/etc/redis/6379.conf) gives WARN "not found". - A password set via an included file (
include /etc/redis/auth.conf) is not seen. bind 0.0.0.0withprotected-mode yesand no password: Redis still refuses non-loopback clients, but the script treats it as FAIL because protected mode is a fallback, not a control.- The
binddefault in recentredis.confisbind 127.0.0.1 -::1; when the directive is absent Redis binds all interfaces but protected-mode applies.
How to fix it
# /etc/redis/redis.conf
bind 127.0.0.1 -::1
protected-mode yes
requirepass <64 random chars>
# Redis 6+ preferred: ACL users with least privilege
user app on >strong-password ~app:* +@read +@write -@dangerous
user default off
rename-command CONFIG "" # optional, or restrict via ACLThen systemctl restart redis-server and update clients (AUTH / --pass).
Verify the fix
# The live value is authoritative:
redis-cli CONFIG GET requirepass # expected: a long value, not empty
redis-cli ACL LIST # Redis 6+: expected least-privilege users, "user default off"
# An unauthenticated command must now be refused:
redis-cli PING
# expected: (error) NOAUTH Authentication required.
redis-cli -a "$REDIS_PASSWORD" --no-auth-warning PING # expected: PONGDebugging
Confirm with command -v redis-server; pgrep -a redis-server.
sudo grep -nE '^(requirepass|bind|user |aclfile)' /etc/redis/redis.conf.
The config lives somewhere the check does not look (Docker, Snap, /etc/redis/6379.conf). Locate it with ps -o args= -C redis-server; the first argument after the binary is the config path. The check reads only the two standard paths.
You set it at runtime. redis-cli CONFIG GET requirepass shows the live value; persist it with redis-cli CONFIG REWRITE (or write it into the config file) so it survives a restart and is visible to the check.
Deliberate. Protected mode is a fallback that disappears the moment any password or bind is configured; the check wants an explicit credential. Set requirepass or ACLs.
The script uses the last bind line only: sudo grep -E '^bind[[:space:]]' "$RDCONF" | tail -1. Anything other than 127.0.0.1, ::1, -::1 or localhost in that line sets EXTB=1 and turns the WARN into a FAIL.
Sources
- Redis: Security
- Redis: ACL
- Redis: AUTH command
- Redis: CONFIG REWRITE
- Redis self-contained redis.conf example (protected-mode, bind)
- Redis security guidance skill (Redis, Inc.)
- OWASP Server-Side Request Forgery Prevention (why loopback-only is not enough)
How the script reads this
Next
Re-run the Authentication audit after applying the fix and confirm this check moves to PASS. CtrlOps runs all 8 checks over your existing SSH connection and scores the result, so the change is visible without reading another config file.
All 8 Authentication fixes