Skip to content

ci: harden GitHub Actions against supply chain attacks#1722

Merged
rodrigopavezi merged 4 commits into
masterfrom
feat/ci-supply-chain-hardening
May 22, 2026
Merged

ci: harden GitHub Actions against supply chain attacks#1722
rodrigopavezi merged 4 commits into
masterfrom
feat/ci-supply-chain-hardening

Conversation

@rodrigopavezi
Copy link
Copy Markdown
Member

Implements all GitHub Actions hardening from RequestNetwork/private-issues#282.

Changes

  • All third-party actions pinned to immutable commit SHAs — including github/codeql-action/upload-sarif which runs with security-events: write
  • Top-level permissions: contents: read added to workflows that lacked it (security workflows already had correct permission blocks)
  • StepSecurity Harden Runner added to every job (egress-policy: audit)
  • SocketDev Firewall Free added to tron-smart-contracts install steps (sfw yarn install --frozen-lockfile)

Next steps after merge

  • Monitor Harden Runner audit logs for ~1 week, then promote egress-policy: auditblock with the actual allowlist

- 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-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 14, 2026

Greptile Summary

This PR hardens seven GitHub Actions workflows against supply chain attacks by pinning all third-party actions to immutable commit SHAs, adding StepSecurity Harden Runner to every job, applying the SocketDev firewall to package install steps, and migrating github-script inline context interpolation to environment variables (fixing a script injection vector).

  • All direct action references (actions/checkout, actions/setup-node, actions/cache, actions/upload-artifact, actions/github-script, github/codeql-action/upload-sarif, step-security/harden-runner, SocketDev/action, kentaro-m/auto-assign-action) are now pinned to full commit SHAs.
  • permissions: contents: read was added to auto-project.yml, pr-comments.yml, reopen-issue-if-prs-open.yml, and tron-smart-contracts.yml; issues: write was added to security-echidna.yml so nightly failure issues can be created.
  • Three workflows (pr-comments.yml, auto-project.yml, reopen-issue-if-prs-open.yml) still call first-party reusable workflows via a mutable @main ref and forward PATs/tokens to them — this remains the open supply chain gap after this PR.

Confidence Score: 4/5

Safe to merge for most jobs, but three workflows still forward PATs/tokens to externally-owned reusable workflows referenced by a mutable branch tag.

The bulk of the hardening is solid — direct action pins, Harden Runner, SocketDev firewall, and the script-injection fixes are all correct. The remaining gap is that pr-comments.yml (a pull_request_target workflow forwarding GH_PAT_AUTO_COMMENTS), auto-project.yml (forwarding PROJECT_TOKEN), and reopen-issue-if-prs-open.yml (forwarding REOPEN_ISSUES_TOKEN) all call external reusable workflows via @main — exactly the attack vector this PR set out to eliminate.

pr-comments.yml needs the most attention due to its pull_request_target trigger combined with the unpinned external workflow and forwarded PAT. auto-project.yml and reopen-issue-if-prs-open.yml share the same pattern with their respective tokens.

