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:…$…:…'; This rule runs locally in the free CLI — or with the full corpus through the hosted service: npx bolvrk check migration.sql