diff --git a/CLAUDE.md b/CLAUDE.md index d6b53ed..8ffff6a 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -19,7 +19,7 @@ GitHub Actions の最新バージョン・SHA 情報の取得、SHA ピン留め - `agents/actver.md` — エージェント定義 - `skills/` → `../../skills/` へのシンボリックリンク - `skills/` — スキル定義(skills.sh 互換、マルチエージェント対応) - - `pin-actions/`, `upgrade-actions/`, `audit-actions/` + - `pin-actions/`, `upgrade-actions/`, `audit-actions/`, `harden-workflows/` - 各スキル: `SKILL.md` + `references/` - `.claude-plugin/marketplace.json` — Claude Code マーケットプレイス登録 - `scripts/validate.sh` — 構造・JSON・frontmatter・リンク・マニフェスト検証 @@ -55,7 +55,7 @@ GitHub Actions の最新バージョン・SHA 情報の取得、SHA ピン留め ## Key Patterns - SKILL.md の description は三人称("This skill should be used when...")でトリガーフレーズを豊富に -- スキル間の cross-skill ハンドオフを Notes に明記(audit → pin/upgrade) +- スキル間の cross-skill ハンドオフを Notes に明記(audit → pin/upgrade/harden, harden → audit/pin/upgrade) - MCP ツールを優先、REST API はフォールバック ## Review Guidelines diff --git a/README.ja.md b/README.ja.md index bf684af..31519ac 100644 --- a/README.ja.md +++ b/README.ja.md @@ -6,7 +6,7 @@ [![ActVer](https://img.shields.io/badge/ActVer-actver.dev-blue)](https://actver.dev) [![Buy Me a Coffee](https://img.shields.io/badge/Buy%20Me%20a%20Coffee-support-orange?logo=buy-me-a-coffee&logoColor=white)](https://buymeacoffee.com/yetanother_yk) -[ActVer](https://actver.dev) の AI コーディングエージェント向けプラグイン&スキル — GitHub Actions のバージョン取得、SHA ピン留め、ワークフローセキュリティ監査。 +[ActVer](https://actver.dev) の AI コーディングエージェント向けプラグイン&スキル — GitHub Actions のバージョン取得、SHA ピン留め、ワークフローセキュリティ監査、CI ハードニング。 **Claude Code**、**Cursor**、**Copilot** など、[skills.sh 経由で 20 以上のエージェント](https://skills.sh)に対応。 @@ -53,6 +53,7 @@ Claude Code、Cursor、Copilot など対応エージェントで利用可能。 | **pin-actions** | Actions を SHA にピン留め | 「ワークフローの Actions を SHA ピン留めして」 | | **upgrade-actions** | 最新版にアップグレード | 「GitHub Actions を更新して」 | | **audit-actions** | セキュリティ監査 | 「CI ワークフローを監査して」 | +| **harden-workflows** | ワークフロー lint CI のセットアップ | 「actionlint/ghalint/zizmor を CI に追加して」 | ## MCP ツール diff --git a/README.md b/README.md index bd95bd3..72a92f6 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ [![ActVer](https://img.shields.io/badge/ActVer-actver.dev-blue)](https://actver.dev) [![Buy Me a Coffee](https://img.shields.io/badge/Buy%20Me%20a%20Coffee-support-orange?logo=buy-me-a-coffee&logoColor=white)](https://buymeacoffee.com/yetanother_yk) -[ActVer](https://actver.dev) plugin & skills for AI coding agents — GitHub Actions version lookup, SHA pinning, and workflow security auditing. +[ActVer](https://actver.dev) plugin & skills for AI coding agents — GitHub Actions version lookup, SHA pinning, workflow security auditing, and CI hardening. Works with **Claude Code**, **Cursor**, **Copilot**, and [20+ other agents via skills.sh](https://skills.sh). @@ -53,6 +53,7 @@ No local process or API key required. | **pin-actions** | Pin actions to SHA | "Pin my workflow actions to SHA" | | **upgrade-actions** | Upgrade to latest | "Update my GitHub Actions" | | **audit-actions** | Security audit | "Audit my CI workflows" | +| **harden-workflows** | Set up workflow linting CI | "Add actionlint/ghalint/zizmor to CI" | ## MCP Tools diff --git a/plugins/actver/agents/actver.md b/plugins/actver/agents/actver.md index 28bd24b..37693e0 100644 --- a/plugins/actver/agents/actver.md +++ b/plugins/actver/agents/actver.md @@ -1,6 +1,6 @@ --- name: actver -description: Use this agent when the user asks about GitHub Actions versions, wants to pin actions to SHA, upgrade actions, or audit workflow security. This agent has access to the ActVer MCP server for real-time version lookups. +description: Use this agent when the user asks about GitHub Actions versions, wants to pin actions to SHA, upgrade actions, audit workflow security, or harden workflows with static analysis tools. This agent has access to the ActVer MCP server for real-time version lookups. --- # ActVer Agent @@ -10,11 +10,13 @@ You have access to the ActVer MCP server which provides two tools for GitHub Act ## Available Tools ### `get_action_version` + Get the latest stable version, commit SHA, and prerelease info for a GitHub Action. **Input**: Action identifier in `owner/repo` format (e.g. `actions/checkout`, `pnpm/action-setup`) **Output includes**: + - Latest stable version (e.g. `v6.3.0`) - Full commit SHA for pinning - Major tag (e.g. `v6`) @@ -23,11 +25,13 @@ Get the latest stable version, commit SHA, and prerelease info for a GitHub Acti - Release date ### `list_action_versions` + List all major versions of a GitHub Action with their latest patch and SHA. **Input**: Action identifier in `owner/repo` format **Output includes**: + - All major versions with latest patch version and SHA - Prerelease status per major version diff --git a/scripts/expected-files.txt b/scripts/expected-files.txt index c0d803d..379217d 100644 --- a/scripts/expected-files.txt +++ b/scripts/expected-files.txt @@ -1,5 +1,7 @@ skills/audit-actions/references/security-checklist.md skills/audit-actions/SKILL.md +skills/harden-workflows/references/workflow-lint-template.md +skills/harden-workflows/SKILL.md skills/pin-actions/references/sha-pinning-guide.md skills/pin-actions/SKILL.md skills/upgrade-actions/references/upgrade-patterns.md diff --git a/skills/audit-actions/SKILL.md b/skills/audit-actions/SKILL.md index 2af66f6..28ef5ab 100644 --- a/skills/audit-actions/SKILL.md +++ b/skills/audit-actions/SKILL.md @@ -55,13 +55,5 @@ General workflow security items (script injection, timeouts, concurrency) are in - This skill identifies and reports issues — it does not fix them automatically - To remediate unpinned actions, use the **pin-actions** skill - To upgrade outdated actions, use the **upgrade-actions** skill +- To set up continuous enforcement with actionlint, ghalint, and zizmor, use the **harden-workflows** skill - For the full security checklist, see [references/security-checklist.md](references/security-checklist.md) - -### Workflow-wide security tooling - -For comprehensive workflow security beyond action-specific checks, recommend adding static analysis tools to CI: -- **actionlint** — Workflow syntax validation and shellcheck integration -- **ghalint** — Security policy enforcement (permissions, timeouts) -- **zizmor** — Injection detection and excessive permissions audit - -Consider adding these tools to your CI pipeline for continuous enforcement. diff --git a/skills/audit-actions/references/security-checklist.md b/skills/audit-actions/references/security-checklist.md index 4d48226..1ffa4b7 100644 --- a/skills/audit-actions/references/security-checklist.md +++ b/skills/audit-actions/references/security-checklist.md @@ -186,7 +186,7 @@ Reference checks can be automatically detected and enforced by adding static ana | [ghalint](https://github.com/suzuki-shunsuke/ghalint) | Policy violations | `job_timeout_minutes_is_required`, `job_permissions` | | [zizmor](https://github.com/zizmorcore/zizmor) | Injection, permissions | `template-injection`, `concurrency-limits`, `excessive-permissions` | -Consider adding these tools to your CI pipeline for continuous enforcement. +Use the **harden-workflows** skill to set up these tools in CI. ## References diff --git a/skills/harden-workflows/SKILL.md b/skills/harden-workflows/SKILL.md new file mode 100644 index 0000000..f600c7d --- /dev/null +++ b/skills/harden-workflows/SKILL.md @@ -0,0 +1,42 @@ +--- +name: harden-workflows +description: This skill should be used when the user wants to add static analysis tools (actionlint, ghalint, zizmor) to their GitHub Actions CI for continuous workflow security enforcement. Common triggers include "harden workflows", "harden CI", "add workflow linting", "setup actionlint", "add zizmor", "add ghalint", "secure my GitHub Actions", "workflow security setup", "static analysis for workflows", "lint my workflows", "workflow lint CI", "add workflow security checks", "enforce workflow policies", or "set up workflow security". This skill sets up tooling in CI — it does not pin individual actions (use pin-actions) or perform one-time audits (use audit-actions). +--- + +# Harden GitHub Actions Workflows + +Set up static analysis tools (actionlint, ghalint, zizmor) in CI to automatically detect workflow security issues, policy violations, and injection vulnerabilities. + +## Scope + +This skill helps **set up tooling** for continuous workflow security enforcement. It does not perform security audits itself — use the **audit-actions** skill for manual security review. + +| Tool | Role | Detects | +|------|------|---------| +| actionlint | Syntax validation | YAML errors, type mismatches, shellcheck issues | +| ghalint | Policy enforcement | Missing timeouts, permissions, credential persistence | +| zizmor | Attack detection | Script injection, excessive permissions, missing concurrency | + +## Steps + +1. Check if `.github/workflows/` already contains a workflow-lint file (e.g. `workflow-lint.yml`) +2. If not present, create a new workflow file based on the [template](references/workflow-lint-template.md): + - Look up the latest SHA-pinned versions of `actions/checkout`, `rhysd/actionlint`, and `zizmorcore/zizmor-action` using ActVer (prefer `get_action_version` MCP tool) + - Look up the latest ghalint release version from GitHub (`gh release view --repo suzuki-shunsuke/ghalint --json tagName`) + - Generate the workflow with all actions SHA-pinned and ghalint version-pinned +3. After the workflow runs for the first time, create a `zizmor.yml` config file if zizmor reports `secrets-outside-env` or `excessive-permissions` findings that are intentional false positives: + - Add ignores for workflows that pass secrets to trusted actions (e.g. claude-code-action, deploy actions) +4. Apply workflow security best practices to existing workflows where missing (confirm with the user before modifying workflows beyond the lint file): + - `permissions: {}` at workflow level (deny by default) + job-level permissions + - `persist-credentials: false` on all `actions/checkout` + - `timeout-minutes` on all jobs + - `concurrency` groups where appropriate +5. Verify ghalint binary with `gh attestation verify` for supply-chain security (already included in the generated workflow template — no separate action needed) + +## Notes + +- This skill sets up tooling — it does not replicate what the tools check. The tools themselves detect and report issues. +- For auditing action-specific security (checking pin status, checkout config, secrets exposure), use the **audit-actions** skill +- To apply SHA pins to actions, use the **pin-actions** skill +- For upgrading action versions, use the **upgrade-actions** skill +- For the workflow template and configuration examples, see [references/workflow-lint-template.md](references/workflow-lint-template.md) diff --git a/skills/harden-workflows/references/workflow-lint-template.md b/skills/harden-workflows/references/workflow-lint-template.md new file mode 100644 index 0000000..0a1c3ed --- /dev/null +++ b/skills/harden-workflows/references/workflow-lint-template.md @@ -0,0 +1,152 @@ +# Workflow Lint Template + +## Workflow File + +Create `.github/workflows/workflow-lint.yml`: + +```yaml +name: Workflow Lint + +on: + push: + branches: [main] + paths: + - ".github/workflows/**" + - ".ghalint.yml" + - "zizmor.yml" + pull_request: + branches: [main] + paths: + - ".github/workflows/**" + - ".ghalint.yml" + - "zizmor.yml" + +permissions: {} # deny by default — each job declares its own + +concurrency: + group: workflow-lint-${{ github.ref }} + cancel-in-progress: true + +jobs: + actionlint: + name: actionlint + runs-on: ubuntu-latest + timeout-minutes: 10 + permissions: + contents: read # Read workflow files for linting + steps: + - uses: actions/checkout@SHA # vX.Y.Z — look up with ActVer + with: + persist-credentials: false + + - uses: rhysd/actionlint@SHA # vX.Y.Z — look up with ActVer + + ghalint: + name: ghalint + runs-on: ubuntu-latest + timeout-minutes: 10 + permissions: + contents: read # Download release artifact from GitHub + attestations: read # Verify SLSA build provenance via gh attestation verify + steps: + - uses: actions/checkout@SHA # vX.Y.Z + with: + persist-credentials: false + + - name: Install ghalint + env: + GHALINT_VERSION: "X.Y.Z" # look up latest from GitHub releases + GH_TOKEN: ${{ github.token }} + run: | + # Note: assumes x86_64 runners. For ARM runners, change linux_amd64 to linux_arm64 + gh release download "v${GHALINT_VERSION}" \ + -R suzuki-shunsuke/ghalint \ + -p "ghalint_${GHALINT_VERSION}_linux_amd64.tar.gz" + gh attestation verify "ghalint_${GHALINT_VERSION}_linux_amd64.tar.gz" \ + -R suzuki-shunsuke/ghalint \ + --signer-workflow suzuki-shunsuke/go-release-workflow/.github/workflows/release.yaml + tar xzf "ghalint_${GHALINT_VERSION}_linux_amd64.tar.gz" -C /usr/local/bin ghalint + + - name: Run ghalint + run: ghalint run + + zizmor: + name: zizmor + runs-on: ubuntu-latest + timeout-minutes: 10 + permissions: + contents: read # Read workflow files for auditing + steps: + - uses: actions/checkout@SHA # vX.Y.Z + with: + persist-credentials: false + + - uses: zizmorcore/zizmor-action@SHA # vX.Y.Z — look up with ActVer + with: + persona: auditor # balances signal-to-noise; use 'pedantic' for maximum coverage, 'regular' for minimal + advanced-security: false # set true only if GitHub Advanced Security is enabled on the repo +``` + +**Important**: Replace all `@SHA # vX.Y.Z` placeholders with actual SHA-pinned versions. Use the ActVer `get_action_version` tool to look up the latest versions. + +## Tool Roles + +| Tool | Focus | Key Rules | +|------|-------|-----------| +| **actionlint** | Syntax & types | shellcheck integration, expression type checking, runner label validation | +| **ghalint** | Security policy | `job_timeout_minutes_is_required`, `job_permissions`, `checkout_persist_credentials_should_be_false` | +| **zizmor** | Attack patterns | `template-injection`, `concurrency-limits`, `excessive-permissions`, `secrets-outside-env` | + +The three tools complement each other — actionlint catches syntax issues, ghalint enforces organizational policies, and zizmor detects security vulnerabilities. + +## Configuration Files + +### zizmor.yml (optional) + +Create `zizmor.yml` at the repository root to suppress expected findings: + +```yaml +# Suppress findings for workflows that intentionally use secrets +# outside GitHub Environments (e.g. trusted first-party actions) +rules: + secrets-outside-env: + ignore: + - workflow-name.yml # only if the workflow passes secrets to trusted actions + excessive-permissions: + ignore: + - workflow-name.yml # only if write permissions are required (e.g. posting PR comments) +``` + +Only add ignores for workflows where the finding is intentional and understood. Do not blanket-ignore rules. + +### .ghalint.yml (optional) + +Create `.ghalint.yml` at the repository root to exclude specific policies: + +```yaml +excludes: + - policy_name: job_timeout_minutes_is_required + workflow_file_path: .github/workflows/special-case.yml + job_name: long-running-job +``` + +## ghalint Binary Verification + +ghalint does not provide a GitHub Action. The template uses `gh attestation verify` for SLSA provenance verification: + +1. `gh release download` — Download the binary from GitHub Releases +2. `gh attestation verify` — Verify the binary was built by the official release workflow +3. `--signer-workflow` — Restrict to the specific build workflow for maximum security + +This is more secure than checksums because it verifies the **build provenance** (who built it, from which repo, using which workflow), not just the file hash. + +## Workflow Best Practices Applied + +The template incorporates these security best practices: + +- **`permissions: {}`** — Deny by default at workflow level; each job declares its own minimal permissions +- **`persist-credentials: false`** — Prevent token persistence in git config +- **`timeout-minutes`** — Prevent runaway jobs +- **`concurrency` + `cancel-in-progress`** — Cancel outdated runs on the same branch +- **`paths` filter** — Only trigger when workflow files or lint configs change +- **SHA-pinned actions** — All actions pinned to full commit SHAs diff --git a/skills/pin-actions/SKILL.md b/skills/pin-actions/SKILL.md index 22820c9..333e605 100644 --- a/skills/pin-actions/SKILL.md +++ b/skills/pin-actions/SKILL.md @@ -1,6 +1,6 @@ --- name: pin-actions -description: This skill should be used when the user asks to pin GitHub Actions to commit SHAs, secure workflows against supply-chain attacks, replace action tags with SHAs, harden GitHub Actions, fix Scorecard pinned-dependencies findings, or lock action versions. Triggers on phrases like "pin actions", "SHA pin", "secure workflows", "harden workflows", "lock action versions", "replace tags with SHAs". +description: This skill should be used when the user asks to pin GitHub Actions to commit SHAs, secure workflows against supply-chain attacks, replace action tags with SHAs, harden action references, fix Scorecard pinned-dependencies findings, or lock action versions. Triggers on phrases like "pin actions", "SHA pin", "secure action references", "lock action versions", "replace tags with SHAs". --- # Pin GitHub Actions to SHA @@ -36,4 +36,6 @@ Pin all GitHub Actions in workflow files to full commit SHAs for supply-chain se - Always preserve the version as a `# vX.Y.Z` comment after the SHA - Skip local actions (`uses: ./.github/actions/...` or `uses: ./`) — these are in the user's own repo - Skip Docker-based actions (`docker://`) — use image digests instead +- To audit workflow security and verify pinning coverage, use the **audit-actions** skill +- To enforce pinning automatically in CI, use the **harden-workflows** skill - For details, see [references/sha-pinning-guide.md](references/sha-pinning-guide.md)