Database audit fix

How to Configure and Secure Redis Network Bindings

The bind directive in redis.conf lists the interfaces Redis answers on, and a non-loopback bind with protected-mode no gives anyone who reaches 6379 file writes and code execution. Set bind 127.0.0.1 -::1 and keep protected-mode yes.

Hiren KalariyaLast reviewed: Sep 25, 2026Check redis-network-binding
High
severity
Yes
needs root or sudo
5
results it can return
5 of 7
checks in this audit

Every threshold on this page is transcribed from the database-security-network-isolation audit script that CtrlOps runs, and a build check fails if the two ever disagree. See all 7 Network Isolation checks, or how the audit runs.

High severityNeeds sudo

What this check reads

Through as_root it greps whichever of /etc/redis/redis.conf or /etc/redis.conf the preamble found, taking the last line that starts with bind followed by whitespace and the last that starts with protected-mode followed by whitespace. Every address on that bind line is then tested one at a time, and anything other than 127.0.0.1, ::1, -::1 or localhost sets EXTB=1. The two readings are graded together rather than separately: EXTB=1 with protected-mode no is a FAIL, EXTB=1 with protected mode still on is a WARN, no bind line at all with protected-mode set to anything but no is a PASS that still tells you to set bind explicitly, and a loopback-only bind is a plain PASS.

When it applies

Runs only when Redis is detected (HAS_RD=1), needs the config at /etc/redis/redis.conf or /etc/redis.conf (anything else gives WARN), and needs root/sudo to read it or it SKIPs. It is a config-file check: a binding changed at runtime with CONFIG SET and not persisted with CONFIG REWRITE is invisible, and included files are not followed. It reads the last bind line and the last protected-mode line. Severity of the result depends on the combination: non-loopback bind with protected-mode no is FAIL, non-loopback bind with protected mode still on is WARN, and no bind line at all with protected mode on is a PASS that still advises setting bind explicitly.

What each result means

Result thresholds this check applies
ResultWhenWhat it means
PASSNo `bind` but `protected-mode` not `no`Redis is loopback-only in practice, but only because protected mode is covering for a missing bind line.
FAILNon-loopback bind **and** `protected-mode no`Redis is reachable off the host with its safety net switched off, which is code execution rather than only data exposure.
WARNNon-loopback bind with protected mode onThe listener reaches past loopback and protected mode is the only thing in the way, which stops helping the moment a password is set.
PASSLoopback-only bindOnly processes on this host can open a connection to Redis.
SKIPRoot needed / config not foundNothing was verified. The config could not be read, so the binding is unknown rather than confirmed safe.

Why it matters

Redis documentation: it must not be exposed to the internet. Protected mode (Redis 3.2+) refuses non-loopback clients when no password and no explicit bind are configured, as a safety net, not a control. Exposed Redis has been exploited for cryptomining and RCE (CONFIG SET dir + SAVE, MODULE LOAD, replication-based payloads). CIS-equivalent guidance: bind to loopback or a private interface and require auth.

Why it fails, and when it is wrong

  • Runtime CONFIG SET bind is not persisted; the file may differ from reality. redis-cli CONFIG GET bind shows the truth.
  • Docker redis image runs with no config file: host check cannot see it.
  • bind * -::* (Redis 7 syntax for all) contains *, which is non-loopback → correct flag.
  • A bind 0.0.0.0 with requirepass set is still reported WARN here (authentication is checked separately).
  • Redis Sentinel/Cluster nodes need a routable bind; restrict by firewall and TLS.

How to fix it

bind 127.0.0.1 -::1
protected-mode yes

For remote clients use a private IP, requirepass/ACL, TLS (tls-port), and a firewall rule.

Verify the fix

# Live values, which beat the config file:
redis-cli CONFIG GET bind
redis-cli CONFIG GET protected-mode
# expected: bind = 127.0.0.1 -::1, protected-mode = yes

ss -tlnp | grep :6379
# expected: 127.0.0.1:6379 only

# From another host:
redis-cli -h <server-ip> PING     # expected: no route / connection refused

Debugging

Re-run with sudo, or read the live values with redis-cli CONFIG GET bind.

The config is somewhere the check does not look (Docker, Snap, /etc/redis/6379.conf). Locate it via ps -o args= -C redis-server; the first argument after the binary is the config path.

Either you changed it at runtime only (persist with redis-cli CONFIG REWRITE), or a later bind line in the file overrides yours: sudo grep -n '^bind' "$RDCONF" shows all of them, and the check uses the last.

Redis binds all interfaces when bind is absent; the PASS relies entirely on protected-mode. That mode stops protecting you the moment a password or a bind is configured, so set bind 127.0.0.1 -::1 explicitly rather than depending on it.

The script iterates the last bind line and treats only 127.0.0.1, ::1, -::1 and localhost as loopback; anything else, including a private LAN address, sets EXTB=1.

An exposed Redis without a password is remote code execution. Pair this with the Redis Authentication check.

Sources

How the script reads this

Next

Re-run the Network Isolation audit after applying the fix and confirm this check moves to PASS. CtrlOps runs all 7 checks over your existing SSH connection and scores the result, so the change is visible without reading another config file.

All 7 Network Isolation fixes
Audit your fleet

Find every one of these on every server, in one click

CtrlOps runs this audit over your existing SSH connection - no agents, no scripts to manage. $7/user/month after a 1 month free trial - no credit card required.

Windows

✓ Start instantly·✓ No credit card·✓ No sneaky autorenewals