Skip to content

fix: migrate secret and input interpolations to env: block pattern (PM-22118)#850

Merged
m2ux merged 11 commits into
mainfrom
fix/PM-22118-secret-input-interpolation-remediation
Mar 5, 2026
Merged

fix: migrate secret and input interpolations to env: block pattern (PM-22118)#850
m2ux merged 11 commits into
mainfrom
fix/PM-22118-secret-input-interpolation-remediation

Conversation

@m2ux

@m2ux m2ux commented Mar 3, 2026

Copy link
Copy Markdown
Contributor

Summary

Remediate seven CI/CD security audit findings (M-F007 through M-F014) by migrating direct ${{ }} expression interpolation in GitHub Actions shell run: blocks to env: block indirection. Deep-dive analysis confirmed M-F012 as a false positive, refining the scope to 10 code changes across 7 files.

🎫 Ticket 📐 Engineering 🧪 Test Plan


Motivation

Secrets and workflow_dispatch inputs are interpolated directly into shell run: blocks via ${{ }}. This means values are pasted verbatim into shell commands before execution, creating shell metacharacter injection and expression injection vulnerabilities. Workflows with packages:write permissions make this a supply-chain risk.

Each vulnerable interpolation is replaced with a two-part pattern: a step-level env: block maps a descriptive variable name to the ${{ }} expression, and the run: block references the value via "$VAR". This ensures values are always treated as data, never as executable code. All workflows behave identically — the change is invisible to end users.


Changes

  • main.yml — 3 findings (M-F007, M-F008, M-F010a): REGISTRY_TOKEN for docker login, GITHUB_TOKEN for earthly (×2)
  • prs.yml — 1 finding (M-F009): GHCR_SECRET for GHCR bearer token base64
  • continuous-integration-test.yml — 1 finding (M-F010b): GITHUB_TOKEN for earthly test
  • continuous-integration.yml — 1 finding (M-F010c): REGISTRY_TOKEN for docker login
  • build-publish-contract-precompiles-image.yml — 1 finding (M-F010d): GH_TOKEN for earthly
  • build-publish-contract-precompiles.yml — 2 findings (M-F011): RUST_VERSION for dispatch input (build + publish jobs)
  • indexer/.github/workflows/build-indexer-images.yaml — 1 finding (M-F014): NODE_TAG_INPUT for dispatch input (3 interpolation sites)

Excluded: M-F012 (release-image.yml) — confirmed false positive. Lines 87 and 265 are with: blocks (safe action input context, not shell interpolation).

Follow-up items (deferred to separate tickets under PM-22116):

  • FU-1: Supplementary hardening (permissions restriction, input validation)
  • FU-2: Tainted data flow remediation in release-image.yml
  • FU-3: actionlint CI step for workflow validation

📌 Submission Checklist

  • Changes are backward-compatible (or flagged if breaking)
  • Pull request description explains why the change is needed
  • Self-reviewed the diff
  • I have included a change file, or skipped for this reason: included
  • If the changes introduce a new feature, I have bumped the node minor version — N/A (security fix, no new features)
  • Update documentation (if relevant) — N/A
  • No new todos introduced

🔱 Fork Strategy

  • Node Runtime Update
  • Node Client Update
  • Other
  • N/A

🗹 TODO before merging

  • Ready for review
  • Address reviewer feedback

Secret and input interpolation remediation for CI/CD workflows.
See: https://shielded.atlassian.net/browse/PM-22118

Made-with: Cursor
@github-actions

github-actions Bot commented Mar 3, 2026

Copy link
Copy Markdown
Contributor

kics-logo

KICS version: v2.1.19

Category Results
CRITICAL CRITICAL 0
HIGH HIGH 0
MEDIUM MEDIUM 47
LOW LOW 3
INFO INFO 59
TRACE TRACE 0
TOTAL TOTAL 109
Metric Values
Files scanned placeholder 26
Files parsed placeholder 26
Files failed to scan placeholder 0
Total executed queries placeholder 73
Queries failed to execute placeholder 0
Execution time placeholder 11

