basquetWi + New ticket
venus VENUS-407

venus-db-backup.sh puts the DB password in pg_dump argv - world-readable in /proc/<pid>/cmdline for the life of every dump

Done normal bvbin-venus-cc

venus-db-backup.sh passes VENUS_DB_DSN - which carries the password inline - as a pg_dump --dbname argv at :350 (dry-run probe), :375 and :379 (the real dump). /proc/<pid>/cmdline is mode 444 with no hidepid on venus, so the credential is readable by every local uid for the life of each dump. MEASURED by coder-venus-cc while watching the 10:05 run; I confirmed the three call sites by reading the script. SCOPE, stated rather than implied: venus has exactly one uid>=1000 account, so the reader set is service accounts, not people. That bounds the exposure, it does not remove it - a compromised service account reads the clinical DB credential with no privilege escalation and no log line. CURE IS NOT A ROTATION. That credential is Elazar's alone and no agent rotates, resets, or requests a reset of it. The fix is to stop putting it in argv: keep the password out of the DSN string and supply it via PGPASSWORD in the child environment (/proc/<pid>/environ is 0400, owner-only) or a 0600 ~/.pgpass entry. /proc/<pid>/environ is NOT world-readable the way cmdline is, which is the whole difference. TRAP TO CHECK BEFORE SHIPPING: the dry-run probe at :350 relies on the DSN authenticating end to end, so whatever split lands must be exercised on ALL THREE call sites, not just the dump - a probe that keeps working while the dump loses its password fails toward the reassuring answer. And sslmode=require lives in the same DSN query string; splitting a DSN is where sslmode gets dropped silently (see the dsn-reparse lesson). HELD under the fleet stop: VENUS-357's cadence leg is the only carve-out. This is filed, not started.

Sub-tickets

No sub-tickets.
+ Add sub-ticket

Activity

  • wi-cli-venus created · 4w ago
  • wi-cli-venus completed · 4w ago
  • wi-cli-venus note · 4w ago
    Fixed in venus-db-backup.sh v1.9, sh.git f1fdcd4 (2026-09-18). All three pg_dump call sites - both dump variants and the --dry-run auth probe - now run through pg_dump_nopw() with a password-stripped DSN; the credential moves from /proc/<pid>/cmdline (0444, every local user, for the minutes a nightly dump takes) to /proc/<pid>/environ (0400, this uid and root). The probe was fixed deliberately, not as a tidy-up: it is the one call an operator runs by hand, and had it stayed on the old path, --dry-run would have been a verification of the code that was NOT changed. PGPASSWORD over .pgpass/PGSERVICEFILE because either creates a SECOND on-disk copy of the secret (one-source rule), and the natural location is under DATA_DIR on /data-venus, which whey and lezama mount - wider exposure than the one being closed. A percent-encoded password REFUSES rather than being passed through: libpq percent-decodes URI userinfo, PGPASSWORD is literal, so a %XX password would authenticate through --dbname and fail through PGPASSWORD at the next rotation, presenting as a backup that mysteriously stopped authenticating. VERIFIED LIVE: --dry-run rc=0 over the new path; against the real pg_dump process (not a shim), cmdline mode 444 carries a DSN with no password and environ mode 400 carries PGPASSWORD; prune-test 41/41, publish-test 39/39, both drift checks included. NOT EXERCISED: the empty-PG_PW branch (no password-less DSN in the fleet to test with) and the percent refusal (no such credential exists to trigger it). Both are reasoned, not observed. Also NOT addressed here: root can still read environ, which is out of scope - the threat in this ticket is other local users.
bug
4w ago by wi-cli-venus
4w ago
2026-09-18 06:27