Skip to content

ci: fix zizmor template-injection in remaining QA/CD workflows (#21132) - #22386

Merged
AskAlexSharov merged 1 commit into
mainfrom
feature/lystopad/zizmor-ti-final-21132
Jul 11, 2026
Merged

AskAlexSharov merged 1 commit into
mainfrom
feature/lystopad/zizmor-ti-final-21132

Conversation

@lystopad

Copy link
Copy Markdown
Member

Part of #21132 — template-injection cleanup, final batch (all remaining files except release.yml).

After this PR the template-injection ignore list in .github/zizmor.yml contains only release.yml (deferred — it needs a release-pipeline change).

Files fixed / dropped from the ignore list:

  • backups-dashboards.yml
  • ci-cd-main-branch-docker-images.yml
  • ci-gate.yml — already clean at the regular persona (its toJSON(needs) is already routed through an env: block); just removed the stale ignore entry.
  • docker-image-remove.yml
  • qa-sync-from-scratch-full-node.yml
  • test-all-erigon-race.yml

What changed

${{ … }} expansions inside run: blocks are substituted into the script text before the shell parses it, so an attacker-influenced value could inject shell code. Each flagged expansion now arrives as data, not code:

  • Built-ins: github.ref_name → $GITHUB_REF_NAME; runner.name → $RUNNER_NAME; github.workspace → $GITHUB_WORKSPACE.
  • Step-level env: for everything else: inputs.checkout_ref/github.ref conditionals → BRANCH_REF/IMAGE_REF; steps.*.outputs.* → BINARIES/COMMIT_ID/SHORT_COMMIT_ID/BUILD_VERSION*/TAG_KEY/KEEP_IMAGES; github.actor → ACTOR; matrix.test-group → TEST_GROUP; github.repository_owner → REPO_OWNER; the already-defined env.CHAIN/env.MODE/env.TAG_KEY/env.DOCKER_URL/… referenced as plain $VAR.

Security hardening beyond the raw findings

In ci-cd-main-branch-docker-images.yml and docker-image-remove.yml, DockerHub push credentials were interpolated directly into run: text ("'"${{ secrets.… }}"'", JWT ${{ env.TOKEN }}). A secret containing a shell metacharacter could have broken out of the surrounding quoting. These now travel through step env: (DH_USERNAME/DH_TOKEN/TOKEN) and are referenced as shell variables, so the secret value never lands in script text.

Notes

  • The --tag publish flag in the docker build is produced by ${DOCKER_PUBLISH_CONDITION}, left intentionally unquoted so it word-splits into --tag <url>:<ver> (or expands to nothing) — exactly reproducing the previous template behavior. Quoting it would change the docker invocation.
  • The cleanup sed pattern is translated to double quotes so only ${TAG_KEY} expands; \(, \{7\}, \1 remain literal.
  • Constrained expressions (matrix.exec_mode == 'parallel' && … || …, needs.*.result) and trusted command substitutions ($(git rev-parse HEAD)) are left as-is — zizmor does not flag them.
  • Workflow-level run-name: and step name: expansions are display strings, not shell, and are not flagged.

Verification

  • zizmor 1.24.1 (regular persona = CI's) with the repo config: 0 template-injection findings across all six files; full-repo exit code unchanged at 12 (< 14, passes the CI gate).
  • actionlint: 0 errors for every file. The only net-new SC2086 (info-level, CI-ignored) is the intentional ${DOCKER_PUBLISH_CONDITION} word-split noted above; every other variable this PR introduces is quoted.

Route untrusted/dynamic contexts (inputs.*, github.*, runner.*, steps.*,
matrix.*, env.* holding secrets or derived values) through env vars or
GitHub built-ins so their values are treated as data rather than
substituted into shell text. Also move DockerHub push credentials in
ci-cd-main-branch-docker-images.yml out of run-block text into step env.

Leaves only release.yml in the template-injection ignore list in
.github/zizmor.yml (deferred: release-pipeline change).

Part of #21132.
@AskAlexSharov
AskAlexSharov added this pull request to the merge queue Jul 11, 2026
Merged via the queue into main with commit 67a39da Jul 11, 2026
93 checks passed
@AskAlexSharov
AskAlexSharov deleted the feature/lystopad/zizmor-ti-final-21132 branch July 11, 2026 02:13
Sahil-4555 pushed a commit to Sahil-4555/erigon that referenced this pull request Jul 13, 2026
…rigontech#22386) (erigontech#22417)

Two changes to `ci-cd-main-branch-docker-images.yml`, in one PR.

## 1. Fix: empty docker tag broke the image build

The workflow was failing on `main` ([run
29223744087](https://github.com/erigontech/erigon/actions/runs/29223744087)):

```
DOCKER_PUBLISH_CONDITION: --tag :
ERROR: failed to build: invalid tag ":": invalid reference format
```

**Root cause:** `DOCKER_PUBLISH_CONDITION` / `BUILD_VERSION_CONDITION`
computed their tag via `format(…, env.DOCKER_URL, env.BUILD_VERSION)`,
but those are **sibling entries in the same `env:` block**, which GitHub
evaluates to empty. The vars were previously unused (the run blocks
computed the value inline, which works because run-block expressions see
the merged env); erigontech#22386 switched the run blocks to reference the env
vars and exposed the latent bug → `--tag :`.

**Fix:** reference the real sources instead of the siblings — top-level
`env.DOCKERHUB_REPOSITORY` and the `steps.*` outputs (the same values
`DOCKER_URL`/`BUILD_VERSION` derive from), both available at step-env
eval time.

## 2. Discord failure notification

Posts to the repo `DISCORD_WEBHOOK` secret when the build fails on an
automated push (manual dispatch runs are watched by whoever triggered
them). Implemented as a `if: failure()` step inside the `Build` job so
the secret stays scoped to the job's existing `environment:
dockerhub-publish`. No-op when the webhook is unset. Mirrors the nightly
Fuzz workflow's alert.

## zizmor

Runs clean at the **auditor persona** (strictest) after this PR:
- `anonymous-definition` → named the `Build` job.
- `secrets-outside-env` → the webhook is used inside the
environment-scoped `Build` job.
- `concurrency-limits` → intentionally ignored in `.github/zizmor.yml`
(documented): every triggering commit must build and publish, and a
concurrency group would cancel intermediate queued runs.

Verification: `zizmor 1.24.1 --persona=auditor` → *No findings to
report*; `actionlint` → 0 errors; default-persona full-repo gate
unchanged (exit 12, passes).
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