|
| 1 | +--- |
| 2 | +name: fleet-auditing-gha |
| 3 | +description: Audits a repo's GitHub Actions permissions + allowlist against the fleet baseline. Reports drift only. Fixes are manual in Settings → Actions because flipping these silently is unsafe. Use when a CI failure looks like "action X is not allowed to be used", when onboarding a new fleet repo, or as a periodic fleet-wide health check. |
| 4 | +user-invocable: true |
| 5 | +allowed-tools: Read, Grep, Glob, Bash(gh:*), Bash(node:*), Bash(jq:*) |
| 6 | +model: claude-haiku-4-5 |
| 7 | +context: fork |
| 8 | +--- |
| 9 | + |
| 10 | +# auditing-gha |
| 11 | + |
| 12 | +Diff a fleet repo's GitHub Actions repository-level settings against the canonical baseline. Read-only: surfaces what to change, doesn't change it. |
| 13 | + |
| 14 | +## When to use |
| 15 | + |
| 16 | +- **"action X is not allowed to be used" CI failure**: the allowlist is missing an entry, or the policy got flipped from `selected` to `local_only`. |
| 17 | +- **Onboarding a new fleet repo**: before the first CI run, confirm the new repo matches the baseline so the first push doesn't hit policy errors. |
| 18 | +- **Periodic fleet health check**: drift accumulates. Somebody adds a workflow that needs a new action and silently flips `verified_allowed: true` to make it work instead of adding the explicit pattern. |
| 19 | + |
| 20 | +## What the baseline checks |
| 21 | + |
| 22 | +| Setting (per repo) | Baseline | Why | |
| 23 | +| ---------------------------------- | -------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | |
| 24 | +| `enabled` | `true` | Per-repo override is on. **Note**: `enabled: false` does NOT mean Actions are off — it means the per-repo override is unset and org policy is the source of truth. To get drift-detection on a repo, opt in to per-repo settings + mirror the canonical baseline. | |
| 25 | +| `allowed_actions` | `'selected'` | "Allow enterprise, and select non-enterprise, actions and reusable workflows" — the only mode where the explicit allowlist is the source of truth. | |
| 26 | +| `github_owned_allowed` | `false` | Don't blanket-allow `actions/*`. The canonical patterns list already names every github-owned action we need; unlisted ones must be explicit. | |
| 27 | +| `verified_allowed` | `false` | Marketplace "verified creator" is not implicit allow — every action must be on the canonical patterns list. | |
| 28 | +| `patterns_allowed ⊇ canonical set` | Each fleet pattern present | Each canonical entry is referenced by at least one socket-registry shared workflow; missing one breaks every consumer. | |
| 29 | + |
| 30 | +The **canonical patterns** (every fleet repo must have all of these): |
| 31 | + |
| 32 | +- `actions/cache/restore@*` |
| 33 | +- `actions/cache/save@*` |
| 34 | +- `actions/cache@*` |
| 35 | +- `actions/checkout@*` |
| 36 | +- `actions/deploy-pages@*` |
| 37 | +- `actions/download-artifact@*` |
| 38 | +- `actions/github-script@*` |
| 39 | +- `actions/setup-go@*` |
| 40 | +- `actions/setup-node@*` |
| 41 | +- `actions/setup-python@*` |
| 42 | +- `actions/upload-artifact@*` |
| 43 | +- `actions/upload-pages-artifact@*` |
| 44 | +- `depot/build-push-action@*` |
| 45 | +- `depot/setup-action@*` |
| 46 | +- `github/codeql-action/upload-sarif@*` |
| 47 | + |
| 48 | +Extras beyond the canonical set are tolerated (reported as info, not failure). A repo may pin a one-off action, but each extra should map to a real consumer; orphans should be pruned. |
| 49 | + |
| 50 | +**Third-party actions are NOT on the allowlist.** Anything outside `actions/`, `github/`, and `depot/` should be ported to a hand-rolled composite under `SocketDev/socket-registry/.github/actions/` rather than added here. The current set of socket-registry composite replacements: |
| 51 | + |
| 52 | +| Third-party | socket-registry composite | |
| 53 | +| --------------------------------- | -------------------------- | |
| 54 | +| `dtolnay/rust-toolchain` | `setup-rust-toolchain` | |
| 55 | +| `hendrikmuhs/ccache-action` | `setup-ccache` | |
| 56 | +| `HaaLeo/publish-vscode-extension` | `publish-vscode-extension` | |
| 57 | +| `mlugg/setup-zig` | `setup-zig` | |
| 58 | +| `pnpm/action-setup` | `setup-pnpm` | |
| 59 | +| `softprops/action-gh-release` | `create-gh-release` | |
| 60 | +| `Swatinem/rust-cache` | `setup-rust-cache` | |
| 61 | + |
| 62 | +Note: `enabled: false` from the per-repo API does NOT mean Actions are disabled. It means the per-repo override is unset and org-level policy is in effect. The skill explains this in its output. |
| 63 | + |
| 64 | +## How to invoke |
| 65 | + |
| 66 | + node .claude/skills/fleet/auditing-gha/run.mts SocketDev/socket-btm SocketDev/socket-cli |
| 67 | + |
| 68 | +Or all-at-once with the canonical fleet list (manual today; the orchestrator skill prompt expands the list at call time): |
| 69 | + |
| 70 | + node .claude/skills/fleet/auditing-gha/run.mts \ |
| 71 | + SocketDev/socket-btm \ |
| 72 | + SocketDev/socket-cli \ |
| 73 | + SocketDev/socket-lib \ |
| 74 | + SocketDev/socket-mcp \ |
| 75 | + SocketDev/socket-packageurl-js \ |
| 76 | + SocketDev/socket-registry \ |
| 77 | + SocketDev/socket-sdk-js \ |
| 78 | + SocketDev/socket-sdxgen \ |
| 79 | + SocketDev/socket-stuie \ |
| 80 | + SocketDev/socket-vscode \ |
| 81 | + SocketDev/socket-webext \ |
| 82 | + SocketDev/socket-wheelhouse \ |
| 83 | + SocketDev/ultrathink |
| 84 | + |
| 85 | +For machine-readable output (one finding per repo): |
| 86 | + |
| 87 | + node .claude/skills/fleet/auditing-gha/run.mts --json SocketDev/socket-btm | jq |
| 88 | + |
| 89 | +## How to fix the findings |
| 90 | + |
| 91 | +Each finding line names the exact toggle to flip. The fix is **manual**: the runner does not write. Flipping these silently is a credible attack vector and should always be a human action. |
| 92 | + |
| 93 | +Two paths: |
| 94 | + |
| 95 | +1. **Web UI (preferred)**: Repo → Settings → Actions → General. The settings map 1:1 with the audit findings: |
| 96 | + - "Allow enterprise, and select non-enterprise, actions and reusable workflows" → flips `allowed_actions` to `selected`. |
| 97 | + - Uncheck "Allow actions created by GitHub" → `github_owned_allowed: false`. |
| 98 | + - Uncheck "Allow Marketplace actions by verified creators" → `verified_allowed: false`. |
| 99 | + - "Allow specified actions and reusable workflows" textarea: paste the canonical patterns list (one per line). Existing extras can stay; remove only ones with no consumer. |
| 100 | + |
| 101 | +2. **`gh api` PUT (admin-scoped tokens only)**: surfaced for completeness; prefer the UI: |
| 102 | + |
| 103 | + gh api -X PUT repos/<owner>/<repo>/actions/permissions \ |
| 104 | + -F enabled=true -F allowed_actions=selected |
| 105 | + gh api -X PUT repos/<owner>/<repo>/actions/permissions/selected-actions \ |
| 106 | + -F github_owned_allowed=false -F verified_allowed=false \ |
| 107 | + -f patterns_allowed[]='actions/cache/restore@*' \ |
| 108 | + -f patterns_allowed[]='actions/cache/save@*' \ |
| 109 | + # ...one -f per canonical pattern... |
| 110 | + |
| 111 | + The whole-list replace semantics on the selected-actions endpoint mean **omitting a repo's existing extras drops them**. Preserve them when relevant. |
| 112 | + |
| 113 | +## Anti-patterns |
| 114 | + |
| 115 | +- **Auto-PUT-ing the baseline from a script.** Don't. The settings affect every workflow on the repo and a wrong setting silently weakens supply-chain posture. The user runs the audit, the user fixes. |
| 116 | +- **Adding an action to the allowlist to make a one-off workflow happy.** First ask: should the workflow use a shared socket-registry workflow that already references an approved action? Adding entries to the canonical set means cascading them to every consumer org. A real commitment. |
| 117 | +- **Treating the audit as a security review.** It checks policy state, not workflow content. A workflow that uses an allowed action insecurely (e.g. `pull_request_target` + `actions/checkout` of untrusted ref) is invisible to this audit; that's `pull-request-target-guard`'s job. |
| 118 | + |
| 119 | +## Companion: `greening-ci` |
| 120 | + |
| 121 | +If a CI failure shows `action <X> is not allowed by enterprise admin` or `not allowed to be used in this repository`, that's an allowlist gap. Run this audit, fix the gap manually, then re-run `/green-ci` to confirm the build goes green. |
0 commit comments