ci: harden GitHub Actions against supply chain attacks#1722
ci: harden GitHub Actions against supply chain attacks#1722rodrigopavezi wants to merge 3 commits into
Conversation
- Pin all third-party actions to immutable commit SHAs - Add top-level permissions: contents: read to all workflows - Add StepSecurity Harden Runner (egress-policy: audit) to every job - Add SocketDev/action (firewall-free) + sfw install wrapper to tron-smart-contracts jobs - Pin github/codeql-action/upload-sarif to SHA (runs with security-events: write) Closes RequestNetwork/private-issues#282
Greptile SummaryThis PR hardens seven GitHub Actions workflows against supply chain attacks by pinning all third-party action references to immutable commit SHAs, adding StepSecurity Harden Runner to every job, introducing top-level
Confidence Score: 4/5Safe to merge for the changes it makes, but three workflows still call external reusable workflows via mutable The SHA pinning, Harden Runner additions, and Socket.dev integration are solid improvements. The remaining gap is in
Important Files Changed
Reviews (3): Last reviewed commit: "chore: re-trigger CI after Performance p..." | Re-trigger Greptile |
✅ Slither Security AnalysisStatus: Passed Findings Summary
📄 Full report available in workflow artifacts. |
✅ Echidna Fuzzing ResultsMode: ci (50000 test sequences) Property Test Results
📄 Full report and corpus available in workflow artifacts. ℹ️ About Echidna FuzzingEchidna is a property-based fuzzer that generates random sequences of transactions Properties tested:
|
The nightly failure-alert step calls github.rest.issues.create() to notify the team when Echidna properties fail. Without issues: write the call silently returns a 403 and the alert is never created.
✅ Slither Security AnalysisStatus: Passed Findings Summary
📄 Full report available in workflow artifacts. |
✅ Echidna Fuzzing ResultsMode: ci (50000 test sequences) Property Test Results
📄 Full report and corpus available in workflow artifacts. ℹ️ About Echidna FuzzingEchidna is a property-based fuzzer that generates random sequences of transactions Properties tested:
|
The previous CircleCI failures on this PR were caused by the RequestNetwork CircleCI org dropping to the Free plan, which caps Docker resource classes at large. The repo's .circleci/config.yml declares xlarge for build/test jobs (deliberate; see #1703), so every build failed with resource-class-not-in-plan. Org was upgraded to Performance; this empty commit re-triggers the pipeline. No source changes. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
✅ Slither Security AnalysisStatus: Passed Findings Summary
📄 Full report available in workflow artifacts. |
✅ Echidna Fuzzing ResultsMode: ci (50000 test sequences) Property Test Results
📄 Full report and corpus available in workflow artifacts. ℹ️ About Echidna FuzzingEchidna is a property-based fuzzer that generates random sequences of transactions Properties tested:
|
MantisClone
left a comment
There was a problem hiding this comment.
Approved 👍 pending comment resolution 🚧
Mostly clean; one bug and one scope gap to address before merge.
🔴 Must-fix before merge
github/codeql-action/upload-sarif@5e316336… does not exist in github/codeql-action. Verified three ways: 422 on direct commit lookup, no ref points at it, not in the tag list. The step is if: always() && hashFiles(...) != '' and Slither emits a SARIF every run, so it fails the SARIF upload (and the Slither job) on every contract PR. This is also the exact action #282 called out as highest priority.
Fix: github/codeql-action/upload-sarif@9e0d7b8d25671d64c341c19c0152d693099fb5ba # v4.35.5.
🟡 Scope gap
security-echidna.yml and security-slither.yml both run yarn install --frozen-lockfile unprotected by Socket Firewall. #282 task 4 said Socket on the install step across CI workflows; the PR only wraps the three Tron install steps. Either add sfw to the two security workflows or call out the rationale in the description.
🔵 Nice-to-have before merge
- Bump
# v2/# v4/# v7comments to exact-version (e.g.# v2.11.1,# v4.4.0) so the next reviewer can verify by eye. The floating major tags have already moved past several of the pinned SHAs. - Lift the dedicated
fix(ci): add issues: write…commit subject into the PR description so the permission expansion is documented in the body, not just in git log.
📋 UAT
PR is missing a UAT procedure. Suggested shape:
- After merge, push any contract change to master to trigger Slither, Echidna, and the three Tron jobs.
- Verify each job has Harden Runner as step 1 and (Tron only)
sfw yarn install --frozen-lockfile. - Open https://app.stepsecurity.io and confirm the audit-mode log shows an egress list on each run.
- Confirm the Slither SARIF upload to the Security tab succeeds (this is the failure mode of the must-fix above).
📌 Follow-ups (separate issues, not blockers)
Fresh-eyes pass surfaced things outside this PR's scope. Happy to file these as private-issues if you want:
- Add
Slither Static Analysis,Echidna Property-Based Fuzzing, and the three Tron checks tomaster's required status checks. Currently only CircleCI gates merge. - Enable
sha_pinning_required: trueat the repo or org level so the pinning policy is regression-proof. - Pin
actions/github-script@v6insideRequestNetwork/auto-comments/.github/workflows/pr-auto-comments.yml. That reusable workflow runs underpull_request_targetwithGH_PAT_AUTO_COMMENTS, so the supply-chain threat model leaks one hop in. - Pin the three first-party
@mainreusable workflows (auto-project.yml,pr-comments.yml,reopen-issue-if-prs-open.yml) to SHAs or document accepting the residual risk. - Add
.github/CODEOWNERSrequiring security-team review on.github/workflows/**. - Add
.github/dependabot.yml. The push to this branch surfaced 166 vulns on master (4 critical / 82 high) which is a related theme. - Set
dismiss_stale_reviews: trueon master branch protection.
| - name: Upload SARIF to GitHub Security | ||
| if: always() && hashFiles('packages/smart-contracts/reports/security/slither.sarif') != '' | ||
| uses: github/codeql-action/upload-sarif@v4 | ||
| uses: github/codeql-action/upload-sarif@5e316336eb4f107009e477d4bfbfff13d7250fae # v4 |
There was a problem hiding this comment.
🔴 Must-fix before merge: this SHA does not exist in github/codeql-action. Verified: gh api repos/github/codeql-action/commits/5e316336... returns 422, and no ref points at it. The step runs if: always() && hashFiles(...) != '' and Slither emits a SARIF every run, so this fails the job every time.
Replace with:
uses: github/codeql-action/upload-sarif@9e0d7b8d25671d64c341c19c0152d693099fb5ba # v4.35.5|
|
||
| - name: Setup Node.js | ||
| uses: actions/setup-node@v4 | ||
| uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 |
There was a problem hiding this comment.
🟡 Adjacent feedback: the yarn install --frozen-lockfile step a few lines below is unprotected by Socket Firewall. #282 task 4 said Socket on the install step across CI workflows; the PR only wraps the three Tron install steps. Suggest adding the same setup-Socket pattern Tron got, immediately before the install step:
- name: Setup Socket.dev
uses: SocketDev/action@ba6de6cc0565af1f42295590380973573297e31f # v1.3.2
with:
mode: firewall-freeand changing the install line to sfw yarn install --frozen-lockfile.
|
|
||
| - name: Setup Node.js | ||
| uses: actions/setup-node@v4 | ||
| uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 |
There was a problem hiding this comment.
🟡 Same Socket Firewall gap as security-echidna.yml. Same fix.
| cache: 'yarn' | ||
|
|
||
| - name: Install TronBox globally | ||
| run: npm install -g tronbox |
There was a problem hiding this comment.
🔵 Minor: this runs before Setup Socket.dev so the tronbox global install isn't gated by sfw. Harden Runner audit still observes its egress. Suggest swapping the two so all dep installs in this job go through Socket.
| - name: Comment on PR | ||
| if: github.event_name == 'pull_request' && always() | ||
| uses: actions/github-script@v7 | ||
| uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7 |
There was a problem hiding this comment.
🔵 Nit, not blocking: the '${{ steps.parse.outputs.X }}' interpolation pattern below is the github-script script-injection shape that zizmor and actionlint flag. Safe today since the values are jq-extracted integers, but the safer pattern is env: + process.env. Same in security-slither.yml:140.
Implements all GitHub Actions hardening from RequestNetwork/private-issues#282.
Changes
github/codeql-action/upload-sarifwhich runs withsecurity-events: writepermissions: contents: readadded to workflows that lacked it (security workflows already had correct permission blocks)egress-policy: audit)sfw yarn install --frozen-lockfile)Next steps after merge
egress-policy: audit→blockwith the actual allowlist