Skip to content

fix: reject env values with line breaks in config templates - #154

Open
Hermsi1337 wants to merge 1 commit into
mainfrom
fix/reject-multiline-env-values
Open

fix: reject env values with line breaks in config templates#154
Hermsi1337 wants to merge 1 commit into
mainfrom
fix/reject-multiline-env-values

Conversation

@Hermsi1337

Copy link
Copy Markdown
Member

Summary

Fixes #153.

Values substituted via {{ .Env.NAME }} were spliced into the YAML verbatim by text/template. A value containing \n or \r:

  • escaped its position and was parsed as new top-level YAML — silently corrupting the stack definition that UpdateStack then applies as full state (quoting does not protect; a " + newline in the value breaks out of quoted scalars too),
  • or, for legitimate multi-line secrets (PEM/SSH keys) in quoted positions, was silently line-folded into a space-joined single line — deploying a broken key with no warning.

Changes

  • cmd/action/main.go: renderConfigTemplate() now performs a probe render first, in which every env value containing a line break is replaced by a nonce-derived token. If a token appears in the output, that variable actually reached the YAML and rendering fails with an error naming it:

    environment variable "DATABASE_URL" contains a line break and cannot be used in the configuration template; a line break would corrupt the resulting YAML document
    

    Otherwise the template is rendered with the real values as before. Properties:

    • {{ .Env.NAME }} syntax and semantics unchanged for single-line values (.Env stays a plain map[string]string).
    • Complete by construction — also covers {{ index .Env "X" }} and {{ range .Env }}, which map-skipping or parse-tree-walking approaches miss silently.
    • Zero false positives: unreferenced multi-line env vars (common on GitHub runners) and references in untaken {{ if }} branches keep working.
  • cmd/action/main_test.go: table-driven reject tests (value position, comment position, quoted breakout, CRLF, lone CR, trailing CR, quoted PEM, index) plus three false-positive guards. Existing tests untouched.

  • README.md: > [!IMPORTANT] note that {{ .Env.NAME }} values must be single-line.

Testing

  • go test -count=1 ./...: all pass (22 top-level tests, 8 new subtests) in golang:1.24.
  • go vet ./... and gofmt: clean.
  • golangci-lint (the Makefile's quay.io/mittwald/golangci-lint:0.0.38 image with the repo config): no findings.

Behavior change

Workflows that today reference a multi-line secret from a quoted position "succeed" while silently deploying a folded, broken value. They will now fail loudly with the error above — this is the intended fix, but worth calling out in the release notes.

Related: #151 / #152 (template rendering vs. YAML comments — independent, composes cleanly with this change).

🤖 Generated with Claude Code

Values substituted via {{ .Env.NAME }} were spliced into the YAML
verbatim. A value containing a line break escaped its position and was
parsed as new top-level YAML, silently corrupting the stack definition;
quoted multi-line secrets were silently folded into a single line.

A probe render now substitutes every line-break-carrying value with a
nonce token first. Only values that actually reach the rendered output
are rejected, with an error naming the variable, so unreferenced
multi-line variables (common on GitHub runners) keep working.

Closes #153

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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.

Env variables containing line breaks silently corrupt the rendered stack YAML

1 participant