Skip to content

fix(compose): strip and resolve pre-deploy hook secrets like service env - #424

Open
vky5 wants to merge 1 commit into
psviderski:mainfrom
vky5:fix/predeploy-env-secret-leak
Open

fix(compose): strip and resolve pre-deploy hook secrets like service env#424
vky5 wants to merge 1 commit into
psviderski:mainfrom
vky5:fix/predeploy-env-secret-leak

Conversation

@vky5

@vky5 vky5 commented Aug 19, 2026

Copy link
Copy Markdown

Fixes #422.

ServiceSpec.PreDeploy.Env didn't get the same treatment as ServiceSpec.Container.Env in two places.

normaliseContainerForStore strips Config.Env and ServiceSpec.Container.Env before a container record goes into the replicated Corrosion store, but never touched ServiceSpec.PreDeploy.Env. So a secret in x-pre_deploy.environment replicated to every machine in the cluster, while the same value in environment stayed local. Reproduced this on a 3-node ucind cluster, details in #422.

ResolveSecrets had the mirror problem: it only resolved secret://name refs in service.Environment, never in the pre-deploy hook's environment. A secret:// reference there just passed through as a literal string, so secrets never actually worked for pre-deploy hooks in the first place.

This PR fixes both:

  • normaliseContainerForStore now also nils ServiceSpec.PreDeploy.Env.
  • ResolveSecrets now resolves refs in the hook's environment too, through a shared resolveEnvSecrets helper instead of duplicating the loop, so the next env-carrying field doesn't need a second copy of the same logic.
  • HasCommandSecretRefs gets the same treatment for consistency (cosmetic, it only decides whether "Resolving secrets..." gets printed).
  • Added tests for both: a new container_test.go (there wasn't one for this package) pinning the stripping behavior, plus cases in secret_test.go for hook secret resolution and the once-only resolution guarantee across both fields.

Ran go test ./internal/machine/store/... ./pkg/client/compose/... -race, and checked each new test actually fails without its fix by reverting one fix at a time before restoring. gofmt/vet/golangci-lint all clean.

…env (fixes psviderski#422)

normaliseContainerForStore only cleared Config.Env and
ServiceSpec.Container.Env before writing a container record to the
replicated Corrosion store, leaving ServiceSpec.PreDeploy.Env in place.
A secret set via x-pre_deploy.environment therefore replicated to
every machine in the cluster, unlike the same value set via
environment.

ResolveSecrets had the same asymmetry in the other direction: it only
resolved secret://name references in service.Environment, so a
reference placed in the pre-deploy hook's environment passed through
unresolved as a literal string. HasCommandSecretRefs is extended the
same way for consistency.

Add tests pinning both behaviours.
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.

[BUG] PreDeploy.Env is not stripped before replication to the cluster store, while Container.Env is

1 participant