Skip to content

Commit 9bf19a4

Browse files
authored
fix(sec-160): pass org-wide app token to zizmor for action ref resolution (#4)
1 parent 86ce285 commit 9bf19a4

2 files changed

Lines changed: 71 additions & 1 deletion

File tree

.github/workflows/zizmor.yml

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,53 @@ jobs:
1818
with:
1919
egress-policy: audit
2020

21-
- name: Checkout
21+
- name: Checkout target repository
2222
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
2323
with:
2424
persist-credentials: false
2525

26+
# Intentionally fails loudly when the org-level variable/secret is
27+
# missing (e.g. fork PRs, where GitHub withholds secrets from workflows
28+
# triggered from forks). A red check on the required workflow is the
29+
# desired signal: it forces a human to either mark the PR trusted or
30+
# investigate why the scanner credentials are unavailable. Do NOT add
31+
# an `if:` guard here to silently skip — loud failure is the contract.
32+
- name: Mint scanner token (org-wide read access for action ref resolution)
33+
id: app-token
34+
uses: actions/create-github-app-token@f8d387b68d61c58ab83c6c016672934102569859 # v3.0.0
35+
with:
36+
app-id: ${{ vars.ZIZMOR_SCANNER_APP_ID }}
37+
private-key: ${{ secrets.ZIZMOR_SCANNER_PRIVATE_KEY }}
38+
owner: rudderlabs
39+
permission-contents: read
40+
permission-metadata: read
41+
42+
# Inject the shared zizmor config from this repo into the target repo's
43+
# run context. Required because zizmor only auto-discovers config from
44+
# the checked-out working tree, and injected runs check out the target
45+
# repo's tree, not shared-workflows. Without this step, any config-level
46+
# rule overrides we ship here (e.g. the `secrets-outside-env` ignore for
47+
# the zizmor workflow itself) would never apply to injected runs.
48+
- name: Checkout shared zizmor config
49+
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
50+
with:
51+
repository: rudderlabs/shared-workflows
52+
# For self-scans (PRs against shared-workflows itself), test the
53+
# PR's proposed config — otherwise a PR that breaks .github/zizmor.yml
54+
# would be validated against main's config and merge green. For
55+
# injected runs in other repos, pin to main for stability.
56+
ref: ${{ github.repository == 'rudderlabs/shared-workflows' && github.event.pull_request.head.sha || 'main' }}
57+
token: ${{ steps.app-token.outputs.token }}
58+
path: .zizmor-shared
59+
persist-credentials: false
60+
sparse-checkout: |
61+
.github/zizmor.yml
62+
sparse-checkout-cone-mode: false
63+
2664
- name: Run zizmor
2765
uses: zizmorcore/zizmor-action@71321a20a9ded102f6e9ce5718a2fcec2c4f70d8 # v0.5.2
2866
with:
2967
advanced-security: true
3068
min-severity: medium
69+
config: .zizmor-shared/.github/zizmor.yml
70+
token: ${{ steps.app-token.outputs.token }}

.github/zizmor.yml

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# zizmor configuration for shared-workflows
2+
# https://docs.zizmor.sh/configuration/
3+
4+
rules:
5+
# Suppress secrets-outside-env for the zizmor workflow itself.
6+
#
7+
# The audit is a real Severity::Medium, Confidence::High finding in zizmor
8+
# v1.23.1 — it correctly notes that this job references a secret without a
9+
# named GitHub Environment guarding execution. The standard mitigation is to
10+
# bind the job to an `environment:` with required reviewers, but this
11+
# workflow is injected by the org required-workflow ruleset into every
12+
# rudderlabs repo and runs in the *target* repo's context. An
13+
# `environment:` directive here would only resolve in repos that happen to
14+
# define a matching environment, which none of them do, so the standard fix
15+
# cannot apply.
16+
#
17+
# The residual risk is bounded by the App registration, not by this file:
18+
# the secret is the private key of the dedicated `ZIZMOR_SCANNER` GitHub
19+
# App, which is registered with `Repository: Contents: Read, Metadata: Read`
20+
# only — no write access to anything, anywhere. Worst-case exfiltration is
21+
# ~1 hour of read-only access to public + internal repository source code,
22+
# which is the same access surface every employee already has via their
23+
# personal GitHub account. The blast radius does not justify gating PRs on
24+
# this finding.
25+
secrets-outside-env:
26+
ignore:
27+
# NOTE: zizmor matches `ignore` rules on the file's basename, not its
28+
# full path (see WorkflowRule matching in zizmor v1.23.1
29+
# crates/zizmor/src/config/mod.rs:639). Bare basename is required.
30+
- zizmor.yml

0 commit comments

Comments
 (0)