Skip to content

security: move Infisical & Spaces secrets off argv (M2, fleet-wide)#85

Merged
ncimino merged 1 commit into
mainfrom
feature/nik-argv-secret-hardening
Jul 15, 2026
Merged

security: move Infisical & Spaces secrets off argv (M2, fleet-wide)#85
ncimino merged 1 commit into
mainfrom
feature/nik-argv-secret-hardening

Conversation

@ncimino

@ncimino ncimino commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

Summary

Fleet-wide fix for the M2 secrets-hygiene finding (AGENTS.md S2): Infisical Machine-Identity secrets and DO Spaces credentials were passed on process argv, where they're readable via ps / /proc/<pid>/cmdline on the droplet. This was deferred from the open-branch consolidation (PR #84) because it needs a deploy test; here it is as its own reviewed pass.

75 files, +274 / −358 (net reduction — the multi-line argv blocks collapse to shorter env-var forms).

The fix

Infisical login — env-var auth instead of --client-secret on argv (the CLI reads INFISICAL_UNIVERSAL_AUTH_* natively; this is the pattern openclaw's entrypoint already used):

export INFISICAL_UNIVERSAL_AUTH_CLIENT_ID="$INFISICAL_CLIENT_ID"
export INFISICAL_UNIVERSAL_AUTH_CLIENT_SECRET="$INFISICAL_CLIENT_SECRET"
infisical login --method=universal-auth [--plain --silent]

Tofu/OpenTofu — export AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY (the S3 backend reads them from env) and drop the two -backend-config access/secret lines; sse_customer_key stays on -backend-config (no env equivalent).

Scope

Every *-docker template + rendered site — anythingllm, keycloak, owncloud, wordpress, searxng, signoz, sandbox, openclaw, devbox — plus otel-agent/ and scripts/*otel*, and the doc examples that showed the old form.

All argv shapes handled: wrapped INFISICAL_TOKEN="$(…)" capture, bare infisical login, swapped --silent --plain order, single-line in-heredoc / inline-ssh "$host" "…" forms, the if-retry loop, and the INFISICAL_OTEL_* var names. Only --plain/--silent and non-secret flags remain on argv.

Test plan

  • bash -n + shellcheck -S error clean on all changed shell scripts.
  • Every changed rendered ansible deploy.yml parses as valid YAML.
  • Grep-verified 0 remaining --client-secret= and -backend-config="secret_key=" in tracked code (historical CHANGELOG prose excluded).
  • Transformation was validated on throwaway copies (both login shapes + both tofu variants) before applying, with a grep-after safety net catching every non-canonical outlier.

Not in scope / human gate

  • Live deploy test (copier render → run the ansible/tofu path against a real droplet) — copier isn't available in the authoring environment and this touches deploy scripts, so a render+deploy smoke test is the pre-promotion gate. The change is a mechanical, statically-verified secret-placement move (argv → env), no logic change.

Compliance

NIST CSF 2.0 PR.DS-1 / PR.AC-4 · CIS Controls v8 3.11.

…fleet-wide)

Closes the AGENTS.md S2 finding that Machine-Identity + DO Spaces credentials
were exposed on process argv (visible via ps / /proc/<pid>/cmdline on the droplet).

Infisical login: env-var auth instead of --client-secret on argv --
  export INFISICAL_UNIVERSAL_AUTH_CLIENT_ID="$INFISICAL_CLIENT_ID"
  export INFISICAL_UNIVERSAL_AUTH_CLIENT_SECRET="$INFISICAL_CLIENT_SECRET"
  infisical login --method=universal-auth [--plain --silent]
(the CLI reads the INFISICAL_UNIVERSAL_AUTH_* env vars natively; matches the
pattern openclaw's entrypoint already used).

Tofu/OpenTofu: export AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY (the S3 backend
reads them from env) and drop the -backend-config access_key/secret_key lines;
sse_customer_key stays on -backend-config (no env equivalent).

Scope: every *-docker template + rendered site (anythingllm, keycloak, owncloud,
wordpress, searxng, signoz, sandbox, openclaw, devbox), otel-agent/, the
scripts/*otel* helpers, and the doc examples that showed the old form. Handled
all shapes: wrapped INFISICAL_TOKEN capture, bare login, swapped --silent --plain,
in-heredoc / inline-ssh single-line, the if-retry loop, and the OTEL var names.

Verification: bash -n + shellcheck -S error clean on all changed scripts;
rendered ansible YAML parses; 0 remaining --client-secret= / backend-config
secret_key in tracked code. Live deploy test (copier render -> ansible/tofu)
is the human pre-merge gate.
Copilot AI review requested due to automatic review settings July 15, 2026 04:59
@ncimino ncimino merged commit 46aaa9f into main Jul 15, 2026
18 checks passed
@ncimino ncimino deleted the feature/nik-argv-secret-hardening branch July 15, 2026 05:01

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fleet-wide hardening to eliminate secrets on process argv by switching Infisical universal-auth to env-var auth and moving DigitalOcean Spaces (S3 backend) credentials from tofu init -backend-config=... flags to the standard AWS env vars.

Changes:

  • Updated Infisical auth flows to set INFISICAL_UNIVERSAL_AUTH_CLIENT_ID/_SECRET and call infisical login without client-secret flags on argv.
  • Updated OpenTofu backend initialization to use AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY instead of passing Spaces access/secret via -backend-config=....
  • Updated docs/runbooks/CHANGELOG to reflect the new non-argv patterns.

Reviewed changes

Copilot reviewed 76 out of 76 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
wordpress-docker/template/terraform/init.sh.jinja Use AWS env vars for Spaces backend auth during tofu init.
wordpress-docker/template/scripts/entrypoint-infisical.sh.jinja Switch Infisical login to universal-auth env vars (no --client-secret on argv).
wordpress-docker/template/scripts/backup.sh.jinja Update remote backup flow to universal-auth env vars prior to infisical run.
wordpress-docker/template/ansible/deploy.yml.jinja Update Ansible deploy tasks to universal-auth env vars before infisical run.
wordpress-docker/docs/INFISICAL_INTEGRATION.md Update docs example from argv secrets to universal-auth env vars.
signoz-docker/template/terraform/init.sh.jinja Use AWS env vars for Spaces backend auth during tofu init.
signoz-docker/template/scripts/entrypoint-infisical.sh.jinja Switch Infisical login to universal-auth env vars (no argv secret flags).
signoz-docker/template/scripts/backup.sh.jinja Update remote backup flow to universal-auth env vars prior to infisical run.
signoz-docker/template/ansible/deploy.yml.jinja Update Ansible deploy tasks to universal-auth env vars before infisical run.
searxng-docker/template/terraform/init.sh.jinja Use AWS env vars for Spaces backend auth during tofu init.
searxng-docker/template/scripts/restore.sh.jinja Update remote restore SSH path to universal-auth env vars (no argv secret flags).
searxng-docker/template/scripts/entrypoint-infisical.sh.jinja Switch Infisical login to universal-auth env vars (no argv secret flags).
searxng-docker/template/scripts/backup.sh.jinja Update remote backup flow to universal-auth env vars prior to infisical run.
searxng-docker/template/ansible/deploy.yml.jinja Update Ansible deploy tasks to universal-auth env vars before infisical run.
scripts/deploy-otel-fleet.sh Update otel fleet deploy to universal-auth env vars (no argv secret flags).
scripts/bootstrap-otel-agent.sh Update otel bootstrap sanity check to universal-auth env vars (no argv secret flags).
sandbox-docker/template/terraform/init.sh.jinja Use AWS env vars for Spaces backend auth during tofu init.
sandbox-docker/template/scripts/restore.sh.jinja Update remote restore to universal-auth env vars (no argv secret flags).
sandbox-docker/template/scripts/entrypoint-infisical.sh.jinja Switch Infisical login to universal-auth env vars (no argv secret flags).
sandbox-docker/template/scripts/backup.sh.jinja Update remote backup flow to universal-auth env vars prior to infisical run.
sandbox-docker/template/ansible/deploy.yml.jinja Update Ansible deploy tasks to universal-auth env vars before infisical run.
owncloud-docker/template/terraform/init.sh.jinja Use AWS env vars for Spaces backend auth during tofu init.
owncloud-docker/template/scripts/restore.sh.jinja Update remote restore to universal-auth env vars (no argv secret flags).
owncloud-docker/template/scripts/entrypoint-infisical.sh.jinja Switch Infisical login to universal-auth env vars (no argv secret flags).
owncloud-docker/template/scripts/backup.sh.jinja Update remote backup flow to universal-auth env vars prior to infisical run.
owncloud-docker/template/README.md.jinja Update README examples to avoid argv secret flags for Infisical login.
owncloud-docker/template/ansible/deploy.yml.jinja Update Ansible deploy tasks to universal-auth env vars before infisical run.
otel-agent/README.md Update operator docs to use universal-auth env vars (no argv secret flags).
otel-agent/deploy.yml Update deploy automation to use universal-auth env vars (no argv secret flags).
openclaw-docker/template/terraform/itofu.sh.jinja Update tofu init wrapper to set AWS env vars instead of backend-config secrets.
openclaw-docker/template/terraform/init.sh.jinja Use AWS env vars for Spaces backend auth during tofu init.
openclaw-docker/template/scripts/restore.sh.jinja Update remote restore to universal-auth env vars (no argv secret flags).
openclaw-docker/template/scripts/backup.sh.jinja Update remote backup flow to universal-auth env vars prior to infisical run.
openclaw-docker/template/ansible/deploy.yml.jinja Update Ansible deploy tasks to universal-auth env vars before infisical run.
openclaw-docker/sites/claw-weown-tools/terraform/init.sh Use AWS env vars for Spaces backend auth during tofu init (rendered site).
openclaw-docker/sites/claw-weown-tools/scripts/restore.sh Update rendered restore script to universal-auth env vars (no argv secret flags).
openclaw-docker/sites/claw-weown-tools/scripts/backup.sh Update rendered backup script to universal-auth env vars (no argv secret flags).
openclaw-docker/sites/claw-weown-tools/ansible/deploy.yml Update rendered deploy to universal-auth env vars (no argv secret flags).
openclaw-docker/sites/claw-weown-dev/terraform/itofu.sh Update rendered itofu to set AWS env vars instead of backend-config secrets.
openclaw-docker/sites/claw-weown-dev/terraform/init.sh Use AWS env vars for Spaces backend auth during tofu init (rendered site).
openclaw-docker/sites/claw-weown-dev/scripts/restore.sh Update rendered restore script to universal-auth env vars (no argv secret flags).
openclaw-docker/sites/claw-weown-dev/scripts/backup.sh Update rendered backup script to universal-auth env vars (no argv secret flags).
openclaw-docker/sites/claw-weown-dev/ansible/deploy.yml Update rendered deploy to universal-auth env vars (no argv secret flags).
keycloak-docker/template/terraform/init.sh.jinja Use AWS env vars for Spaces backend auth during tofu init.
keycloak-docker/template/scripts/restore.sh.jinja Update remote restore to universal-auth env vars (no argv secret flags).
keycloak-docker/template/scripts/entrypoint-infisical.sh.jinja Switch Infisical login to universal-auth env vars (no argv secret flags).
keycloak-docker/template/scripts/backup.sh.jinja Update remote backup flow to universal-auth env vars prior to infisical run.
keycloak-docker/template/ansible/deploy.yml.jinja Update Ansible deploy tasks to universal-auth env vars before infisical run.
keycloak-docker/sites/sso.weown.dev/terraform/init.sh Use AWS env vars for Spaces backend auth during tofu init (rendered site).
keycloak-docker/sites/sso.weown.dev/scripts/entrypoint-infisical.sh Update rendered entrypoint to universal-auth env vars (no argv secret flags).
keycloak-docker/sites/sso.weown.dev/ansible/deploy.yml Update rendered deploy to universal-auth env vars (no argv secret flags).
docs/INFISICAL_OUTAGE_RUNBOOK.md Update outage procedure to avoid argv secret flags for Infisical login.
devbox-docker/template/terraform/init.sh.jinja Use AWS env vars for Spaces backend auth during tofu init.
devbox-docker/sites/dev-weown-devbox/terraform/itofu.sh Update rendered itofu to set AWS env vars instead of backend-config secrets.
devbox-docker/sites/dev-weown-devbox/terraform/init.sh Use AWS env vars for Spaces backend auth during tofu init (rendered site).
CHANGELOG.md Record fleet-wide M2 remediation and scope of changes.
anythingllm-docker/template/terraform/itofu.sh.jinja Update tofu init wrapper to set AWS env vars instead of backend-config secrets.
anythingllm-docker/template/scripts/restore.sh.jinja Update remote restore to universal-auth env vars (no argv secret flags).
anythingllm-docker/template/scripts/entrypoint-infisical.sh.jinja Switch Infisical login to universal-auth env vars (no argv secret flags).
anythingllm-docker/template/scripts/backup.sh.jinja Update remote backup flow to universal-auth env vars prior to infisical run.
anythingllm-docker/template/ansible/deploy.yml.jinja Update Ansible deploy tasks to universal-auth env vars before infisical run.
anythingllm-docker/sites/s004.ccc.bot/terraform/itofu.sh Update rendered itofu to set AWS env vars instead of backend-config secrets.
anythingllm-docker/sites/s004.ccc.bot/terraform/init.sh Use AWS env vars for Spaces backend auth during tofu init (rendered site).
anythingllm-docker/sites/s004.ccc.bot/scripts/restore.sh Update rendered restore script to universal-auth env vars (no argv secret flags).
anythingllm-docker/sites/s004.ccc.bot/scripts/backup.sh Update rendered backup script to universal-auth env vars (no argv secret flags).
anythingllm-docker/sites/s004.ccc.bot/ansible/deploy.yml Update rendered deploy to universal-auth env vars (no argv secret flags).
anythingllm-docker/sites/dev-weown-anythingllm/terraform/itofu.sh Update rendered itofu to set AWS env vars instead of backend-config secrets.
anythingllm-docker/sites/dev-weown-anythingllm/scripts/restore.sh Update rendered restore script to universal-auth env vars (no argv secret flags).
anythingllm-docker/sites/dev-weown-anythingllm/scripts/entrypoint-infisical.sh Update rendered entrypoint to universal-auth env vars (no argv secret flags).
anythingllm-docker/sites/dev-weown-anythingllm/scripts/backup.sh Update rendered backup script to universal-auth env vars (no argv secret flags).
anythingllm-docker/sites/dev-weown-anythingllm/ansible/deploy.yml Update rendered deploy to universal-auth env vars (no argv secret flags).
anythingllm-docker/sites/ai.weown.agency/terraform/init.sh Use AWS env vars for Spaces backend auth during tofu init (rendered site).
anythingllm-docker/sites/ai.weown.agency/scripts/restore.sh Update rendered restore script to universal-auth env vars (no argv secret flags).
anythingllm-docker/sites/ai.weown.agency/scripts/backup.sh Update rendered backup script to universal-auth env vars (no argv secret flags).
anythingllm-docker/sites/ai.weown.agency/ansible/deploy.yml Update rendered deploy to universal-auth env vars (no argv secret flags).
anythingllm-docker/DEPLOYMENT_GUIDE.md Update deployment guide examples to avoid argv secret flags for Infisical login.
Comments suppressed due to low confidence (1)

scripts/bootstrap-otel-agent.sh:265

  • The remote bootstrap script unsets INFISICAL_TOKEN after the sanity check, but leaves the universal-auth client ID/secret exported in the remote environment for the remainder of the session. Unset those variables as well to reduce exposure of the Machine Identity secret to any subsequent commands in the session.

Comment on lines 37 to +41
# Step 2: Login to Infisical
export INFISICAL_TOKEN
INFISICAL_TOKEN="$(infisical login --method=universal-auth \
--client-id="$INFISICAL_CLIENT_ID" \
--client-secret="$INFISICAL_CLIENT_SECRET" \
--plain --silent)"
export INFISICAL_UNIVERSAL_AUTH_CLIENT_ID="$INFISICAL_CLIENT_ID"
export INFISICAL_UNIVERSAL_AUTH_CLIENT_SECRET="$INFISICAL_CLIENT_SECRET"
INFISICAL_TOKEN="$(infisical login --method=universal-auth --plain --silent)"
Comment on lines 37 to +41
# Step 2: Login to Infisical
export INFISICAL_TOKEN
INFISICAL_TOKEN="$(infisical login --method=universal-auth \
--client-id="$INFISICAL_CLIENT_ID" \
--client-secret="$INFISICAL_CLIENT_SECRET" \
--plain --silent)"
export INFISICAL_UNIVERSAL_AUTH_CLIENT_ID="$INFISICAL_CLIENT_ID"
export INFISICAL_UNIVERSAL_AUTH_CLIENT_SECRET="$INFISICAL_CLIENT_SECRET"
INFISICAL_TOKEN="$(infisical login --method=universal-auth --plain --silent)"
Comment on lines 157 to +159
if [[ -n "$host" ]]; then
echo "==> Running restore on remote: ${host}"
ssh "$host" "source /opt/$PROJECT_NAME/.infisical-auth.env && export INFISICAL_TOKEN=\"\$(infisical login --method=universal-auth --client-id=\"\$INFISICAL_CLIENT_ID\" --client-secret=\"\$INFISICAL_CLIENT_SECRET\" --plain --silent)\" && infisical run --projectId=\$INFISICAL_PROJECT_ID --env=\$INFISICAL_ENV -- bash -c '$RESTORE_CMDS'"
ssh "$host" "source /opt/$PROJECT_NAME/.infisical-auth.env && export INFISICAL_UNIVERSAL_AUTH_CLIENT_ID=\"\$INFISICAL_CLIENT_ID\" && export INFISICAL_UNIVERSAL_AUTH_CLIENT_SECRET=\"\$INFISICAL_CLIENT_SECRET\" && export INFISICAL_TOKEN=\"\$(infisical login --method=universal-auth --plain --silent)\" && infisical run --projectId=\$INFISICAL_PROJECT_ID --env=\$INFISICAL_ENV -- bash -c '$RESTORE_CMDS'"
Comment on lines 194 to 198
export INFISICAL_TOKEN
INFISICAL_TOKEN="$(infisical login --method=universal-auth \
--client-id="$INFISICAL_CLIENT_ID" \
--client-secret="$INFISICAL_CLIENT_SECRET" \
--silent --plain)"
export INFISICAL_UNIVERSAL_AUTH_CLIENT_ID="$INFISICAL_CLIENT_ID"
export INFISICAL_UNIVERSAL_AUTH_CLIENT_SECRET="$INFISICAL_CLIENT_SECRET"
INFISICAL_TOKEN="$(infisical login --method=universal-auth --silent --plain)"

Comment on lines +62 to +64
export INFISICAL_UNIVERSAL_AUTH_CLIENT_ID=<client-id>
export INFISICAL_UNIVERSAL_AUTH_CLIENT_SECRET=<client-secret>
infisical login --method=universal-auth
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants