Remediation Guides

PostgreSQL Default Unpassworded Account: How to Fix Trust Authentication (Nessus 10483)

26 September 2026 8 min read

PostgreSQL Default Unpassworded Account (Nessus plugin 10483) means the scanner logged in to your PostgreSQL server over the network without supplying a password, typically because a pg_hba.conf line uses the trust method. Fix it by setting passwords, changing trust lines to scram-sha-256, reloading the configuration, and restricting who can reach TCP 5432.

This is a configuration problem, not a software bug. No PostgreSQL update clears it, and setting a password on its own does not either, because the trust method never asks for one.

What the scanner is actually detecting

Plugin 10483 is a remote check in the Nessus Databases family. Nessus connects to the PostgreSQL port and tries to log in with a default account and no password. If the server lets it in, the plugin reports Tenable’s synopsis: “The remote database server can be accessed without a password.” No credentials are involved, so it appears in network-only scans as well; see how credentialed and uncredentialed checks differ for why that matters when comparing reports.

Field Value
Plugin ID 10483
Name PostgreSQL Default Unpassworded Account
Family / type Databases / remote
Severity High (CVSS v2 base 7.5)
CVE reference CVE-1999-0508
Tenable solution Set passwords with ALTER USER and require password or Kerberos authentication in pg_hba.conf for local and remote connections

PostgreSQL uses the first pg_hba.conf line whose connection type, client address, database and user match, with no fall-through. If that line says trust, the server accepts the client as whatever role it names, superusers included, and ignores any password. The usual origins are:

  • initdb defaults: without -A (or –auth-host and –auth-local), initdb writes trust lines. The manual warns against keeping them unless you trust every local user.
  • A shortcut line: someone added host all all 0.0.0.0/0 trust to get an application connected.
  • Container settings: the official Docker image appends host all all all with the POSTGRES_HOST_AUTH_METHOD value, so setting it to trust opens every address.

Real-world risk, stated honestly

  • Trust for all users from a routable network: anyone who reaches port 5432 is a superuser. They can read, change or drop every database, create roles to keep access, and run operating system commands as the server’s account through COPY … PROGRAM, which superusers may use. Fix this case first.
  • Trust limited to one database, role or small subnet: exposure equals that role’s privileges from those addresses.
  • Trust on loopback only: every local user and process can connect as any role, including postgres. Real on shared hosts, but an attacker needs a foothold on the host first.

How to confirm it on the host

Reproduce the scanner’s test from a machine on the scanner’s network, as a user with no ~/.pgpass file. The -w option makes psql fail instead of prompting when the server asks for a password.

unset PGPASSWORD PGPASSFILE
psql -w -h 192.0.2.30 -p 5432 -U postgres -d postgres -c 'SELECT current_user;'

If a row comes back, the finding is confirmed. Then, on the server, find the active file and list its trust lines (pg_hba_file_rules exists from PostgreSQL 10 and is readable by superusers):

sudo -u postgres psql -Atc 'SHOW hba_file;'
sudo -u postgres psql -c "SELECT line_number, type, database, user_name, address, netmask, auth_method FROM pg_hba_file_rules WHERE auth_method = 'trust';"
sudo -u postgres psql -Atc 'SHOW listen_addresses;'
sudo ss -ltnp | grep ':5432'

The view shows the file as it is now, not what the server last loaded, so an edited but unreloaded file looks clean while the old rules still apply. On Windows, run the same queries through psql.exe (adjust the version folder) and check the listener:

$psql = "C:Program FilesPostgreSQL16binpsql.exe"
& $psql -h 127.0.0.1 -U postgres -d postgres -c "SHOW hba_file;"
& $psql -h 127.0.0.1 -U postgres -d postgres -c "SELECT line_number, type, database, user_name, address, auth_method FROM pg_hba_file_rules WHERE auth_method = 'trust';"
Get-NetTCPConnection -LocalPort 5432 -State Listen

Finally, see which login roles have no password or an MD5 hash:

SELECT rolname, rolsuper,
       CASE WHEN rolpassword IS NULL THEN 'none'
            WHEN rolpassword LIKE 'md5%' THEN 'md5'
            WHEN rolpassword LIKE 'SCRAM-SHA-256$%' THEN 'scram-sha-256'
       END AS stored_password
FROM pg_authid
WHERE rolcanlogin;

How to fix it

Step 1: back up the file, and set passwords before removing trust

Order matters. If you replace trust before the admin role has a password, the next connection that depended on trust is refused.

HBA=$(sudo -u postgres psql -Atc 'SHOW hba_file;')
sudo cp -p "$HBA" "$HBA.bak"

Step 2: store passwords as SCRAM

Run SHOW password_encryption;. The default has been scram-sha-256 since PostgreSQL 14 (it was md5 before). On 10 through 13, set password_encryption = scram-sha-256 in postgresql.conf and run SELECT pg_reload_conf(); first. Then give postgres and every other login role that needs one a long random password:

sudo -u postgres psql
postgres=# password postgres
postgres=# password app_user

password hashes the password before sending it. ALTER USER postgres WITH PASSWORD ‘…’; also works, but the cleartext can end up in command history or the server log. Roles still holding an MD5 hash need a new password too: the documented migration is to switch password_encryption, have users set new passwords, then change pg_hba.conf. Versions older than 10 have no SCRAM, so use md5 there and plan the upgrade.

Step 3: change pg_hba.conf trust to scram-sha-256

Edit the file from Step 1. A typical before and after:

# Before
local   all          all                          trust
host    all          all          127.0.0.1/32    trust
host    all          all          ::1/128         trust
host    all          all          0.0.0.0/0       trust
host    replication  all          127.0.0.1/32    trust

