Files
computer-playbook/tests
kevinveenbirkenbachandClaude Opus 5.5 54ea4890e7 fix(security): hand container exec credentials over on stdin, not environment
ffed838bc7 moved 24 credentials from `container exec -e NAME=VALUE` to
`-e NAME` plus the task's `environment:`. That kept the value out of the
docker argv but not out of the host process table: for command, shell
and script alike, Ansible runs `/bin/sh -c 'NAME=value ... && sleep 0'`
(plugins/action/script.py joins the environment string onto the command;
the trailing `sleep 0` keeps that shell and its argv alive for the whole
task). Only a task's stdin reaches no argv.

- Every site of ffed838bc7 on this branch now sends its secrets as the
  first lines of `stdin:`; the calling shell runs
  `IFS= read -r NAME && export NAME && container exec -e NAME ...`, one
  line per secret. Where `container exec -i` feeds the container a
  payload (SQL, PHP, Ruby, a shell script), the payload follows on the
  next lines and passes through untouched. Non-secret values stay in
  `environment:`. Elasticsearch keeps one read prefix,
  ELASTICSEARCH_AUTH_FROM_STDIN, for its five exec tasks.
- Nextcloud's admin realignment and the Postgres pg_hba rescue move from
  `script` (which takes no stdin) to `command` with `bash -c` over the
  script; both scripts read the password themselves and fail loudly on
  empty stdin. dump_pg_hba.sh also stops passing
  `--env "PGPASSWORD=${PGPASSWORD}"`, which put the value straight into
  the docker argv.
- test_exec_env_passes_no_value now also reads `--env` and a quoted
  `"NAME=..."`, the spelling that hid the pg_hba leak. That surfaced the
  agent-broker probe key and the MCP contract's path key and bearer
  header on `container exec`/`run` argv; they now reach the engine
  through the calling process' environment, as does LiteLLM's
  MIN_CHARS_PER_TOKEN (a count, but caught by its name).
- The docstrings and failure messages of the three exec lints name
  stdin as the remedy and say why `environment:` is not one.

Left for later, by agreement with feature/updater: the Postgres
superuser script and its two callers, and the Nextcloud OpenProject
provisioning, which that branch rewrites. Detecting a credential bound
in `environment:` lands once those are merged.

Probed with ansible-core 2.20 against a stub `container` that records
argv, the forwarded variables, stdin and a full-width `ps` snapshot:
every shape used here (read prefix with `args: stdin` under bash and
dash, a secret line plus payload through `exec -i`, two secrets with
`cmd`/`stdin` in the module mapping, `command` with `bash -c` and
`stdin`, an `until` retry) delivers the exact value and payload and
leaves the secret out of every argv, while the old `environment:` form
shows it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 16:44:12 +01:00
..
…

Tests 🧪

All automated tests for Infinito.Nexus live here.

Directory Type Guide
unit/ Unit tests (isolated, no I/O) unit.md
integration/ Integration tests (real component boundaries) integration.md
external/ Opt-in live third-party checks, excluded from make test external.md
e2e/ End-to-end Playwright tests playwright.md
regression/ Regression guard rules regression.md
lint/ Structural lint checks lint.md
fuzz/ Coverage-guided atheris harnesses, run weekly in CI, excluded from make test workflows.md

Run each suite via the make targets documented in the linked guides.