Skip to content

fix(security): pin Semgrep CI container image by SHA digest [DEVA11Y-476] - #15

Merged
Crash0v3rrid3 merged 2 commits into
mainfrom
fix/DEVA11Y-476-pin-semgrep-image
May 27, 2026
Merged

fix(security): pin Semgrep CI container image by SHA digest [DEVA11Y-476]#15
Crash0v3rrid3 merged 2 commits into
mainfrom
fix/DEVA11Y-476-pin-semgrep-image

Conversation

@sunny-se

@sunny-se sunny-se commented May 26, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Chain-breaker for C-001 (DEVA11Y-485, CVSS 10.0): pins the Semgrep CI container image to a SHA256 digest, eliminating the tag-poisoning vector (F-004 / CWE-829).
  • The workflow previously used returntocorp/semgrep with no tag or digest — any upstream tag mutation would silently alter the CI environment.
  • Now pinned to returntocorp/semgrep@sha256:f682953ce85e3725f4a4dd94bd7ad13e570bb6b2c7a8cf7c6e38a9eac89239b2 (latest amd64 as of 2026-05-26).

Verification

  • Confirm .github/workflows/Semgrep.yml line 31 contains @sha256: (no bare tag).
  • Semgrep CI job should still pass on this PR's check suite.

Jira

🤖 Generated with Claude Code

F-004 / DEVA11Y-476 — The Semgrep workflow used an unpinned image tag
(CWE-829), enabling tag-poisoning attacks. Pin to SHA256 digest.
This is the chain-breaker for C-001 (DEVA11Y-485, CVSS 10.0).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@sunny-se
sunny-se requested a review from a team as a code owner May 26, 2026 08:59
@Crash0v3rrid3
Crash0v3rrid3 merged commit 93d2f48 into main May 27, 2026
5 checks passed
Crash0v3rrid3 added a commit that referenced this pull request Aug 28, 2026
…A11Y-476] (#38)

* chore(deps): add Dependabot to rotate the pinned Semgrep CI image (DEVA11Y-476)

The Semgrep workflow container image is already pinned by immutable @sha256
digest (PR #15), which is the DEVA11Y-476 chain-breaker for the C-001 chain
(DEVA11Y-485: CI image compromise -> mutable main -> SPM plugin RCE). A static
digest, however, never receives upstream security patches — the current pin
already lags returntocorp/semgrep:latest.

Add .github/dependabot.yml with a `docker` ecosystem entry over
/.github/workflows so Dependabot bumps the pinned digest to the newest build on
a weekly cadence, keeping immutability without freezing the image.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* chore(ci): add cooldown to Dependabot Semgrep image updates

Adds a release-age cooldown so Dependabot does not adopt a freshly-published
returntocorp/semgrep digest immediately — a poisoned-image would otherwise be
pulled in within a day of publication, the exact window digest-pinning is meant
to defend (DEVA11Y-476 / chain DEVA11Y-485). Also resolves the semgrep/ci
finding flagging the update config for lacking a minimum release age.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* chore(ci): rotate GitHub Actions via Dependabot + drift-alarm the Semgrep image

Dependabot's `docker` ecosystem cannot discover a `container:` image ref in a
workflow file (dependabot-core#5819), so the previous `docker`/`/.github/workflows`
config would never rotate the pin and would fail a weekly Dependabot job. Pivot:

- dependabot.yml: replace the unusable `docker` entry with a `github-actions`
  entry (directory "/", weekly, cooldown default-days 7) — real, supported
  rotation for the action `uses:` pins here, several of which are 3 years stale.
  Drop the undefined `security` label and the redundant open-pull-requests-limit.
  Cooldown retained (also clears the semgrep/ci dependabot-missing-cooldown rule).
- Add semgrep-image-pin-drift.yml: read-only scheduled/dispatch job that alarms
  (fails) when the pinned returntocorp/semgrep@sha256 digest drifts from :latest,
  keeping a human in the loop on the image bump (better for the C-001 threat model
  than auto-adopting latest).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* chore(ci): address PR#38 round-2 review (cooldown/drift/pin/guard)

Resolves Nishant's second review on PR #38:

1. cooldown is inert for the github-actions Dependabot ecosystem — kept only
   to satisfy Semgrep's dependabot-missing-cooldown rule; documented as inert
   in dependabot.yml (no real release-age protection for action bumps).
2. Semgrep image drift workflow: made the intended-failure branches reachable
   under GHA's injected `bash -e` (|| true on the grep/token/latest command
   substitutions + explicit empty-token guard), same class of fix as #37
   66249fe. Verified: happy/stale/pin-removed/registry-down all annotate+exit.
3. Reworked the alarm from "differs from :latest" (red most weeks → muted) to
   "pinned image older than 45 days" (actionable). Bumped the Semgrep image
   pin to the current :latest digest so it lands green:
   f682953… -> f1f7b71861c7b28b6e0f661225a2c4f58a484f5d0f182465c6d6b3b22f972ade
   (created 2026-08-20, ~8 days old).
4. Removed the job-level `if: github.actor != 'dependabot[bot]'` guard on
   Semgrep.yml and scoped it to only the privileged upload-sarif step, so
   Dependabot PRs that bump the action pins living in Semgrep.yml still get
   scanned; only the security-events:write SARIF upload is skipped for them.

Also documented the scheduled-workflow ops caveat (60-day inactivity disable;
failed runs notify only the last cron editor) in the drift workflow.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

2 participants