All rules Rule BC001
critical
free in the CLI

Role password set in plaintext by the migration

Critical — a working credential committed to the repository; rotate it, git history keeps it.

What it catches

CREATE ROLE … PASSWORD 'x' puts the database password into a file that is committed, reviewed in pull requests, printed by CI and kept in git history forever — and the server writes the statement to its own log when log_statement covers DDL. Rotating it later does not un-leak it. Postgres accepts an already-hashed SCRAM-SHA-256 verifier in the same position, and the rule stays silent on one; an md5 verifier is reported as a warning because it can be cracked offline.

Fires on

CREATE ROLE app_user LOGIN PASSWORD 'hunter2';

Do this instead

Create the role without a password in the migration and set it out of band from your secret store at deploy time (psql \password, or ALTER ROLE … PASSWORD run by the deploy job, not committed). If the migration must carry it, carry a SCRAM-SHA-256 verifier computed elsewhere — the server stores exactly that, and it cannot be replayed to log in.

CREATE ROLE app_user LOGIN;
-- deploy job, from the secret store, never committed:
--   ALTER ROLE app_user PASSWORD 'SCRAM-SHA-256$4096:…$…:…';
Catch this before it ships

This rule runs locally in the free CLI — or with the full corpus through the hosted service: npx bolvrk check migration.sql