From 3c1af0c24f763b933737e5827996ca6e4d83482f Mon Sep 17 00:00:00 2001 From: Steve Dodier-Lazaro Date: Fri, 29 May 2026 16:16:32 +0200 Subject: [PATCH 1/4] CI: Restrict trusted CircleCI PR authors to specific teams --- .../workflows/trigger-circle-ci-workflow.yml | 26 +++++++++++++++---- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/.github/workflows/trigger-circle-ci-workflow.yml b/.github/workflows/trigger-circle-ci-workflow.yml index 2e429aa10e79..f715a74ef1b1 100644 --- a/.github/workflows/trigger-circle-ci-workflow.yml +++ b/.github/workflows/trigger-circle-ci-workflow.yml @@ -94,9 +94,9 @@ jobs: - id: trusted-author env: EVENT_NAME: ${{ github.event_name }} - ASSOCIATION: ${{ github.event.pull_request.author_association }} USER_TYPE: ${{ github.event.pull_request.user.type }} USER_LOGIN: ${{ github.event.pull_request.user.login }} + GITHUB_API_TOKEN: ${{ github.token }} run: | # You can only push to `main` and `next` as a core team member, so the content is trustworthy. if [ "$EVENT_NAME" = "push" ]; then @@ -104,11 +104,27 @@ jobs: # These commits are made by the release actions, which are gated to core team members. elif [ "$USER_LOGIN" = "github-actions[bot]" ] && [ "$USER_TYPE" = "Bot" ]; then echo "result=true" >> "$GITHUB_OUTPUT" - # Trusted members of the organization can also write to cache (core team, DX, and a few maintainers) - elif { [ "$ASSOCIATION" = "OWNER" ] || [ "$ASSOCIATION" = "MEMBER" ]; } && [ "$USER_TYPE" != "Bot" ]; then - echo "result=true" >> "$GITHUB_OUTPUT" else - echo "result=false" >> "$GITHUB_OUTPUT" + # Explicitly trust only members of specific Storybook teams. + # Team slugs for: Maintainers, Core, Developer Experience. + TRUSTED_TEAMS="maintainers core developer-experience" + IS_TRUSTED=false + + for TEAM in $TRUSTED_TEAMS; do + STATE=$(curl -fsSL \ + -H "Authorization: Bearer $GITHUB_API_TOKEN" \ + -H "Accept: application/vnd.github+json" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + "https://api.github.com/orgs/storybookjs/teams/$TEAM/memberships/$USER_LOGIN" \ + | jq -r '.state' 2>/dev/null || true) + + if [ "$STATE" = "active" ]; then + IS_TRUSTED=true + break + fi + done + + echo "result=$IS_TRUSTED" >> "$GITHUB_OUTPUT" fi outputs: workflow: ${{ steps.normal.outputs.workflow || steps.docs.outputs.workflow || steps.merged.outputs.workflow || steps.daily.outputs.workflow }} From 3bb369f4b9f907c3e552e40524cd6f773af9a99d Mon Sep 17 00:00:00 2001 From: Steve Dodier-Lazaro Date: Fri, 29 May 2026 16:18:30 +0200 Subject: [PATCH 2/4] Restore trusted author param lost in rebase --- .github/workflows/trigger-circle-ci-workflow.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/trigger-circle-ci-workflow.yml b/.github/workflows/trigger-circle-ci-workflow.yml index f715a74ef1b1..a01cbb566d3a 100644 --- a/.github/workflows/trigger-circle-ci-workflow.yml +++ b/.github/workflows/trigger-circle-ci-workflow.yml @@ -145,11 +145,13 @@ jobs: WORKFLOW: ${{ needs.get-parameters.outputs.workflow }} GH_BASE_BRANCH: ${{ needs.get-parameters.outputs.ghBaseBranch }} GH_PR_NUMBER: ${{ needs.get-parameters.outputs.ghPrNumber }} + GH_TRUSTED_AUTHOR: ${{ needs.get-parameters.outputs.ghTrustedAuthor }} run: | PARAMETERS=$(jq -nc \ --arg workflow "$WORKFLOW" \ --arg ghBaseBranch "$GH_BASE_BRANCH" \ --arg ghPrNumber "$GH_PR_NUMBER" \ + --arg ghTrustedAuthor "$GH_TRUSTED_AUTHOR" \ '{workflow: $workflow, ghBaseBranch: $ghBaseBranch, ghPrNumber: $ghPrNumber}') PAYLOAD=$(jq -nc --arg branch "$BRANCH" --argjson parameters "$PARAMETERS" \ '{branch: $branch, parameters: $parameters}') From 21a4ff684ed464b5a4c3d3f38475ffe00f1bcac4 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 29 May 2026 15:10:33 +0000 Subject: [PATCH 3/4] fix(ci): pass trusted-author flag and grant members read permission Co-authored-by: Sidnioulz <5108577+Sidnioulz@users.noreply.github.com> --- .github/workflows/trigger-circle-ci-workflow.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/trigger-circle-ci-workflow.yml b/.github/workflows/trigger-circle-ci-workflow.yml index a01cbb566d3a..74dd979b0a8a 100644 --- a/.github/workflows/trigger-circle-ci-workflow.yml +++ b/.github/workflows/trigger-circle-ci-workflow.yml @@ -77,7 +77,8 @@ jobs: get-parameters: if: github.repository_owner == 'storybookjs' runs-on: ubuntu-latest - permissions: {} + permissions: + members: read steps: - id: normal if: github.event_name == 'pull_request_target' && (contains(github.event.pull_request.labels.*.name, 'ci:normal')) @@ -152,7 +153,7 @@ jobs: --arg ghBaseBranch "$GH_BASE_BRANCH" \ --arg ghPrNumber "$GH_PR_NUMBER" \ --arg ghTrustedAuthor "$GH_TRUSTED_AUTHOR" \ - '{workflow: $workflow, ghBaseBranch: $ghBaseBranch, ghPrNumber: $ghPrNumber}') + '{workflow: $workflow, ghBaseBranch: $ghBaseBranch, ghPrNumber: $ghPrNumber, ghTrustedAuthor: $ghTrustedAuthor}') PAYLOAD=$(jq -nc --arg branch "$BRANCH" --argjson parameters "$PARAMETERS" \ '{branch: $branch, parameters: $parameters}') curl -sS --fail-with-body -X POST \ From 331367ee24c579a7f091a540f1beb50af17477d8 Mon Sep 17 00:00:00 2001 From: Steve Dodier-Lazaro Date: Fri, 5 Jun 2026 20:51:55 +0200 Subject: [PATCH 4/4] Fix permissions --- .github/workflows/trigger-circle-ci-workflow.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/trigger-circle-ci-workflow.yml b/.github/workflows/trigger-circle-ci-workflow.yml index 74dd979b0a8a..db7dd9893e50 100644 --- a/.github/workflows/trigger-circle-ci-workflow.yml +++ b/.github/workflows/trigger-circle-ci-workflow.yml @@ -77,8 +77,7 @@ jobs: get-parameters: if: github.repository_owner == 'storybookjs' runs-on: ubuntu-latest - permissions: - members: read + permissions: {} steps: - id: normal if: github.event_name == 'pull_request_target' && (contains(github.event.pull_request.labels.*.name, 'ci:normal')) @@ -97,7 +96,7 @@ jobs: EVENT_NAME: ${{ github.event_name }} USER_TYPE: ${{ github.event.pull_request.user.type }} USER_LOGIN: ${{ github.event.pull_request.user.login }} - GITHUB_API_TOKEN: ${{ github.token }} + GITHUB_API_TOKEN: ${{ secrets.STORYBOOKJS_ORG_MEMBERSHIP_TOKEN }} run: | # You can only push to `main` and `next` as a core team member, so the content is trustworthy. if [ "$EVENT_NAME" = "push" ]; then