From 23eee4f3a45a927391045176b0fb65f6fdccbf3f Mon Sep 17 00:00:00 2001 From: Murderlon Date: Tue, 23 Sep 2025 10:57:36 +0200 Subject: [PATCH 1/4] Use environments to protect CI --- .github/workflows/ci.yml | 31 +++++++++++++++---------------- bb.test | 1 - 2 files changed, 15 insertions(+), 17 deletions(-) delete mode 100644 bb.test diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8f5860ef..be89669d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,11 +1,7 @@ name: CI -# SECURITY NOTE: This workflow uses pull_request_target which has access to secrets. -# This is needed because tests require access to external services with credentials. -# `pull_request_target` will always run without manual approval, even if "Require approval for all external contributors" is enabled in the repo settings. -# Therefore we implement a "safe to test" label that must be manually added once we have checked that the diff is safe. -# For PRs from forks, secrets are only provided when the "safe to test" label is present. -# This allows maintainers to safely test external contributions while preventing -# malicious actors from accessing secrets. +# SECURITY: Uses environment protection for external PRs instead of unsafe "safe to test" labels. +# Environment protection provides secure manual approval tied to specific commits, +# eliminating race conditions and ensuring maintainer review before secrets access. on: push: branches: [main] @@ -13,7 +9,7 @@ on: - "**.md" - ".changeset/**" pull_request_target: - types: [opened, synchronize, reopened, labeled] + types: [opened, synchronize, reopened] paths-ignore: - "**.md" - ".changeset/**" @@ -25,26 +21,29 @@ on: concurrency: ${{ github.workflow }}--${{ github.ref }} permissions: + contents: read pull-requests: write jobs: main: name: Node.js 20 runs-on: ubuntu-latest - # Only run tests with secrets if: - # 1. This is a push to main, OR - # 2. PR is from the same repository (trusted), OR - # 3. PR has the "safe to test" label (maintainer approved) + # SECURITY: Use environment protection for external contributors + environment: ${{ github.event.pull_request.head.repo.full_name != github.repository && 'external-testing' || '' }} + # Run tests with secrets for: + # 1. Push to main (trusted), OR + # 2. PR from same repository (trusted) + # For external PRs: environment protection requires manual approval if: | - github.event_name == 'push' || - github.event.pull_request.head.repo.full_name == github.repository || - contains(github.event.pull_request.labels.*.name, 'safe to test') + github.event_name == 'push' || + github.event.pull_request.head.repo.full_name == github.repository steps: - name: Checkout sources uses: actions/checkout@v4 with: - ref: ${{ github.event.pull_request.head.sha || github.sha }} + # SECURITY: For external PRs, only checkout trusted base branch + ref: ${{ github.event.pull_request.head.repo.full_name == github.repository && github.event.pull_request.head.sha || github.sha }} - name: Decrypt keyfile run: ./.github/scripts/decrypt_secret.sh diff --git a/bb.test b/bb.test deleted file mode 100644 index 3f8cad41..00000000 --- a/bb.test +++ /dev/null @@ -1 +0,0 @@ -bugbounty: pwned by Nisimi, Orca Security From e00d780d17b6dee25c660af7538c0287cb3150ae Mon Sep 17 00:00:00 2001 From: Murderlon Date: Tue, 23 Sep 2025 11:56:35 +0200 Subject: [PATCH 2/4] Apply feedback --- .github/workflows/ci.yml | 57 +++++++++++++++++++++++++++++----------- 1 file changed, 41 insertions(+), 16 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index be89669d..062e0f42 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,18 +15,49 @@ on: - ".changeset/**" pull_request: types: [opened, synchronize, reopened] - paths: - - .github/workflows/ci.yml + paths-ignore: + - "**.md" + - ".changeset/**" -concurrency: ${{ github.workflow }}--${{ github.ref }} +concurrency: + group: ${{ github.workflow }}--${{ github.ref }} + cancel-in-progress: true permissions: contents: read - pull-requests: write + pull-requests: read jobs: - main: - name: Node.js 20 + # Basic validation job - runs for all PRs without secrets + basic-validation: + name: Build and lint + runs-on: ubuntu-latest + if: github.event_name == 'pull_request' + + steps: + - name: Checkout sources + uses: actions/checkout@v4 + + - name: Install Node.js + uses: actions/setup-node@v4 + with: + node-version: 20.x + + - name: Install dependencies + run: npm ci --no-fund --no-audit + + - name: Build + run: npm run build + + - name: Check formatting + run: npm run format:check + + - name: Run linters + run: npm run lint + + # Integration tests with secrets - requires approval for external PRs + tests: + name: Tests runs-on: ubuntu-latest # SECURITY: Use environment protection for external contributors environment: ${{ github.event.pull_request.head.repo.full_name != github.repository && 'external-testing' || '' }} @@ -42,8 +73,8 @@ jobs: - name: Checkout sources uses: actions/checkout@v4 with: - # SECURITY: For external PRs, only checkout trusted base branch - ref: ${{ github.event.pull_request.head.repo.full_name == github.repository && github.event.pull_request.head.sha || github.sha }} + # Environment protection provides security - we can safely checkout PR code + ref: ${{ github.event.pull_request.head.sha || github.sha }} - name: Decrypt keyfile run: ./.github/scripts/decrypt_secret.sh @@ -51,9 +82,9 @@ jobs: KEYFILE_PASSPHRASE: ${{secrets.KEYFILE_PASSPHRASE}} - name: Install Node.js - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: - node-version: 20.19 + node-version: 20.x - name: Install dependencies run: npm ci --no-fund --no-audit @@ -61,12 +92,6 @@ jobs: - name: Build run: npm run build - - name: Check formatting - run: npm run format:check - - - name: Run linters - run: npm run lint - - name: Run tests run: npm run test env: From b10af49943d4dc7de9a7847db1364dcdf8c6d29c Mon Sep 17 00:00:00 2001 From: Murderlon Date: Tue, 23 Sep 2025 12:06:20 +0200 Subject: [PATCH 3/4] Apply feedback --- .github/workflows/ci.yml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 062e0f42..7195290c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,7 +20,7 @@ on: - ".changeset/**" concurrency: - group: ${{ github.workflow }}--${{ github.ref }} + group: ${{ github.workflow }}--${{ github.event_name == 'pull_request_target' && format('pr#{0}', github.event.pull_request.number) || github.ref }} cancel-in-progress: true permissions: @@ -42,6 +42,8 @@ jobs: uses: actions/setup-node@v4 with: node-version: 20.x + cache: npm + cache-dependency-path: package-lock.json - name: Install dependencies run: npm ci --no-fund --no-audit @@ -67,7 +69,8 @@ jobs: # For external PRs: environment protection requires manual approval if: | github.event_name == 'push' || - github.event.pull_request.head.repo.full_name == github.repository + (github.event_name == 'pull_request_target' && + github.event.pull_request.head.repo.full_name == github.repository) steps: - name: Checkout sources @@ -85,6 +88,8 @@ jobs: uses: actions/setup-node@v4 with: node-version: 20.x + cache: npm + cache-dependency-path: package-lock.json - name: Install dependencies run: npm ci --no-fund --no-audit From f7416270a5c8f552c2e923da07b071cf618ffc9d Mon Sep 17 00:00:00 2001 From: Murderlon Date: Tue, 23 Sep 2025 12:09:39 +0200 Subject: [PATCH 4/4] fixup! Apply feedback --- .github/workflows/ci.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7195290c..5cb5922a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -69,8 +69,7 @@ jobs: # For external PRs: environment protection requires manual approval if: | github.event_name == 'push' || - (github.event_name == 'pull_request_target' && - github.event.pull_request.head.repo.full_name == github.repository) + (github.event.pull_request.head.repo.full_name == github.repository) steps: - name: Checkout sources