Skip to content

ci: pipeline-security tooling — Harden-Runner (audit) + zizmor + actionlint - #308

Merged
devopam merged 2 commits into
mainfrom
claude/harden-runner-audit
Aug 14, 2026
Merged

ci: pipeline-security tooling — Harden-Runner (audit) + zizmor + actionlint#308
devopam merged 2 commits into
mainfrom
claude/harden-runner-audit

Conversation

@devopam

@devopam devopam commented Aug 14, 2026

Copy link
Copy Markdown
Owner

Summary

Adds the CI/CD-pipeline security controls we agreed on after reviewing the awesome-cicd-security and Orca lists. Everything else on those lists was already covered by your existing stack (Scorecard, CodeQL, bandit, pip-audit, Dependabot, fuzzing, signed releases, OIDC) or was offensive/audit-only tooling — the genuine gaps were runtime egress control and GitHub-Actions-specific static analysis.

1. StepSecurity Harden-Runner (audit mode) — added as the first step of every job across all 7 workflows (18 jobs). In egress-policy: audit it only monitors outbound traffic (can't block anything), capturing the egress baseline. The defence against the compromised-Action call-home/exfiltration class (tj-actions-style). Next step, once the baseline is reviewed: allow-list egress and flip the sensitive workflows (publish first) to block.

2. zizmor (actions-security.yml) — static security analysis of the workflows (template injection, artifact credential persistence, over-broad permissions) via uvx zizmor@1.9.0 → SARIF to the code-scanning dashboard.

3. actionlint — workflow linter (syntax + shell-script bugs) via SHA-pinned raven-actions/actionlint.

Both scanners start in reporting mode (findings surface, don't block), matching the Harden-Runner audit posture. Promote to blocking after triaging the baseline.

zizmor already found a useful baseline

Run locally (offline) as a pre-check — 22 findings (3 high, 11 medium), all real and worth a focused follow-up:

  • High — excessive-permissions: id-token: write at the workflow level in publish.yml (only the trusted-publishing jobs need it).
  • Medium — artipacked: several actions/checkout steps lack persist-credentials: false.

Kept out of this PR to keep it scoped to introducing the tooling; the new actions-security.yml checkouts already set persist-credentials: false as the pattern to follow.

⚠️ Merge ordering vs #307

This PR and #307 (SBOM/provenance/CODEOWNERS) both modify publish.yml, so they'll conflict. Suggest merge #307 first, then I'll rebase this branch onto it (mechanical — different regions of the build job).

Validation

  • ✅ All 8 workflows YAML-valid; new action refs SHA-pinned
  • ✅ zizmor executed locally (offline audits) — runs clean, produces SARIF
  • ⚠️ Harden-Runner audit steps + the scanners only exercise on their triggers; audit mode can't break existing jobs (monitor-only). No source/test change.

Roadmap linkage

Advances roadmap row: N/A — CI/supply-chain hardening.

Checklist

  • Tests — N/A (CI-only); workflows validated + zizmor run locally
  • ruff/mypy — no source change
  • CHANGELOG.md updated under [Unreleased]
  • Roadmap row cited (N/A)
  • No hand-edits to src/mcpg/_vendor/

🤖 Generated with Claude Code

https://claude.ai/code/session_0122yLZLJ8t4W43sdN6BmTZc


Generated by Claude Code

Summary by Sourcery

Introduce CI/CD pipeline security tooling focused on GitHub Actions egress auditing and workflow analysis.

New Features:

  • Add StepSecurity Harden-Runner in audit mode as the first step of every job across all GitHub Actions workflows to monitor runtime egress.
  • Add a dedicated Actions Security workflow running zizmor for GitHub Actions security analysis with SARIF reporting to the code-scanning dashboard.
  • Add actionlint-based workflow linting to validate GitHub Actions syntax, expressions, and shell usage in reporting mode.

Enhancements:

  • Document the new pipeline security tooling and its audit-first rollout under the Unreleased Security section of the changelog.

@github-advanced-security

Copy link
Copy Markdown

You are seeing this message because GitHub Code Scanning has recently been set up for this repository, or this pull request contains the workflow file for the Code Scanning tool.

What Enabling Code Scanning Means:

  • The 'Security' tab will display more code scanning analysis results (e.g., for the default branch).
  • Depending on your configuration and choice of analysis tool, future pull requests will be annotated with code scanning analysis results.
  • You will be able to see the analysis results for the pull request's branch on this overview once the scans have completed and the checks have passed.

For more information about GitHub Code Scanning, check out the documentation.

@sourcery-ai sourcery-ai Bot 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.

Hey - I've found 1 issue, and left some high level feedback:

  • Consider extracting the repeated Harden-Runner step into a reusable workflow or composite action to reduce duplication and make future policy changes (e.g., switching from audit to block) easier to apply consistently.
  • For the zizmor and actionlint jobs that are intentionally non-blocking, you may want to add a clear TODO or comment indicating the planned criteria or timeline for flipping continue-on-error/fail-on-error to blocking, so the audit posture doesn’t become permanent by accident.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- Consider extracting the repeated Harden-Runner step into a reusable workflow or composite action to reduce duplication and make future policy changes (e.g., switching from audit to block) easier to apply consistently.
- For the zizmor and actionlint jobs that are intentionally non-blocking, you may want to add a clear TODO or comment indicating the planned criteria or timeline for flipping `continue-on-error`/`fail-on-error` to blocking, so the audit posture doesn’t become permanent by accident.

## Individual Comments

### Comment 1
<location path="CHANGELOG.md" line_range="13-15" />
<code_context>
+- **Pipeline-security tooling: Harden-Runner, zizmor, actionlint.**
+  - **StepSecurity Harden-Runner** added (audit/egress-monitoring mode) as the
+    first step of every job across all workflows — captures a runtime egress
+    baseline so outbound traffic can later be allow-listed (block mode). The
+    defence against compromised-Action call-home / exfiltration.
+  - **zizmor** (`.github/workflows/actions-security.yml`) — static security
+    analysis of the Actions workflows (template injection, artifact
</code_context>
<issue_to_address>
**suggestion (typo):** Clarify sentence fragment and fix awkward hyphenation in "compromised-Action".

This line reads as a sentence fragment, and the hyphen in "compromised-Action" is awkward. Please rephrase into a full sentence and drop the hyphen, e.g. "This provides defence against compromised Action call-home / exfiltration."

```suggestion
    first step of every job across all workflows — captures a runtime egress
    baseline so outbound traffic can later be allow-listed (block mode). This
    provides defence against compromised Action call-home / exfiltration.
```
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread CHANGELOG.md Outdated
…onlint

Runtime + static hardening of the CI/CD pipeline itself, from the
CI/CD-security review.

- StepSecurity Harden-Runner added as the first step of every job across
  all 7 workflows (18 jobs), in audit/egress-monitoring mode. Captures a
  runtime egress baseline so traffic can later be allow-listed (block
  mode). Defends against compromised-Action call-home / exfiltration.
- New .github/workflows/actions-security.yml:
  - zizmor (uvx zizmor@1.9.0) — Actions static security analysis
    (template injection, artifact credential persistence, over-broad
    permissions) → SARIF to the code-scanning dashboard.
  - actionlint (raven-actions/actionlint, SHA-pinned) — workflow linter.
- Both scanners start in reporting mode (non-blocking) to match the
  Harden-Runner audit rollout; promote to blocking after triage.

All new action refs SHA-pinned. Workflows YAML-validated; zizmor run
locally (offline) as a pre-check — it already surfaces a useful baseline
(id-token scoping, persist-credentials on checkouts) for a follow-up.

Roadmap linkage: N/A — CI/supply-chain hardening.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0122yLZLJ8t4W43sdN6BmTZc
@devopam
devopam force-pushed the claude/harden-runner-audit branch from 5abf090 to 3ec9819 Compare August 14, 2026 06:00
Review follow-up (#308):
- Add explicit TODO(security) markers with criteria on the zizmor
  `continue-on-error` and actionlint `fail-on-error` so the reporting/
  audit posture doesn't silently become permanent — flip to blocking
  once the baseline is triaged clean.
- Rephrase the CHANGELOG Harden-Runner bullet from a sentence fragment
  ("The defence against compromised-Action…") into a full sentence.

Declined the "extract Harden-Runner into a composite/reusable action"
suggestion: harden-runner must be the first step (before checkout) to
monitor the checkout itself, but a local composite action needs checkout
to run first to be resolvable — a chicken-and-egg that leaves the
checkout unmonitored. Block-mode allow-lists are per-workflow anyway.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0122yLZLJ8t4W43sdN6BmTZc

devopam commented Aug 14, 2026

Copy link
Copy Markdown
Owner Author

Thanks — addressed in e93bd45:

  • TODO/criteria for flipping to blocking ✅ — added explicit TODO(security) markers on both the zizmor continue-on-error and actionlint fail-on-error, with the criterion (flip once the baseline triages to zero High/Medium findings). Good guard against the audit posture becoming permanent by accident.

  • CHANGELOG fragment / "compromised-Action" ✅ — rephrased into a full sentence, hyphen dropped.

  • Extract Harden-Runner into a reusable/composite action — declining, on a technical constraint: Harden-Runner must be the first step, before actions/checkout, so it can monitor the checkout itself. A local composite action (uses: ./…) isn't resolvable until the repo is checked out, so wrapping the step in one would force checkout to run first — leaving that step (the highest-value one to watch) unmonitored. Reusable workflows can't inject a single first step either. And since block-mode allowed-endpoints differ per workflow, a shared definition wouldn't reduce the real per-workflow work. The repeated 4-line block is the least-bad option here; the SHA stays consistent because it's pinned identically everywhere (Dependabot updates them together).


Generated by Claude Code

@devopam
devopam merged commit fdbd317 into main Aug 14, 2026
27 checks passed
@devopam
devopam deleted the claude/harden-runner-audit branch August 14, 2026 06:31
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.

3 participants