From 3dbeb6441b5566591bc546dfea7698e0a6f9c555 Mon Sep 17 00:00:00 2001 From: zenexer Date: Sat, 23 May 2026 08:49:30 +0000 Subject: [PATCH 1/2] ci: migrate scan-plugins.yml to Workload Identity Federation auth MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replaces the static ANTHROPIC_API_KEY repo secret with Workload Identity Federation: the scan-plugins shared action mints a GitHub OIDC token (id-token: write) and the claude CLI exchanges it for a short-lived bearer. The federation rule is bound to this repository (repository_id-pinned). Depends on anthropics/claude-plugins-community#34 (adds the WIF inputs to the shared action). Pinned to that PR's head SHA; will re-pin to a main-branch SHA once #34 merges. Drops the 'Require ANTHROPIC_API_KEY' fail-closed guard — the WIF inputs are literal in this file, so the action's skip-if-no-auth path can't trigger. Updates the prompt-injection security comment to reflect the short-lived bearer model. --- .github/workflows/scan-plugins.yml | 43 ++++++++++++++++-------------- 1 file changed, 23 insertions(+), 20 deletions(-) diff --git a/.github/workflows/scan-plugins.yml b/.github/workflows/scan-plugins.yml index f54764a4..436d253a 100644 --- a/.github/workflows/scan-plugins.yml +++ b/.github/workflows/scan-plugins.yml @@ -32,6 +32,7 @@ on: permissions: contents: read + id-token: write # Anthropic Workload Identity Federation (scan-plugins action) # Serialize scans per ref so concurrent runs (a re-dispatch racing the # original, or a manual dispatch) don't both restore the same cache, scan @@ -76,18 +77,11 @@ jobs: echo "relevant=true" >> "$GITHUB_OUTPUT" fi - # The shared action no-ops gracefully when ANTHROPIC_API_KEY is unset - # (sensible default for community repos). Here `scan` is a required - # check, so a silent no-op would make it a rubber stamp — fail closed. - - name: Require ANTHROPIC_API_KEY when a scan is needed - if: steps.changes.outputs.relevant == 'true' - env: - API_KEY_SET: ${{ secrets.ANTHROPIC_API_KEY != '' }} - run: | - if [[ "$API_KEY_SET" != "true" ]]; then - echo "::error::ANTHROPIC_API_KEY is not configured; refusing to skip a required policy scan." - exit 1 - fi + # Auth: the shared scan-plugins action below uses Workload Identity + # Federation (anthropic-federation-rule-id input) — the IDs are literal + # in this file, so the action's "skip if no auth" path can't trigger. + # The previous "Require ANTHROPIC_API_KEY" fail-closed guard is + # therefore no longer needed. # Verdict cache, keyed on the policy content hash. A prompt change # invalidates every cached verdict — that is intentional. The save key @@ -200,9 +194,17 @@ jobs: # The verdict (cached + fresh) is what gates the job, not the action's # exit code, and the revert workflow needs the artifact even on failure. continue-on-error: true - uses: anthropics/claude-plugins-community/.github/actions/scan-plugins@b277757588871fe55b2620de8c6dfda470e2e9d8 + # Pinned to claude-plugins-community#34 (WIF input support). + # TODO: re-pin to a main-branch SHA once #34 merges. + uses: anthropics/claude-plugins-community/.github/actions/scan-plugins@e8411e847ec6b0bcb7c68f853f13d4d653f68862 with: - anthropic-api-key: ${{ secrets.ANTHROPIC_API_KEY }} + # Anthropic auth via Workload Identity Federation — the action + # mints a GitHub OIDC token (id-token: write above) and the claude + # CLI exchanges it for a short-lived bearer. The federation rule is + # bound to this repository (repository_id-pinned). + anthropic-federation-rule-id: fdrl_01AnM1ihR2h7PCjXfDqfedpq + anthropic-organization-id: 1ec12c5c-6542-4da8-bf2f-c15919aef01c + anthropic-service-account-id: svac_01UaBRpFouHrgVdfvAM7Bt39 marketplace-path: .scan-cache/scan-targets.json policy-prompt: .github/policy/prompt.md fail-on-findings: "true" @@ -241,12 +243,13 @@ jobs: fi # Defense in depth: the scan action runs Claude with Read access over - # a cloned external repo and ANTHROPIC_API_KEY in its process env. A - # successful prompt injection could coerce the model to put key - # material into `summary`/`violations`. The action's own step summary - # already carries that risk; this workflow adds an artifact and a PR - # comment, both public sinks. Scrub any key-shaped token here so it - # never reaches the cache, artifact, or comment. + # a cloned external repo. With WIF auth the process env carries a + # short-lived OIDC JWT (masked) and the CLI's exchanged bearer + # rather than a long-lived sk-ant- key, which bounds the blast + # radius of a prompt-injection exfil to a token that expires in + # minutes. The sk-ant- scrubber stays as defense-in-depth (covers + # any future static-key fallback) so key-shaped strings still never + # reach the cache, artifact, or PR comment. jq -c '(.. | strings) |= gsub("sk-ant-[A-Za-z0-9_-]{8,}"; "[REDACTED]")' \ "$CACHE_DIR/scanned-raw.json" > "$CACHE_DIR/scanned-raw.json.tmp" mv "$CACHE_DIR/scanned-raw.json.tmp" "$CACHE_DIR/scanned-raw.json" From c9c5309aef3dac6e6c894fd59e4b637027f28f35 Mon Sep 17 00:00:00 2001 From: zenexer Date: Sun, 24 May 2026 20:55:40 +0000 Subject: [PATCH 2/2] scan-plugins: re-pin to cpc#34 merge commit on main MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit claude-plugins-community#34 merged at e85f0d65b4fc87f07862e1dcdc467950514414ec — re-pinning from the PR head SHA to the squash-merge commit on main so the pin survives any future branch GC. --- .github/workflows/scan-plugins.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/scan-plugins.yml b/.github/workflows/scan-plugins.yml index 436d253a..60cbef18 100644 --- a/.github/workflows/scan-plugins.yml +++ b/.github/workflows/scan-plugins.yml @@ -196,7 +196,7 @@ jobs: continue-on-error: true # Pinned to claude-plugins-community#34 (WIF input support). # TODO: re-pin to a main-branch SHA once #34 merges. - uses: anthropics/claude-plugins-community/.github/actions/scan-plugins@e8411e847ec6b0bcb7c68f853f13d4d653f68862 + uses: anthropics/claude-plugins-community/.github/actions/scan-plugins@e85f0d65b4fc87f07862e1dcdc467950514414ec with: # Anthropic auth via Workload Identity Federation — the action # mints a GitHub OIDC token (id-token: write above) and the claude