# After
# TYPE  DATABASE     USER         ADDRESS         METHOD
local   all          postgres                     peer
local   all          all                          scram-sha-256
host    all          all          127.0.0.1/32    scram-sha-256
host    all          all          ::1/128         scram-sha-256
host    appdb        app_user     10.0.20.0/24    scram-sha-256
host    replication  replicator   10.0.30.5/32    scram-sha-256
  • The peer line keeps sudo -u postgres psql working on Linux. Peer accepts only local socket connections from the matching operating system user, so a scanner cannot use it; it is not available on Windows.
  • Replace 0.0.0.0/0 with the application subnets, and name the database and role where you can. Use hostssl if TLS is configured.
  • Check replication lines and any included files (PostgreSQL 16 and later).

Check for syntax errors, then reload:

sudo -u postgres psql -c "SELECT line_number, error FROM pg_hba_file_rules WHERE error IS NOT NULL;"
sudo -u postgres psql -c "SELECT pg_reload_conf();"

pg_ctl reload or systemctl reload on the PostgreSQL unit does the same (unit names vary by package; systemctl list-units ‘postgresql*’ shows yours). pg_hba.conf is only consulted when a connection starts, so open sessions are not dropped. On Windows the manual states new connections pick up pg_hba.conf changes immediately; running pg_reload_conf() anyway also applies the password_encryption change.

Step 4: reduce network exposure

listen_addresses defaults to localhost. If it is ‘*’, list only the addresses clients use. This setting needs a restart, not a reload:

# postgresql.conf
listen_addresses = 'localhost,10.0.10.5'
# Linux (use your unit name)
sudo systemctl restart postgresql

# Windows
Get-Service postgresql* | Restart-Service

Then allow TCP 5432 only from the hosts that need it:

# firewalld
sudo firewall-cmd --permanent --remove-service=postgresql
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="10.0.20.0/24" port port="5432" protocol="tcp" accept'
sudo firewall-cmd --reload

# ufw (remove broader 5432 rules first)
sudo ufw allow from 10.0.20.0/24 to any port 5432 proto tcp
Get-NetFirewallPortFilter | Where-Object LocalPort -eq 5432 | Get-NetFirewallRule
New-NetFirewallRule -DisplayName "PostgreSQL from app subnet" -Direction Inbound -Protocol TCP -LocalPort 5432 -RemoteAddress 10.0.20.0/24 -Action Allow

How to verify the fix and rescan

  1. Repeat the remote psql command. Expect fe_sendauth: no password supplied (a password is now required), no pg_hba.conf entry for host (no line matches your address), or a timeout if the firewall blocks you.
  2. Repeat the pg_hba_file_rules query. It should return no trust rows, or only ones you have deliberately kept and documented.
  3. Repeat the pg_authid query. Every login role should show scram-sha-256.
  4. Rescan with the same Nessus scanner and policy. If the firewall now blocks that scanner, the plugin cannot test at all, so keep the query output as evidence that the Nessus 10483 remediation holds on the server itself.
  5. Confirm applications, backup jobs, monitoring and replicas reconnect.

What can break and how to roll back

  • Clients that never sent a password: applications, cron jobs, pg_dump scripts and monitoring agents that relied on trust fail on their next new connection. Put credentials in their configuration or a .pgpass file in the same change window.
  • Replicas: a standby whose primary_conninfo has no password stops streaming once the replication line changes.
  • MD5 hashes: a role still holding an MD5 hash cannot pass a scram-sha-256 line until it gets a new password.
  • Old drivers: older client libraries do not support SCRAM. Check driver versions first.

To roll back, restore the backup and reload. A reload through systemctl or pg_ctl is an operating system signal, so it works even when you cannot log in to the database:

sudo cp -p "$HBA.bak" "$HBA"
sudo systemctl reload postgresql   # use your unit name, or: pg_ctl reload -D <data directory>

Passwords you set do not need reverting. Treat a rollback as temporary, because the finding returns with it.

Common false positive reasons

The plugin completes a real login, so reports are usually accurate. Disputes tend to come from these:

  • The scanner runs on the database host: the default loopback trust lines matched. The finding is real, but the exposure is local only.
  • Something else answers on the port: a connection pooler such as PgBouncer with its own authentication settings, a second instance, or a container publishing 5432. Check the owning process with ss -ltnp.
  • The file was fixed but not reloaded: on Linux the old rules stay active until a reload, so the report is correct even though the file looks clean.
  • Stale results: the host was fixed after the scan, or the address now belongs to another host behind NAT or a load balancer.

FAQ

Does ALTER USER postgres WITH PASSWORD clear plugin 10483?

Not by itself. Trust ignores passwords, so the finding stays until the matching pg_hba.conf line uses a password method and the configuration is reloaded.

Should I use md5 or scram-sha-256?

scram-sha-256 on PostgreSQL 10 and later. MD5 password support is deprecated. An md5 line automatically uses SCRAM when the stored password is a SCRAM hash, which helps during migration.

Is blocking port 5432 enough?

It removes remote exposure and usually clears the scan result, but trust still lets any local user connect as any role. Fix both.

Tracking this finding across many hosts

Trust lines tend to come back when servers are rebuilt from the same image, script or container settings. If you use SITEY, you can upload the .nessus export, have its AI draft a host-specific remediation script that runs only after a person approves it, deploy it through SITEY agents on Linux or Windows servers, and re-test each Nessus finding to confirm it is closed.

Sources

SITEY closes the loop, not just the report.Discover, validate, fix and verify in your own infrastructure.

See pricing