Skip to content

fix(plugin): guard mounted secret invocations (D-0559, D-0651, D-0707) - #972

Merged
acamarata merged 1 commit into
mainfrom
dw4-cli-3
Oct 26, 2026
Merged

acamarata merged 1 commit into
mainfrom
dw4-cli-3

Conversation

@acamarata

Copy link
Copy Markdown
Collaborator

Mounted plugin commands could receive restored machine-invocation secrets on their own process arguments. Refuse these calls with E421 before starting the binary until the plugin protocol supports a secret handoff. Ordinary machine and direct calls continue to execute.

Rows verified against fresh origin/main at 309e2ed8:

  • D-0559: ALREADY-FIXED. Commit 3993b4eb (fix(redaction): mask basic auth and preserve loopback mappings (D-0559) #806) adds BASICAUTH to the shared secret-name rule, a generated Mailpit diff regression, and loopback mapping coverage. Redis healthchecks use REDISCLI_AUTH with no password argument (internal/compose/cache_service.go). No changes for this row.
  • D-0651: FIXED. Record successful secret restoration for the current invocation, reset that state on each restoration, and refuse mounted binary execution when secrets were restored. Regression coverage exercises positional and flag handoffs, secret-free errors, state reset, and ordinary machine/direct calls. Update the protocol constraint comment and plugin security documentation.
  • D-0707: BLOCKED. The deliberate all-files guard and TestPersistGeneratedSecrets_LoadKeysOnlyInInactiveEnvNotPersisted remain. Shared .env.secrets loads after the active env file; removing the guard would override another environment's real credentials. A complete fix needs an approved per-environment persistence design choosing active-env file writes or a new secrets layer and its precedence. No cascade or persistence changes made.

Validation:

  • GOTOOLCHAIN=go1.26.10 CGO_ENABLED=0 go test -mod=vendor ./internal/config ./internal/observability ./internal/reconcile -run 'Test(IsSecretKey|RedactPreservesLoopbackPortMappings|UnifiedHidesGeneratedMailpitBasicAuth|UnifiedHidesGeneratedRedisPassword)$' -count=1: PASS.
  • GOTOOLCHAIN=go1.26.10 CGO_ENABLED=0 go test -mod=vendor ./cmd/commands -run 'TestMountProxyRestoredSecrets|TestRestoreSecretArgvMasksRestoredValues' -count=1: PASS. Negative control with the proxy guard disabled and -run '^TestMountProxyRestoredSecrets$': both secret cases FAIL because the binary executes (exit 19). Guard restored.
  • GOTOOLCHAIN=go1.26.10 CGO_ENABLED=0 go test -mod=vendor ./cmd/commands ./internal/invoke -count=1: PASS (303s and 21s).
  • GOTOOLCHAIN=go1.26.10 make build BINARY=/Volumes/D5/tmp/dw4-cli-3.B5TBjH/nself: PASS.
  • GOTOOLCHAIN=go1.26.10 CGO_ENABLED=0 go vet -mod=vendor ./cmd/commands ./internal/invoke: PASS.
  • GOTOOLCHAIN=go1.26.10 CGO_ENABLED=0 GOFLAGS=-mod=vendor golangci-lint run ./cmd/commands/... ./internal/invoke/...: PASS, 0 issues.
  • make fmt-check and git diff --check: PASS.

Temporary output uses /Volumes/D5/tmp/dw4-cli-3.B5TBjH; all Go checks use the repository-pinned toolchain and vendored dependencies. No check failures required a clean-main comparison.

No HQ files changed. No release, version, production, or repository-settings changes.

@acamarata
acamarata merged commit 541a640 into main Oct 26, 2026
35 of 37 checks passed
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.

1 participant