Security Review

  • Mutable reusable workflow refs with forwarded secrets (pr-comments.yml, auto-project.yml, reopen-issue-if-prs-open.yml): all three call external RequestNetwork/* reusable workflows pinned to @main rather than a commit SHA. pr-comments.yml is the most exposed — it uses pull_request_target (runs with base-repo write access even for fork PRs) and forwards GH_PAT_AUTO_COMMENTS to the unpinned workflow. A compromise of those repos' main branches would give an attacker the token and PR write access.

Important Files Changed

Filename Overview
.github/workflows/pr-comments.yml Adds top-level permissions block, but the reusable workflow call to RequestNetwork/auto-comments@main remains unpinned; highest-risk file due to pull_request_target + forwarded PAT.
.github/workflows/auto-project.yml Adds permissions: contents: read; reusable workflow call to RequestNetwork/.github@main with PROJECT_TOKEN is still mutable.
.github/workflows/reopen-issue-if-prs-open.yml Adds permissions: contents: read; reusable workflow call to RequestNetwork/.github@main with REOPEN_ISSUES_TOKEN remains pinned to a mutable branch.
.github/workflows/auto_assign_pr.yml Harden Runner added and kentaro-m/auto-assign-action pinned to commit SHA; permissions block was already present.
.github/workflows/security-echidna.yml All actions pinned to commit SHAs, Harden Runner added, issues: write permission added, github-script steps migrated from inline context interpolation to env vars.
.github/workflows/security-slither.yml All actions pinned to commit SHAs including codeql-action/upload-sarif, Harden Runner added, github-script steps migrated to env vars; security-events: write was already present.
.github/workflows/tron-smart-contracts.yml All actions pinned, Harden Runner added to all three jobs, SocketDev firewall applied to install steps, top-level permissions: contents: read added.

Comments Outside Diff (1)

  1. .github/workflows/pr-comments.yml, line 14-19 (link)

    P1 security Reusable workflow still referenced via mutable @main tag

    This workflow uses pull_request_target (giving it write access to the base repo, even for fork PRs) and passes GH_PAT_AUTO_COMMENTS to an external reusable workflow pinned only at @main. If RequestNetwork/auto-comments main branch is ever compromised, malicious workflow code runs with PR write access and the PAT. The same pattern exists in auto-project.yml (calls RequestNetwork/.github@main with PROJECT_TOKEN) and reopen-issue-if-prs-open.yml (same repo with REOPEN_ISSUES_TOKEN). All three need to be pinned to a commit SHA instead of @main to close the gap this PR aims to address.

Reviews (4): Last reviewed commit: "fix(ci): address PR review comments on s..." | Re-trigger Greptile

@github-actions
Copy link
Copy Markdown

✅ Slither Security Analysis

Status: Passed

Findings Summary

Severity Count Status
✅ High 0 Pass
🟡 Medium 2 Review Recommended
🔵 Low 0 Info
ℹ️ Informational 1 Info

⚠️ Please review the findings in the Security tab or download the artifacts.

📄 Full report available in workflow artifacts.
🔍 View detailed findings in the Security tab.

@github-actions
Copy link
Copy Markdown

✅ Echidna Fuzzing Results

Mode: ci (50000 test sequences)
Status: All Properties Passed

Property Test Results

Status Count
✅ Passed 16
❌ Failed 0
Total 16
Pass Rate 100.0%

📄 Full report and corpus available in workflow artifacts.

ℹ️ About Echidna Fuzzing

Echidna is a property-based fuzzer that generates random sequences of transactions
to test invariants (properties that should always hold true).

Properties tested:

  • Fee calculation bounds
  • Access control enforcement
  • Amount constraints
  • No duplicate payments
  • Zero address validation
  • Integer overflow protection

@rodrigopavezi rodrigopavezi self-assigned this May 14, 2026
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.
@github-actions
Copy link
Copy Markdown

✅ Slither Security Analysis

Status: Passed

Findings Summary

Severity Count Status
✅ High 0 Pass
🟡 Medium 2 Review Recommended
🔵 Low 0 Info
ℹ️ Informational 1 Info

⚠️ Please review the findings in the Security tab or download the artifacts.

📄 Full report available in workflow artifacts.
🔍 View detailed findings in the Security tab.

@github-actions
Copy link
Copy Markdown

✅ Echidna Fuzzing Results

Mode: ci (50000 test sequences)
Status: All Properties Passed

Property Test Results

Status Count
✅ Passed 16
❌ Failed 0
Total 16
Pass Rate 100.0%

📄 Full report and corpus available in workflow artifacts.

ℹ️ About Echidna Fuzzing

Echidna is a property-based fuzzer that generates random sequences of transactions
to test invariants (properties that should always hold true).

Properties tested:

  • Fee calculation bounds
  • Access control enforcement
  • Amount constraints
  • No duplicate payments
  • Zero address validation
  • Integer overflow protection

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>
@github-actions
Copy link
Copy Markdown

✅ Slither Security Analysis

Status: Passed

Findings Summary

Severity Count Status
✅ High 0 Pass
🟡 Medium 2 Review Recommended
🔵 Low 0 Info
ℹ️ Informational 1 Info

⚠️ Please review the findings in the Security tab or download the artifacts.

📄 Full report available in workflow artifacts.
🔍 View detailed findings in the Security tab.

@github-actions
Copy link
Copy Markdown

✅ Echidna Fuzzing Results

Mode: ci (50000 test sequences)
Status: All Properties Passed

Property Test Results

Status Count
✅ Passed 16
❌ Failed 0
Total 16
Pass Rate 100.0%

📄 Full report and corpus available in workflow artifacts.

ℹ️ About Echidna Fuzzing

Echidna is a property-based fuzzer that generates random sequences of transactions
to test invariants (properties that should always hold true).

Properties tested:

  • Fee calculation bounds
  • Access control enforcement
  • Amount constraints
  • No duplicate payments
  • Zero address validation
  • Integer overflow protection

Copy link
Copy Markdown
Member

@MantisClone MantisClone left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 / # v7 comments 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:

  1. After merge, push any contract change to master to trigger Slither, Echidna, and the three Tron jobs.
  2. Verify each job has Harden Runner as step 1 and (Tron only) sfw yarn install --frozen-lockfile.
  3. Open https://app.stepsecurity.io and confirm the audit-mode log shows an egress list on each run.
  4. 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:

  1. Add Slither Static Analysis, Echidna Property-Based Fuzzing, and the three Tron checks to master's required status checks. Currently only CircleCI gates merge.
  2. Enable sha_pinning_required: true at the repo or org level so the pinning policy is regression-proof.
  3. Pin actions/github-script@v6 inside RequestNetwork/auto-comments/.github/workflows/pr-auto-comments.yml. That reusable workflow runs under pull_request_target with GH_PAT_AUTO_COMMENTS, so the supply-chain threat model leaks one hop in.
  4. Pin the three first-party @main reusable workflows (auto-project.yml, pr-comments.yml, reopen-issue-if-prs-open.yml) to SHAs or document accepting the residual risk.
  5. Add .github/CODEOWNERS requiring security-team review on .github/workflows/**.
  6. Add .github/dependabot.yml. The push to this branch surfaced 166 vulns on master (4 critical / 82 high) which is a related theme.
  7. Set dismiss_stale_reviews: true on master branch protection.

Comment thread .github/workflows/security-slither.yml Outdated
Comment thread .github/workflows/security-echidna.yml
Comment thread .github/workflows/security-slither.yml
Comment thread .github/workflows/tron-smart-contracts.yml Outdated
Comment thread .github/workflows/security-echidna.yml
- Fix invalid codeql-action/upload-sarif SHA (5e316336 -> 9e0d7b8d, v4.35.5)
- Add Socket.dev Firewall to security-slither and security-echidna yarn install steps
- Gate tronbox global install through sfw by swapping step order in tron-smart-contracts
- Use env: + process.env pattern in github-script steps to eliminate ${{ }} script injection
@github-actions
Copy link
Copy Markdown

✅ Slither Security Analysis

Status: Passed

Findings Summary

Severity Count Status
✅ High 0 Pass
🟡 Medium 2 Review Recommended
🔵 Low 0 Info
ℹ️ Informational 1 Info

⚠️ Please review the findings in the Security tab or download the artifacts.

📄 Full report available in workflow artifacts.
🔍 View detailed findings in the Security tab.

@github-actions
Copy link
Copy Markdown

✅ Echidna Fuzzing Results

Mode: ci (50000 test sequences)
Status: All Properties Passed

Property Test Results

Status Count
✅ Passed 16
❌ Failed 0
Total 16
Pass Rate 100.0%

📄 Full report and corpus available in workflow artifacts.

ℹ️ About Echidna Fuzzing

Echidna is a property-based fuzzer that generates random sequences of transactions
to test invariants (properties that should always hold true).

Properties tested:

  • Fee calculation bounds
  • Access control enforcement
  • Amount constraints
  • No duplicate payments
  • Zero address validation
  • Integer overflow protection

Copy link
Copy Markdown
Member Author

rodrigopavezi commented May 22, 2026

Merge activity

  • May 22, 2:36 PM UTC: A user started a stack merge that includes this pull request via Graphite.
  • May 22, 2:36 PM UTC: @rodrigopavezi merged this pull request with Graphite.

@rodrigopavezi rodrigopavezi merged commit 2d9d248 into master May 22, 2026
15 checks passed
@rodrigopavezi rodrigopavezi deleted the feat/ci-supply-chain-hardening branch May 22, 2026 14:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants