diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 9aa58a5d..cdedeae4 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -81,8 +81,12 @@ jobs: - name: 📦 Install Dependencies run: pnpm install --frozen-lockfile + # Same pin as release.yml, and for the same reason. This job carries + # `pages: write` and `id-token: write`, so whatever runs here can publish + # to the project's Pages site. SHA is v1.3.0, what `v1` already resolved + # to. - name: 🏗 Setup Turborepo Cache - uses: dtinth/setup-github-actions-caching-for-turbo@v1 + uses: dtinth/setup-github-actions-caching-for-turbo@cc723b4600e40a6b8815b65701d8614b91e2669e # v1.3.0 - name: 🛠️ Setup Pages uses: actions/configure-pages@v6 diff --git a/.github/workflows/e2e-ios.yml b/.github/workflows/e2e-ios.yml index 00fc0a59..a48a004a 100644 --- a/.github/workflows/e2e-ios.yml +++ b/.github/workflows/e2e-ios.yml @@ -94,8 +94,8 @@ concurrency: jobs: # Run the (expensive) macOS build when: # - the PR is opened/updated by the repo owner (GSTJ), OR - # - a reviewer has approved the PR (including subsequent pushes to an - # already-approved PR), OR + # - a reviewer who can write here has approved the PR (including subsequent + # pushes to an already-approved PR), OR # - somebody dispatched the workflow by hand, which already requires write # access to this repository, OR # - the event is a push to main, which is already-reviewed code. @@ -145,9 +145,20 @@ jobs: echo "approved=false" >> "$GITHUB_OUTPUT" exit 0 fi - # Otherwise look up the latest review per reviewer on this PR. + # Otherwise look up the latest review on this PR, counting only + # reviewers who can write here. This repo is public, so anyone with a + # GitHub account can submit an APPROVED review on a fork PR. Without + # the author_association filter, two throwaway accounts (one to open, + # one to approve) are enough to run 45 minutes of macos-26 on + # attacker-controlled code. Nothing is leaked either way, the job has + # `contents: read` and no secrets, but it is billed compute. STATE=$(gh api "repos/${{ github.repository }}/pulls/$PR_NUM/reviews" \ - --jq '[.[] | select(.state=="APPROVED" or .state=="CHANGES_REQUESTED")] | sort_by(.submitted_at) | last | .state' \ + --jq '[.[] + | select(.state=="APPROVED" or .state=="CHANGES_REQUESTED") + | select(.author_association=="OWNER" + or .author_association=="MEMBER" + or .author_association=="COLLABORATOR")] + | sort_by(.submitted_at) | last | .state' \ || echo "") if [ "$STATE" = "APPROVED" ]; then echo "PR is approved." diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index daaf0c52..f1471c8a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -96,8 +96,15 @@ jobs: - name: 📦 Install Dependencies run: pnpm install + # Pinned to a commit, not the `v1` tag. This is the only third-party + # action in the repo that isn't `actions/*` or `pnpm/*`, it sits on a + # personal account, and it hasn't been pushed to since June 2024. It also + # leaves an HTTP server running on localhost for the rest of the job, and + # this job is the one that puts NPM_TOKEN on disk a few steps down. A + # mutable tag there means someone else's account decides what runs next to + # our publish credentials. SHA is v1.3.0, what `v1` already resolved to. - name: 🏗 Setup Turborepo Cache - uses: dtinth/setup-github-actions-caching-for-turbo@v1 + uses: dtinth/setup-github-actions-caching-for-turbo@cc723b4600e40a6b8815b65701d8614b91e2669e # v1.3.0 - name: 🛠️ Build run: pnpm run build @@ -211,7 +218,7 @@ jobs: run: | git config --global user.email "gabrielstaveira@gmail.com" git config --global user.name "Gabriel Taveira" - npm config set //registry.npmjs.org/:_authToken $NPM_TOKEN + npm config set //registry.npmjs.org/:_authToken "$NPM_TOKEN" pnpm run release # A release happens rarely, so the steps below it can sit unexecuted for