Skip to content

Commit 4179d3e

Browse files
sserrataclaude
andcommitted
ci: harden GitHub Actions workflows
Port the pan.dev post-incident hardening checklist: - persist-credentials: false on all checkouts - pass user-controlled context via env vars, not shell interpolation - constrain artifact unzip to demo/build/* - post-build tamper diff on deploy-affecting config - environment: preview/production on deploy jobs - restore-only, SHA-pinned screenshot cache on PR path; trusted writer on main - concurrency group on live deploy - add CODEOWNERS for build-critical paths - remove obsolete canary-beta-release workflow Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 516bd48 commit 4179d3e

6 files changed

Lines changed: 89 additions & 51 deletions

File tree

.github/CODEOWNERS

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# Build-critical paths require maintainer review
2+
/.github/ @PaloAltoNetworks/docusaurus-openapi-maintainers
3+
/scripts/ @PaloAltoNetworks/docusaurus-openapi-maintainers
4+
/packages/ @PaloAltoNetworks/docusaurus-openapi-maintainers
5+
/package.json @PaloAltoNetworks/docusaurus-openapi-maintainers
6+
/yarn.lock @PaloAltoNetworks/docusaurus-openapi-maintainers
7+
/demo/docusaurus.config.ts @PaloAltoNetworks/docusaurus-openapi-maintainers
8+
/firebase.json @PaloAltoNetworks/docusaurus-openapi-maintainers
9+
/.firebaserc @PaloAltoNetworks/docusaurus-openapi-maintainers
10+
/.github/CODEOWNERS @PaloAltoNetworks/docusaurus-openapi-maintainers

.github/workflows/build-perf.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ jobs:
1818
pull-requests: write
1919
steps:
2020
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v4
21+
with:
22+
persist-credentials: false
2123
- uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v4
2224
with:
2325
node-version: "22"
@@ -41,6 +43,8 @@ jobs:
4143
contents: read
4244
steps:
4345
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v4
46+
with:
47+
persist-credentials: false
4448
- uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v4
4549
with:
4650
node-version: "22"

.github/workflows/canary-beta-release.yml

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

.github/workflows/codeql-analysis.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ jobs:
2222
steps:
2323
- name: Checkout repository
2424
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v4
25+
with:
26+
persist-credentials: false
2527

2628
- name: Initialize CodeQL
2729
uses: github/codeql-action/init@ebcb5b36ded6beda4ceefea6a8bc4cc885255bb3 # v3

.github/workflows/deploy-live.yml

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ on:
44
push:
55
branches: [main]
66

7+
concurrency:
8+
group: deploy-live
9+
cancel-in-progress: false
10+
711
jobs:
812
build:
913
if: github.repository == 'PaloAltoNetworks/docusaurus-openapi-docs'
@@ -15,6 +19,8 @@ jobs:
1519
steps:
1620
- name: Checkout repository
1721
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v4
22+
with:
23+
persist-credentials: false
1824

1925
- name: Setup node
2026
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v4
@@ -31,6 +37,9 @@ jobs:
3137
- name: Build site
3238
run: yarn build-demo && zip -r build.zip demo/build
3339

40+
- name: Check for tampered config
41+
run: git diff --exit-code -- firebase.json .firebaserc package.json yarn.lock 'demo/docusaurus.config.*' 'scripts/**' '.github/**'
42+
3443
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
3544
with:
3645
name: build
@@ -41,12 +50,16 @@ jobs:
4150
name: Deploy
4251
needs: build
4352
runs-on: ubuntu-latest
53+
environment: production
4454
permissions:
55+
contents: read
4556
id-token: write
4657

4758
steps:
4859
- name: Checkout repository
4960
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v4
61+
with:
62+
persist-credentials: false
5063

5164
- name: Setup node
5265
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v4
@@ -73,7 +86,7 @@ jobs:
7386
name: build
7487

7588
- name: Unzip build artifact
76-
run: unzip build.zip
89+
run: unzip -n build.zip 'demo/build/*'
7790

7891
- name: Deploy to Firebase
7992
id: deploy_live
@@ -86,3 +99,44 @@ jobs:
8699
target: docusaurus-openapi.tryingpan.dev
87100
env:
88101
FIREBASE_CLI_PREVIEWS: hostingchannels
102+
103+
cache_prod_screenshots:
104+
name: Cache Prod Screenshots
105+
needs: deploy
106+
if: ${{ github.repository == 'PaloAltoNetworks/docusaurus-openapi-docs' }}
107+
runs-on: ubuntu-latest
108+
permissions:
109+
contents: read
110+
111+
steps:
112+
- name: Checkout repository
113+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v4
114+
with:
115+
persist-credentials: false
116+
117+
- name: Setup node
118+
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v4
119+
with:
120+
node-version: "22"
121+
cache: "yarn"
122+
123+
- name: Install dependencies
124+
run: yarn --frozen-lockfile --prefer-offline --ignore-scripts
125+
126+
- name: Install Playwright
127+
run: npx playwright install --with-deps chromium
128+
129+
- name: Get production sitemap hash
130+
id: sitemap-hash
131+
run: |
132+
hash=$(curl -fsSL https://docusaurus-openapi.tryingpan.dev/sitemap.xml | sha256sum | cut -d' ' -f1)
133+
echo "hash=$hash" >> "$GITHUB_OUTPUT"
134+
135+
- name: Capture production screenshots
136+
run: yarn ts-node scripts/sitemap-visual-diff.ts --preview-url https://docusaurus-openapi.tryingpan.dev/ --concurrency 4 --paths "/tests/"
137+
138+
- name: Save production screenshots
139+
uses: actions/cache/save@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4
140+
with:
141+
path: visual_diffs/prod
142+
key: prod-screenshots-${{ steps.sitemap-hash.outputs.hash }}

.github/workflows/deploy-preview.yml

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,19 +17,20 @@ jobs:
1717
- name: Check if actor is org member
1818
id: is-org-member
1919
run: |
20-
if [ "${{ github.actor }}" = "dependabot[bot]" ]; then
20+
if [ "$ACTOR" = "dependabot[bot]" ]; then
2121
echo "is-org-member-result=false" >> "$GITHUB_OUTPUT"
2222
exit 0
2323
fi
2424
status=$(curl -s -o /dev/null -w "%{http_code}" -H "Authorization: Bearer $GH_TOKEN" \
25-
https://api.github.com/orgs/PaloAltoNetworks/members/${{ github.actor }})
25+
"https://api.github.com/orgs/PaloAltoNetworks/members/${ACTOR}")
2626
if [ "$status" = "204" ]; then
2727
echo "is-org-member-result=true" >> "$GITHUB_OUTPUT"
2828
else
2929
echo "is-org-member-result=false" >> "$GITHUB_OUTPUT"
3030
fi
3131
env:
3232
GH_TOKEN: ${{ secrets.PAT }}
33+
ACTOR: ${{ github.actor }}
3334

3435
analyze:
3536
if: github.repository == 'PaloAltoNetworks/docusaurus-openapi-docs' && needs.precheck.outputs.is-org-member-result == 'true'
@@ -50,6 +51,7 @@ jobs:
5051
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v4
5152
with:
5253
ref: ${{ github.event.pull_request.head.sha }}
54+
persist-credentials: false
5355

5456
- name: Initialize CodeQL
5557
uses: github/codeql-action/init@1b549b9259bda1cb5ddde3b41741a82a2d15a841 # v3
@@ -79,6 +81,7 @@ jobs:
7981
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v4
8082
with:
8183
ref: ${{ github.event.pull_request.head.sha }}
84+
persist-credentials: false
8285

8386
- name: Initialize CodeQL
8487
uses: github/codeql-action/init@1b549b9259bda1cb5ddde3b41741a82a2d15a841 # v3
@@ -104,6 +107,7 @@ jobs:
104107
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v4
105108
with:
106109
ref: ${{ github.event.pull_request.head.sha }}
110+
persist-credentials: false
107111

108112
- name: Setup node
109113
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v4
@@ -120,6 +124,9 @@ jobs:
120124
- name: Build site
121125
run: yarn build-demo && zip -r build.zip demo/build
122126

127+
- name: Check for tampered config
128+
run: git diff --exit-code -- firebase.json .firebaserc package.json yarn.lock 'demo/docusaurus.config.*' 'scripts/**' '.github/**'
129+
123130
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
124131
with:
125132
name: build
@@ -130,6 +137,7 @@ jobs:
130137
needs: build
131138
if: ${{ github.repository == 'PaloAltoNetworks/docusaurus-openapi-docs' && !failure() && !cancelled() }}
132139
runs-on: ubuntu-latest
140+
environment: preview
133141
permissions:
134142
contents: read
135143
pull-requests: write
@@ -141,6 +149,8 @@ jobs:
141149
steps:
142150
- name: Checkout repository
143151
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v4
152+
with:
153+
persist-credentials: false
144154

145155
- name: Setup node
146156
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v4
@@ -167,7 +177,7 @@ jobs:
167177
name: build
168178

169179
- name: Unzip build artifact
170-
run: unzip build.zip
180+
run: unzip -n build.zip 'demo/build/*'
171181

172182
- name: Deploy to Firebase
173183
id: deploy_preview
@@ -195,6 +205,7 @@ jobs:
195205
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v4
196206
with:
197207
ref: ${{ github.event.pull_request.head.sha }}
208+
persist-credentials: false
198209

199210
- name: Setup node
200211
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v4
@@ -215,15 +226,15 @@ jobs:
215226
echo "hash=$hash" >> "$GITHUB_OUTPUT"
216227
217228
- name: Restore cached production screenshots
218-
uses: actions/cache@v5.0.4
229+
uses: actions/cache/restore@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4
219230
with:
220231
path: visual_diffs/prod
221232
key: prod-screenshots-${{ steps.sitemap-hash.outputs.hash }}
222-
restore-keys: |
223-
prod-screenshots-
224233

225234
- name: Run visual diff
226-
run: yarn ts-node scripts/sitemap-visual-diff.ts --preview-url ${{ needs.deploy.outputs.preview_url }} --summary-file visual_diffs/results.json --concurrency 4 --paths "/tests/"
235+
run: yarn ts-node scripts/sitemap-visual-diff.ts --preview-url "$PREVIEW_URL" --summary-file visual_diffs/results.json --concurrency 4 --paths "/tests/"
236+
env:
237+
PREVIEW_URL: ${{ needs.deploy.outputs.preview_url }}
227238

228239
- name: Generate report and summary
229240
run: yarn ts-node scripts/generate-visual-diff-report.ts visual_diffs/results.json visual_diffs/index.html

0 commit comments

Comments
 (0)