Database audit fixes

Network Isolation: fixing all 7 checks

The network isolation audit reads each detected engine's bind address and every listening TCP socket on the host, so a failure means a database port is answering on an address other than loopback.

The four binding checks are keyed to engine detection, so each reports SKIP with "not installed" when its engine is absent, then skips a second way on privilege: PostgreSQL and Redis when the audit account cannot read postgresql.conf or redis.conf as root, MySQL when no bind-address can be read from the server or from /etc/mysql. Exposed Database Ports is the exception: it skips only when neither ss nor netstat exists on the host, which makes it the one check here that still reports on an engine the others could not reach.

7
checks in this audit
5
rated high severity
4
need root or sudo
~12s
automated run time

Transcribed from the database-security-network-isolation audit script. For what the audit covers rather than how to fix it, see the Network Isolation checklist.

Every check

Find your finding

Listed in the order the audit runs them. Take the check name from the third field of the result line and open its page.

  • Database Engines

    Soon

    Inventory of detected database engines (MySQL/MariaDB, PostgreSQL, MongoDB, Redis, MSSQL) and their versions

    LowNo root2 results
  • MySQL Network Binding

    Soon

    Check whether MySQL/MariaDB is bound to localhost or has TCP networking disabled

    HighNeeds root3 results
  • PostgreSQL Network Binding

    Soon

    Check whether PostgreSQL's listen_addresses is restricted to localhost

    HighNeeds root3 results
  • MongoDB Network Binding

    Soon

    Check whether MongoDB's bindIp is restricted to localhost

    HighNeeds root4 results
  • Redis Network Binding

    Soon

    Check Redis bind directive and protected-mode setting for external exposure

    HighNeeds root4 results
  • Exposed Database Ports

    Soon

    Check for well-known database ports listening on external interfaces

    HighNo root3 results
  • Web Database Admin Tools

    Soon

    Check for phpMyAdmin, Adminer or pgAdmin footprints that are frequently brute-forced

    MediumNo root2 results
Shared script behaviour

How the Network Isolation audit reads your server

Every check in this audit runs after the same preamble, and several of its results only make sense once you know what that preamble could and could not see.

Engine detection: HAS_MY, HAS_PG, HAS_MG, HAS_RD are set from client binaries, server processes or config directories. MYOK=1 only if mysql -N -e 'SELECT 1' works as root over the socket; PGOK=1 only if su postgres -c 'psql -X -tAc "SELECT 1"' works. RDCONF is /etc/redis/redis.conf or /etc/redis.conf; MGCONF is /etc/mongod.conf. Containerised databases are not detected by these probes; audit them with the Docker checks or exec into the container.

Why checks skip

A SKIP is never a pass

A skipped check verified nothing at all. The most common cause is privilege: 4 of the 7 checks in this audit need root for a complete result. Before every run, each script works out which of four privilege modes it is in.

The four privilege modes an audit script can run in, and what each one means for checks that need root
ModeHow it is reachedWhat it means for your results
rootThe audit runs as UID 0.Every privileged branch runs directly. No check skips for lack of permission.
nopasssudo -n true succeeds, so the account has passwordless sudo.Privileged commands run through sudo -n.
passA sudo password was supplied in the CtrlOps audit settings and accepted.Privileged commands run through sudo -S.
noneNone of the above worked.CAN_ROOT=0. Every privileged branch returns SKIP with a "Need root" message rather than guessing.

If many checks skip with a “need root” message, run the audit as root, grant the audit account sudo (with or without NOPASSWD), or supply the sudo password in the CtrlOps audit settings.

FAQ

Network Isolation questions

No, it is measuring something else. The check lists listening sockets with ss -tln and reports any of 3306, 5432, 27017, 6379, 1433, 9200 or 11211 bound to an address that is not loopback, and a UFW or nftables rule in front of that socket does not change what is listening. Two cases are worth separating: a container published with -p 5432:5432 appears as 0.0.0.0 through docker-proxy and does genuinely bypass UFW, while a plain listener behind a working firewall is a defence-in-depth finding. Confirm from another host with nmap -p 3306 before you decide which one you have.
Detection looks at the host only: a client or server binary on PATH, a running mysqld, postgres, mongod or redis-server process, or a config path such as /etc/postgresql or /etc/redis. A database inside a container matches none of those, so every check for that engine skips. The same probe cuts the other way, because a host with only the mysql client and no server still counts as having MySQL, and each MySQL check then skips with "not accessible", which reads like a fault but is correct. Audit containerised databases with the Docker checks, or by exec-ing into the container.
No, that will drop the application. The safe shape is to bind to the private interface rather than to all interfaces, restrict the port to the app server address in the firewall, pin the database accounts to that host instead of the % wildcard, and require TLS on the connection. The check will still WARN afterwards, because it reads the bind address and cannot see your firewall rules, so record it as an accepted finding alongside the rule that scopes it.
Audit your fleet

Run all 7 Network Isolation checks, 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.

Start instantly· No credit card· No sneaky autorenewals