m2ux added 2 commits March 3, 2026 15:53
Replace direct ${{ secrets.* }} and ${{ github.event.inputs.* }}
interpolation in shell run: blocks with env: block indirection
across 6 workflow files:

- main.yml: M-F007 (docker login), M-F008 (earthly ARM64),
  M-F010a (earthly AMD64)
- prs.yml: M-F009 (GHCR bearer token base64)
- continuous-integration-test.yml: M-F010b (earthly test)
- continuous-integration.yml: M-F010c (docker login)
- build-publish-contract-precompiles-image.yml: M-F010d (earthly)
- build-publish-contract-precompiles.yml: M-F011 (dispatch input
  rust_version, 2 locations)

M-F012 (release-image.yml) confirmed as false positive — with:
blocks are safe. M-F014 (indexer submodule) requires separate
commit coordination.

Made-with: Cursor
Update indexer submodule pointer to include the M-F014 fix:
migrate ${{ github.event.inputs.node_tag }} direct interpolation
to env: block indirection in build-indexer-images.yaml.

Made-with: Cursor
@m2ux m2ux marked this pull request as ready for review March 3, 2026 16:18
@m2ux m2ux requested a review from a team as a code owner March 3, 2026 16:18
Add change file for secret input interpolation remediation to satisfy
the check-changes CI requirement.

Made-with: Cursor
@m2ux m2ux self-assigned this Mar 4, 2026
m2ux and others added 6 commits March 4, 2026 14:16
Resolve 4 conflicts in 3 files where main's refactoring (quoting
style, export pattern) overlapped with PM-22118 env: block
remediation. Keep env var references, adopt main's style changes.

Made-with: Cursor
…les-image.yml

File was deleted on main. M-F010d remediation for this file is no
longer applicable — the vulnerable workflow no longer exists.

Made-with: Cursor
Rebase the indexer fix commit onto current indexer main (e8ecb1a) so
the build-indexer-images CI job has access to the indexer-api build
target. Previous pointer was forked from an older indexer main that
predated the indexer-api image addition.

Made-with: Cursor
Rebase indexer PM-22118 fix onto the same base commit as main
(3f0a8ef) to resolve justfile namespace mismatch. The previous
pointer was rebased onto indexer HEAD (e8ecb1a) which changed
docker image tags from ghcr.io/midnight-ntwrk/ to midnightntwrk/,
causing the CI retagging step to fail.

Made-with: Cursor
M-F014 (build-indexer-images.yaml) is in the indexer repo and out of
scope for this midnight-node PR. Revert submodule to main's pointer.
M-F014 remediation will be tracked as a separate indexer PR.

Made-with: Cursor
@m2ux m2ux added this pull request to the merge queue Mar 5, 2026
Merged via the queue into main with commit 9c1ce4d Mar 5, 2026
35 checks passed
@m2ux m2ux deleted the fix/PM-22118-secret-input-interpolation-remediation branch March 5, 2026 15:52
gilescope pushed a commit that referenced this pull request Apr 8, 2026
changed:
- stack config accepts only Kubernetes and Docker executors -> see e2e-tests/docs/configure-stack.md on how to use it
- saving files on remote host is done only via write_file fixture, which handles removing data after test completes
- write_file fixture can write non-json files as well

removed:
- SSHRunner
- binary-host dependency

Refs: ETCM-9557
m2ux added a commit that referenced this pull request Apr 23, 2026
changed:
- stack config accepts only Kubernetes and Docker executors -> see e2e-tests/docs/configure-stack.md on how to use it
- saving files on remote host is done only via write_file fixture, which handles removing data after test completes
- write_file fixture can write non-json files as well

removed:
- SSHRunner
- binary-host dependency

Refs: ETCM-9557
Signed-off-by: Mike Clay <mike.clay@shielded.io>
m2ux added a commit that referenced this pull request Apr 23, 2026
changed:
- stack config accepts only Kubernetes and Docker executors -> see e2e-tests/docs/configure-stack.md on how to use it
- saving files on remote host is done only via write_file fixture, which handles removing data after test completes
- write_file fixture can write non-json files as well

removed:
- SSHRunner
- binary-host dependency

Refs: ETCM-9557
Signed-off-by: Mike Clay <mike.clay@shielded.io>
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