What this check reads
It greps /etc/mongod.conf for lines whose first non-blank text is bindIp, keeps the last one, then strips everything up to the last colon on that line and removes all spaces, leaving a bare comma-separated address list. That list is classified in a single pass: 0.0.0.0 or :: as a whole entry anywhere in it is a FAIL, a list built only from 127.0.0.1, localhost and ::1 is a PASS, and anything else is a WARN asking you to confirm and firewall each address. A bindIp line that is missing entirely is also a WARN, as is a host where mongod is present but /etc/mongod.conf is not. Nothing is ever read from the running server.
When it applies
Runs only when MongoDB is detected (HAS_MG=1) and requires /etc/mongod.conf at exactly that path; any other config location gives WARN. It is a config-file grep, never a query to the server, so a binding set with --bind_ip on the command line is not seen. It reads the last bindIp line, and its parsing is crude - it strips everything up to the last colon on the line and removes spaces, so a YAML file where bindIp appears in an unusual layout can be misread. 0.0.0.0 or :: anywhere in the value is FAIL; only-loopback is PASS; any other address list is WARN.
What each result means
| Result | When | What it means |
|---|---|---|
| SKIP | Not installed | Nothing was measured. No mongod was found here, so no MongoDB binding was assessed. |
| WARN | `mongod.conf` not found, or no `bindIp` | The binding could not be established from the file, so confirm by hand that mongod answers only on 127.0.0.1. |
| FAIL | Bound to all interfaces | MongoDB is listening on every interface, the exact state that mass scanners wipe and ransom. |
| PASS | Loopback only | Only clients running on this host can reach MongoDB. |
| WARN | Specific non-loopback addresses | A routable address is in the list, which a replica set may legitimately need; confirm each one is intended and firewalled. |
Why it matters
Before 3.6, MongoDB packages bound to all interfaces by default; from 3.6 the default is localhost. Exposed, unauthenticated MongoDB instances were mass-wiped in 2017 and are still scanned daily (Shodan lists tens of thousands). MongoDB Security Checklist: "Limit Network Exposure"; CIS MongoDB "Ensure MongoDB only listens for network connections on authorized interfaces".
Why it fails, and when it is wrong
bindIpAll: trueis an alternative key that the check does not read: a server withbindIpAll: trueand nobindIpgets WARN "no bindIp" rather than FAIL.- Command-line
--bind_ip/--bind_ip_alloverrides are not seen. - Replica set members need to bind a routable address; that is a WARN with "confirm and firewall".
- The regex treats
::as all-interfaces but::1as loopback;[::1]style is not used in mongod.conf.
How to fix it
Read the MongoDB binding
Anything containing 0.0.0.0 accepts connections from every interface, which is the state the mass ransom campaigns needed.
sudo grep bindIp /etc/mongod.confSet bindIp to loopback
Set bindIp to 127.0.0.1 under the net section, then restart. A replica set member that genuinely needs a routable address belongs behind a firewall rule and TLS, not on every interface.
net:
port: 27017
bindIp: 127.0.0.1
# replica sets: bindIp: 127.0.0.1,10.0.0.5 plus firewall and TLSsudo systemctl restart mongodRead the Redis binding and protected mode
Redis is the other engine in this audit that is routinely left open, and it is worth reading at the same time. A bind beyond loopback with protected-mode off is the worst combination, because Redis executes commands immediately.
sudo grep -E '^(bind|protected-mode)' /etc/redis/redis.confLock Redis to loopback
Set an explicit loopback bind, leave protected-mode on rather than relying on it, then restart.
# /etc/redis/redis.conf
bind 127.0.0.1 ::1
protected-mode yessudo systemctl restart redisVerify the fix
# What the server is actually bound to:
ss -tlnp | grep :27017
# expected: 127.0.0.1:27017 only
sudo grep -A3 '^net:' /etc/mongod.conf
# expected: bindIp: 127.0.0.1
# Ask the running server (authoritative, unlike the config grep):
mongosh --quiet --eval 'db.adminCommand({getCmdLineOpts:1}).parsed.net'
# From another host:
nc -zv <server-ip> 27017 # expected: refusedDebugging
Confirm with command -v mongod; pgrep -a mongod.
The server uses a different config path. Find it with ps -o args= -C mongod (look for -f/--config). The check only ever reads /etc/mongod.conf, so it cannot pass on such a host.
No directive was matched. Either it genuinely is not set (modern packages do set it) or the YAML layout defeated the grep. Check with sudo grep -n bindIp /etc/mongod.conf and confirm reality with ss -tlnp | grep 27017.
A later bindIp line wins (the check takes the last one), or the value contains 0.0.0.0 alongside loopback. sudo grep -n bindIp /etc/mongod.conf shows every occurrence.
The config was edited without a restart, or the server was started with --bind_ip overriding the file. Compare the getCmdLineOpts output with the file, then systemctl restart mongod.
This binds everything and is not matched by the check, producing a false PASS. Grep for it explicitly: sudo grep -n bindIpAll /etc/mongod.conf.
Sources
- MongoDB: IP Binding
- MongoDB: net.bindIp / net.bindIpAll
- MongoDB: Security Checklist
- MongoDB 3.6 release notes (localhost binding default)
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