fix(db-access): keep database URLs out of argv (ISS-41) #262

Merged
janpeter merged 1 commit from fix/iss41-no-dsn-argv into main 2026-09-28 14:57:56 +02:00
Owner

ISS-41 (S-2026-09-28-1 / T-122).

Problem: prisma_as_deployer and run_policy in ops-agent/wrappers/db-access/prisma-operator.sh started their children with [runuser -u ops-agent --] env -i … DATABASE_URL=<dsn> …. That put the migrator/superuser DSN in argv:

  • readable by every local user via ps / /proc/<pid>/cmdline;
  • on root paths (approve_policy_hash, adoption, resolve) logged by pam_unix as journald _CMDLINE. Measured: the rotated superuser password was there 4× since 2026-09-28 01:51Z.

Fix: exec_with_only_env NAME=VALUE … -- cmd builds exactly the same environment as env -i (in a subshell: remove all inherited exports, export the pairs, then exec), without the values ever appearing in an argv. The root launcher becomes runuser -m -u ops-agent --, so that environment is kept (verified on srv: the child gets exactly PATH/HOME/USER/LOGNAME/DATABASE_URL, id = ops-agent, runuser cmdline without a secret).

Test: new case in test/db-access-operator.test.ts, with a recording env shim first in PATH and recorders around the Prisma and policy children. It fails on the old wrapper: the shim saw DATABASE_URL/DIRECT_URL/DB_ACCESS_OPERATOR_URL with the password. It passes on the new one, and the children still get the credentials through their env.
db-access suites (umask 022): main 101/101 → this branch 102/102.

Rollout: after merge, install-db-access-module.sh on srv, then live proof (T-123): prisma_migrate_status + adoption_precheck with a /proc sampler and a journal scan. After that, the superuser rotation again (T-124).

🤖 Generated with Claude Code

ISS-41 (S-2026-09-28-1 / T-122). **Problem:** `prisma_as_deployer` and `run_policy` in `ops-agent/wrappers/db-access/prisma-operator.sh` started their children with `[runuser -u ops-agent --] env -i … DATABASE_URL=<dsn> …`. That put the migrator/superuser DSN in argv: - readable by every local user via `ps` / `/proc/<pid>/cmdline`; - on root paths (approve_policy_hash, adoption, resolve) logged by pam_unix as journald `_CMDLINE`. Measured: the rotated superuser password was there 4× since 2026-09-28 01:51Z. **Fix:** `exec_with_only_env NAME=VALUE … -- cmd` builds exactly the same environment as `env -i` (in a subshell: remove all inherited exports, export the pairs, then `exec`), without the values ever appearing in an argv. The root launcher becomes `runuser -m -u ops-agent --`, so that environment is kept (verified on srv: the child gets exactly PATH/HOME/USER/LOGNAME/DATABASE_URL, id = ops-agent, runuser cmdline without a secret). **Test:** new case in `test/db-access-operator.test.ts`, with a recording `env` shim first in PATH and recorders around the Prisma and policy children. It fails on the old wrapper: the shim saw `DATABASE_URL`/`DIRECT_URL`/`DB_ACCESS_OPERATOR_URL` with the password. It passes on the new one, and the children still get the credentials through their env. db-access suites (umask 022): main 101/101 → this branch 102/102. **Rollout:** after merge, `install-db-access-module.sh` on srv, then live proof (T-123): `prisma_migrate_status` + `adoption_precheck` with a /proc sampler and a journal scan. After that, the superuser rotation again (T-124). 🤖 Generated with [Claude Code](https://claude.com/claude-code)
fix(db-access): keep database URLs out of argv (ISS-41)
All checks were successful
CI / Select checks (pull_request) Successful in 13s
CI / Ops-agent checks (pull_request) Successful in 41s
CI / DB access operator (pull_request) Successful in 1m10s
CI / Deploy artifact checks (pull_request) Successful in 40s
CI / Docker image build (pull_request) Successful in 1m25s
CI / Mac foundation hermetic checks (pull_request) Successful in 2m14s
CI / Root app checks (pull_request) Successful in 9m28s
CI / Mac foundation reproducible build (pull_request) Successful in 2m50s
CI / Required checks (pull_request) Successful in 39s
CI / Publish post-merge release evidence (pull_request) Has been skipped
28bb84a904
prisma_as_deployer and run_policy started their children with
`[runuser -u ops-agent --] env -i ... DATABASE_URL=<dsn> ...`, which put the
migrator DSN in argv: readable by every local user via /proc/<pid>/cmdline,
and on root paths (approve, adoption, resolve) logged by pam as journald
_CMDLINE. The rotated superuser password was found there four times.

exec_with_only_env builds the same exact environment in a subshell (all
inherited exports removed, the given pairs exported) and execs the command,
so the values only travel in the environment. The root launcher becomes
`runuser -m` so that clean environment is kept instead of reset.

Regression test: a recording env shim first in PATH plus recorders around the
Prisma and policy children; red on the old wrapper (the shim saw the DSN for
both children), green now. db-access suites: 101/101 on main, 102/102 here.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
s4m-codex-reviewer left a comment

Verdict: APPROVED

Geen blocking findings aangetroffen.

  • Geen gekoppeld plan gevonden — beoordeeld op codekwaliteit + product-standaarden.
  • Tests: git diff --check en bash -n ops-agent/wrappers/db-access/prisma-operator.sh zijn geslaagd. De gerichte Vitest-test kon in de reviewomgeving niet draaien doordat de native rolldown-binding niet gemapt kan worden; de toegevoegde regressietest dekt het Prisma- en policy-argv-pad.
# Verdict: APPROVED Geen blocking findings aangetroffen. - Geen gekoppeld plan gevonden — beoordeeld op codekwaliteit + product-standaarden. - Tests: `git diff --check` en `bash -n ops-agent/wrappers/db-access/prisma-operator.sh` zijn geslaagd. De gerichte Vitest-test kon in de reviewomgeving niet draaien doordat de native rolldown-binding niet gemapt kan worden; de toegevoegde regressietest dekt het Prisma- en policy-argv-pad.
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
janpeter/Ops-dashboard!262
No description provided.