Skip to content

ci: support external contributor PRs securely - #310

Merged
fsamier merged 2 commits into
mainfrom
chore/ci-external-contributors
Jul 29, 2026
Merged

ci: support external contributor PRs securely#310
fsamier merged 2 commits into
mainfrom
chore/ci-external-contributors

Conversation

@fsamier

@fsamier fsamier commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Summary

Adapt CI workflows to safely support external contributor (fork) PRs, addressing the security and functional issues surfaced by #308.

Changes

ci.yml — Hardened for fork PRs

  • Switch to ubuntu-latest (GitHub-hosted runners) — untrusted fork code must never run on self-hosted runners (public-ledgerhq-shared-small) to prevent arbitrary code execution on Ledger infrastructure
  • Reduce permissions to contents: read at job level — principle of least privilege
  • Guard API keys step with if: github.event.pull_request.head.repo.full_name == github.repository — secrets are empty for fork PRs, but this makes intent explicit
  • Remove inline labeling/enforce-labels — moved to ci-trusted.yml since these need write access
  • Test results uploaded as artifact instead of inline PR comment (fork PRs can't write comments)
  • Docs deployment isolated to a separate deploy-docs job with minimal permissions (pages: write, id-token: write), only runs on push to main

ci-trusted.yml — New workflow for privileged operations

  • Uses pull_request_target trigger — runs in the base branch context with access to secrets/write token
  • Checks out base branch only — never checks out or executes fork code
  • Handles auto-labeling and label enforcement for all PRs (internal + external)
  • Handles test report publishing by downloading artifacts from the CI workflow

Security considerations

  • Fork PR code never runs on self-hosted runners
  • Fork PR code never has access to secrets or write tokens
  • pull_request_target workflow never checks out fork code (only base.ref)
  • Permissions follow principle of least privilege per job

Notes

  • release.yml intentionally kept on public-ledgerhq-shared-small (needs JFrog Artifactory access)
  • GitHub-hosted runners are free for public repositories — no cost impact

- Switch CI to GitHub-hosted runners (ubuntu-latest) so fork PRs
  never execute on self-hosted infrastructure
- Reduce permissions to contents:read for lint & test job
- Guard API keys step to only run for internal PRs
- Move labeling and test report publishing to ci-trusted.yml
  using pull_request_target (safe: never checks out fork code)
- Isolate docs deployment to a separate job with minimal permissions
@fsamier
fsamier requested a review from a team as a code owner July 29, 2026 10:03
Comment thread .github/workflows/ci.yml Dismissed
@fsamier
fsamier enabled auto-merge (squash) July 29, 2026 10:11
@fsamier
fsamier merged commit fbbf91e into main Jul 29, 2026
13 checks passed
@fsamier
fsamier deleted the chore/ci-external-contributors branch July 29, 2026 10:11
@fsamier fsamier added the ci label Jul 29, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR restructures GitHub Actions CI to safely support external (fork) pull requests by moving privileged operations (labeling, commenting) into a separate trusted workflow and reducing permissions in the main CI workflow.

Changes:

  • Switched CI to GitHub-hosted runners (ubuntu-latest) with read-only permissions for PRs, and guarded secret-dependent steps.
  • Replaced inline test reporting with artifact upload in ci.yml, and introduced a new ci-trusted.yml workflow intended to publish reports and manage labels with write permissions.
  • Split GitHub Pages deployment into a dedicated deploy-docs job that only runs on pushes to main with minimal Pages permissions.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
.github/workflows/ci.yml Harden CI for fork PRs (runner/permissions), upload artifacts (tests/docs), and deploy docs only on main pushes.
.github/workflows/ci-trusted.yml New trusted workflow using pull_request_target for labeling and test report publishing.
Comments suppressed due to low confidence (1)

.github/workflows/ci-trusted.yml:77

  • This workflow is triggered by pull_request_target, so github.event.workflow_run.id is not present in the event payload. The artifact download will fail (or always download nothing) because run-id resolves to an empty value.
      - name: Download test results artifact
        timeout-minutes: 5
        uses: actions/download-artifact@v4
        with:
          name: test-results
          run-id: ${{ github.event.workflow_run.id }}
          github-token: ${{ secrets.GITHUB_TOKEN }}
        continue-on-error: true

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +63 to +68
uses: lewagon/wait-on-check-action@v1.3.4
with:
ref: ${{ github.event.pull_request.head.sha }}
check-name: "lint & test"
repo-token: ${{ secrets.GITHUB_TOKEN }}
wait-interval: 30
Comment on lines +16 to +19
permissions:
contents: read
pull-requests: write

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants