Skip to content

Commit d3ad801

Browse files
louibbitgobot
authored andcommitted
feat(lint-gha): add zizmor lint workflow for public repositories
Add the ruleset-required zizmor workflow that enforces the public-repository action-pinning policy: it checks out the repository a targeted pull request was opened against and runs zizmor with the policy inlined in the workflow, mirroring the org-wide lint workflow. The standalone .github/zizmor.yml is removed now that the policy lives in the workflow. Ticket: INF-3420 Session-Id: 217d73a9-ac3c-466a-9cd9-112324f86e76 Task-Id: bfb9a42e-a4b1-49e6-a6e5-6f8d9d3d3051
1 parent 6286e12 commit d3ad801

2 files changed

Lines changed: 205 additions & 136 deletions

File tree

.github/workflows/lint-gha.yaml

Lines changed: 205 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,205 @@
1+
name: Lint GitHub Actions Files
2+
3+
# This workflow is required to pass org-wide for public repositories
4+
# via a GitHub organization ruleset "required_workflows" rule. GitHub
5+
# runs it against pull requests opened in the repositories the ruleset
6+
# targets, checking out and scanning THAT repository's workflows, not
7+
# BitGoJS's own.
8+
#
9+
# Required workflows only support these events; see
10+
# https://docs.github.com/en/enterprise-cloud@latest/repositories/configuring-branches-and-merges-in-your-repository/managing-rulesets/available-rules-for-rulesets#require-workflows-to-pass-before-merging
11+
on:
12+
pull_request:
13+
merge_group:
14+
15+
permissions:
16+
contents: read
17+
18+
jobs:
19+
zizmor:
20+
name: Run Zizmor
21+
runs-on: ${{ vars.BUILD_SYSTEM_MEDIUM_RUNNER || 'ubuntu-latest' }}
22+
timeout-minutes: 10
23+
permissions:
24+
contents: read
25+
steps:
26+
# Checks out the CALLING repo (the one the PR was opened against),
27+
# not BitGoJS -- this is standard ruleset-required-workflow
28+
# behavior: github.repository/actions/checkout resolve to the
29+
# target repo's PR head, exactly as if this workflow were defined
30+
# directly in that repo.
31+
- name: Checkout target repository
32+
uses: actions/checkout@v7
33+
34+
# zizmor's default config discovery only looks in the repo it's
35+
# scanning (the one just checked out above), and the target
36+
# repo's own policy, if any, is not ours. The policy is therefore
37+
# inlined here and written to a file that --config points at.
38+
#
39+
# Policy:
40+
# - GitHub-owned (actions/*, github/*) and the docker/* and
41+
# aws-actions/* orgs are exempt from hash-pinning --
42+
# ref-pinning (a tag or branch) is enough; hash-pinning them
43+
# adds SHA-churn maintenance with no security benefit.
44+
# - The grandfathered lists came from a 2026-09-03 scan of
45+
# every non-archived public repository in the BitGo org for
46+
# uses: references not pinned to a full-length commit SHA
47+
# (INF-3420). Both lists are shrink-only: remove an entry
48+
# once every public-repository workflow that references it
49+
# pins it to a commit SHA -- do not add new entries.
50+
# - Everything else defaults to hash-pin ("*": hash-pin), so
51+
# new third-party actions must be pinned to a commit SHA
52+
# from day one.
53+
- name: Write zizmor policy
54+
env:
55+
ENABLE_ALL_GHA_LINT_CHECKS: ${{ vars.ENABLE_ALL_GHA_LINT_CHECKS }}
56+
run: |
57+
policy="${GITHUB_WORKSPACE}/.zizmor-ci-policy.yml"
58+
if [ "$ENABLE_ALL_GHA_LINT_CHECKS" = 'true' ]; then
59+
disabled_dest=/dev/null
60+
else
61+
disabled_dest="$policy"
62+
fi
63+
echo "rules:" > "$policy"
64+
cat >> "$disabled_dest" <<'DISABLED'
65+
adhoc-packages:
66+
disable: true
67+
anonymous-definition:
68+
disable: true
69+
archived-uses:
70+
disable: true
71+
artipacked:
72+
disable: true
73+
bot-conditions:
74+
disable: true
75+
cache-poisoning:
76+
disable: true
77+
concurrency-limits:
78+
disable: true
79+
dangerous-triggers:
80+
disable: true
81+
dependabot-cooldown:
82+
disable: true
83+
dependabot-execution:
84+
disable: true
85+
excessive-permissions:
86+
disable: true
87+
forbidden-uses:
88+
disable: true
89+
github-app:
90+
disable: true
91+
github-env:
92+
disable: true
93+
hardcoded-container-credentials:
94+
disable: true
95+
impostor-commit:
96+
disable: true
97+
insecure-commands:
98+
disable: true
99+
insecure-url-scheme:
100+
disable: true
101+
known-vulnerable-actions:
102+
disable: true
103+
misfeature:
104+
disable: true
105+
obfuscation:
106+
disable: true
107+
overprovisioned-secrets:
108+
disable: true
109+
ref-confusion:
110+
disable: true
111+
ref-version-mismatch:
112+
disable: true
113+
secrets-inherit:
114+
disable: true
115+
secrets-outside-env:
116+
disable: true
117+
self-hosted-runner:
118+
disable: true
119+
self-repository:
120+
disable: true
121+
stale-action-refs:
122+
disable: true
123+
superfluous-actions:
124+
disable: true
125+
template-injection:
126+
disable: true
127+
typosquat-uses:
128+
disable: true
129+
undocumented-permissions:
130+
disable: true
131+
unpinned-images:
132+
disable: true
133+
unpinned-tools:
134+
disable: true
135+
unredacted-secrets:
136+
disable: true
137+
unsound-condition:
138+
disable: true
139+
unsound-contains:
140+
disable: true
141+
unsound-ternary:
142+
disable: true
143+
use-trusted-publishing:
144+
disable: true
145+
DISABLED
146+
cat >> "$policy" <<'PINNING'
147+
unpinned-uses:
148+
config:
149+
policies:
150+
# Trusted orgs -- ref-pinning (a tag or branch) is
151+
# enough. Mirrors the org-level policy: GitHub-owned
152+
# (actions/*, github/*) and the docker/* and
153+
# aws-actions/* orgs.
154+
"actions/*": ref-pin
155+
"github/*": ref-pin
156+
"docker/*": ref-pin
157+
"aws-actions/*": ref-pin
158+
159+
# Grandfathered internal (BitGo-owned) actions and
160+
# reusable workflows still referenced by a floating
161+
# tag/branch by at least one public repository as of
162+
# the INF-3420 scan.
163+
"BitGo/gha-renovate-bot/*": ref-pin
164+
"BitGo/install-github-release-binary/*": ref-pin
165+
"BitGo/semantic-release-github-actions/*": ref-pin
166+
167+
# Grandfathered external third-party actions still
168+
# referenced by a floating tag/branch by at least one
169+
# public repository as of the INF-3420 scan.
170+
"actions-rs/toolchain": ref-pin
171+
"azure/setup-helm": ref-pin
172+
"codecov/codecov-action": ref-pin
173+
"dtolnay/rust-toolchain": ref-pin
174+
"helm/chart-releaser-action": ref-pin
175+
"ilammy/msvc-dev-cmd": ref-pin
176+
"ludeeus/action-shellcheck": ref-pin
177+
"peter-evans/create-pull-request": ref-pin
178+
"xresloader/upload-to-github-release": ref-pin
179+
180+
# Everything else: every other action (including new
181+
# third-party actions, subpaths of grandfathered
182+
# third-party repos, and internal actions in repos
183+
# not listed above) must be pinned to a full commit
184+
# SHA.
185+
"*": hash-pin
186+
PINNING
187+
188+
- name: Run zizmor
189+
uses: zizmorcore/zizmor-action@70fb788f84895a7701f5643d103d587e460b5c99 # v0.6.3
190+
with:
191+
config: .zizmor-ci-policy.yml
192+
# Online audits (e.g. ref-confusion) call the GitHub API to
193+
# inspect OTHER repos referenced by uses: clauses. The default
194+
# github.token is only scoped to the checked-out repo, so
195+
# those lookups fail fatally for any repo the token cannot
196+
# read. unpinned-uses (the only audit this policy relies on)
197+
# is fully offline-capable.
198+
online-audits: "false"
199+
# Advanced Security (SARIF + code scanning upload) needs a
200+
# paid feature target repos may not have; use plain
201+
# annotations so this works uniformly across every repository
202+
# the ruleset targets.
203+
advanced-security: "false"
204+
annotations: "true"
205+
fail-on-no-inputs: "false"

.github/zizmor.yml

Lines changed: 0 additions & 136 deletions
This file was deleted.

0 commit comments

Comments
 (0)