Skip to content

ci(grype): install pinned grype by checksum, drop scan-action - #294

Closed
stephrobert wants to merge 1 commit into
getplumber:mainfrom
stephrobert:fix/grype-mutable-remote-exec
Closed

ci(grype): install pinned grype by checksum, drop scan-action#294
stephrobert wants to merge 1 commit into
getplumber:mainfrom
stephrobert:fix/grype-mutable-remote-exec

Conversation

@stephrobert

Copy link
Copy Markdown
Contributor

Problem

The grype container-scan job pins anchore/scan-action by commit SHA, which
looks immutable. It is not. At runtime the action fetches and executes an
install script from a moving ref:

// anchore/scan-action — action.js
const installScriptUrl = `https://raw.githubusercontent.com/anchore/grype/main/install.sh`;
const installScriptPath = await tools.downloadTool(installScriptUrl);
// ...then executed

anchore/grype@main can change with no change to anything committed here, so the
SHA pin gives a false sense of immutability: the code actually executed in CI is
not pinned. This is the supply-chain gap that pin-by-SHA does not close when an
action pulls remote code.

Fix

Install the pinned grype release directly and verify it against a SHA-256 that
lives in this workflow — the only trust anchor, immutable unless this file
changes — then run grype with the same gate:

env:
  GRYPE_VERSION: "0.114.0"
  GRYPE_SHA256: "edda0968d8827daab01d32b3cd7de192ae0915005e7bbfcfef9e68e79bc43343"
run: |
  set -euo pipefail
  tmp="$(mktemp -d)"
  curl -sSfL -o "$tmp/grype.tar.gz" \
    "https://github.com/anchore/grype/releases/download/v${GRYPE_VERSION}/grype_${GRYPE_VERSION}_linux_amd64.tar.gz"
  echo "${GRYPE_SHA256}  $tmp/grype.tar.gz" | sha256sum -c -
  tar -xzf "$tmp/grype.tar.gz" -C "$tmp" grype
  sudo install "$tmp/grype" /usr/local/bin/grype
# scan
run: grype "plumber:ci" --fail-on high --only-fixed

To bump grype, update both GRYPE_VERSION and GRYPE_SHA256 together (the hash
is published in the release's checksums.txt).

Verification

Locally, against grype 0.114.0: download + sha256sum -c + extract + grype version + --fail-on high --only-fixed all succeed. Same severity gate as
before (fail on fixable high+).

Note

The general case — a pinned third-party action that fetches/executes mutable
remote code — is not something Plumber detects today (pin-by-SHA passes it).
That detection is worth a dedicated control and will be tracked separately.

anchore/scan-action, even pinned by commit SHA, fetches and executes
`install.sh` from anchore/grype@main at runtime (see action.js:
`https://raw.githubusercontent.com/anchore/grype/main/install.sh`).
`main` is a moving ref, so the pinned SHA gives a false sense of
immutability: the code actually executed in CI can change with no
change to anything committed here.

Replace the action with a direct install of the pinned grype release,
verified against a SHA-256 committed to this repo — the only trust
anchor, immutable unless this file changes. Then run grype directly
with the same gate (--fail-on high --only-fixed).

Verified locally: download + checksum + extract + flags all succeed
against grype 0.114.0.

@thomasboni thomasboni left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Verified the PR independently: the sha256 matches my own download of the official release asset and the official checksums.txt, the CI run proves the chain works end-to-end, and the severity gate is an exact match for the old action's behavior. One small parity gap with the replaced action below.

Comment thread .github/workflows/ci.yml
fail-build: true
severity-cutoff: high
only-fixed: true
run: grype "plumber:ci" --fail-on high --only-fixed

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The replaced anchore/scan-action set GRYPE_CHECK_FOR_APP_UPDATE: false; without it grype makes a phone-home update check on every scan. Restoring it keeps parity and drops an unneeded network call:

Suggested change
run: grype "plumber:ci" --fail-on high --only-fixed
env:
GRYPE_CHECK_FOR_APP_UPDATE: "false"
run: grype "plumber:ci" --fail-on high --only-fixed

thomasboni added a commit that referenced this pull request Jul 3, 2026
anchore/scan-action, though pinned by SHA, downloads and executes
install.sh from anchore/grype@main at every run, a moving ref the pin
does not cover. Install the pinned grype release directly instead and
verify it against a sha256 committed in the workflow, then scan with
the same severity gate as before (fail on fixable high+). Also disable
grype's phone-home update check, which the removed action used to turn
off.

Redoes #294 by @stephrobert with the review suggestion applied, since
the original branch could not be updated.

Co-authored-by: Stéphane ROBERT <robert.stephane.28@gmail.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@thomasboni

Copy link
Copy Markdown
Contributor

Merged in #298

@thomasboni thomasboni closed this Jul 3, 2026
plumber-release-bot Bot pushed a commit that referenced this pull request Jul 6, 2026
## [0.3.87](v0.3.86...v0.3.87) (2026-07-06)

### 🐛 Bug Fixes

* **collect:** contain local CI-config reads and skip symlinked Dockerfiles ([ef9c275](ef9c275))
* **gitlab:** harden local include resolution ([729e259](729e259))

### ♻️ Refactoring

* **render:** sanitize repo-derived text and bound resource use ([17ed05e](17ed05e))
* **score:** resolve the score endpoint from CLI/env only ([0a89351](0a89351))

### 👷 CI/CD

* **grype:** install pinned grype by checksum, drop scan-action ([a275cdf](a275cdf)), closes [#294](#294)
* pin runtime tool installs to immutable versions ([a203b7f](a203b7f))
* **release:** pin v0.3.86 refs [skip ci] ([101cd21](101cd21))
* **release:** stop persisting credentials in the pin-refs checkout ([8f0f261](8f0f261)), closes [#293](#293)
* **scorecard:** document the action's mutable-image gap ([61c8cdd](61c8cdd))
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