From 0c85aee498c438d8df7c640e78343cdf64e14e7c Mon Sep 17 00:00:00 2001 From: Aleksandr Pasevin Date: Wed, 20 May 2026 17:36:37 +0300 Subject: [PATCH 1/3] fix(ci): harden workflows against script injection Extract repeated token-resolution boilerplate into a reusable auth-token composite action and eliminate ${{ }} interpolation inside run: blocks across workflows. - Add .github/actions/auth-token composite for fork-aware token resolution - Pass NPM_TOKEN and matrix values through env vars in run: blocks - Add concurrency groups to PR workflows - Set cancel-in-progress: false on production deployment - Unify harden-runner to v2.13.0 - Bump pnpm/action-setup to v4.2.0 and setup-node to v4.4.0 - Bump docker/setup-buildx-action to v3.12.0 - Drop continue-on-error on CI test step - Use app token (instead of GITHUB_TOKEN) in update-dependencies Supersedes #337, which had diverged from main after #373 removed publish.yml, update-versions.yml, and the publish-rc job in docker-stg. Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/actions/auth-token/action.yml | 62 ++++++++++++++++++ .github/actions/prepare/action.yml | 4 +- .github/workflows/check-versions.yml | 36 ++++------- .github/workflows/ci.yml | 38 ++++------- .github/workflows/coverage.yml | 36 ++++------- .github/workflows/dependencies.yml | 31 +++------ .github/workflows/docker-prod.yaml | 10 +-- .github/workflows/docker-stg.yaml | 8 +-- .github/workflows/export-testing.yml | 77 ++++++++--------------- .github/workflows/lint.yml | 36 ++++------- .github/workflows/scorecard.yml | 13 ++-- .github/workflows/update-dependencies.yml | 24 ++++--- 12 files changed, 179 insertions(+), 196 deletions(-) create mode 100644 .github/actions/auth-token/action.yml diff --git a/.github/actions/auth-token/action.yml b/.github/actions/auth-token/action.yml new file mode 100644 index 000000000..0cc7e2f88 --- /dev/null +++ b/.github/actions/auth-token/action.yml @@ -0,0 +1,62 @@ +--- +name: Resolve Authentication Token +description: | + Selects between a GitHub App token and the default GITHUB_TOKEN. + Uses the app token when credentials are available and the workflow + is not triggered from a fork. + +inputs: + app-id: + description: GitHub App ID + required: false + default: '' + private-key: + description: GitHub App private key + required: false + default: '' + is-fork: + description: Whether the PR is from a fork + required: false + default: 'false' + +outputs: + token: + description: The resolved authentication token + value: ${{ steps.select.outputs.token }} + +runs: + using: composite + steps: + - name: Check if app creds exist + id: has-app + shell: bash + env: + IS_FORK: ${{ inputs.is-fork }} + APP_ID: ${{ inputs.app-id }} + PRIVATE_KEY: ${{ inputs.private-key }} + run: | + present=true + if [ "$IS_FORK" = "true" ]; then present=false; fi + if [ -z "$APP_ID" ] || [ -z "$PRIVATE_KEY" ]; then present=false; fi + echo "present=$present" >> "$GITHUB_OUTPUT" + + - uses: actions/create-github-app-token@af35edadc00be37caa72ed9f3e6d5f7801bfdf09 # v1.11.7 + id: gh-app-token + if: steps.has-app.outputs.present == 'true' + with: + app-id: ${{ inputs.app-id }} + private-key: ${{ inputs.private-key }} + + - name: Select token + id: select + shell: bash + env: + HAS_APP: ${{ steps.has-app.outputs.present }} + APP_TOKEN: ${{ steps.gh-app-token.outputs.token }} + FALLBACK_TOKEN: ${{ github.token }} + run: | + if [ "$HAS_APP" = "true" ]; then + echo "token=$APP_TOKEN" >> "$GITHUB_OUTPUT" + else + echo "token=$FALLBACK_TOKEN" >> "$GITHUB_OUTPUT" + fi diff --git a/.github/actions/prepare/action.yml b/.github/actions/prepare/action.yml index 83e35c9fa..050675206 100644 --- a/.github/actions/prepare/action.yml +++ b/.github/actions/prepare/action.yml @@ -15,12 +15,12 @@ runs: token: ${{ inputs.token }} persist-credentials: true - - uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0 + - uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4.2.0 with: run_install: false - name: Use node@22 - uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 + uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: node-version: 22.18.0 cache: 'pnpm' diff --git a/.github/workflows/check-versions.yml b/.github/workflows/check-versions.yml index 1847f10cd..ab0c0a70a 100644 --- a/.github/workflows/check-versions.yml +++ b/.github/workflows/check-versions.yml @@ -10,6 +10,10 @@ on: - develop - "release/**" +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + permissions: contents: read @@ -25,32 +29,16 @@ jobs: with: egress-policy: audit - - name: Check if app creds exist (base repo only) - id: has-app - run: | - present=true - if [ "${{ github.event.pull_request.head.repo.fork || false }}" = "true" ]; then present=false; fi - if [ -z "${{ vars.GH_APP_ID }}" ] || [ -z "${{ secrets.GH_APP_PRIVATE_KEY }}" ]; then present=false; fi - echo "present=$present" >> "$GITHUB_OUTPUT" + - name: Checkout + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - uses: actions/create-github-app-token@af35edadc00be37caa72ed9f3e6d5f7801bfdf09 # v1.11.7 - id: gh-app-token - if: steps.has-app.outputs.present == 'true' + - name: Resolve authentication token + id: auth + uses: ./.github/actions/auth-token with: app-id: ${{ vars.GH_APP_ID }} private-key: ${{ secrets.GH_APP_PRIVATE_KEY }} - - - name: Select token - id: auth - run: | - if [ "${{ steps.has-app.outputs.present }}" = "true" ]; then - echo "token=${{ steps.gh-app-token.outputs.token }}" >> "$GITHUB_OUTPUT" - else - echo "token=${{ github.token }}" >> "$GITHUB_OUTPUT" - fi - - - name: Checkout Repo - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + is-fork: ${{ github.event.pull_request.head.repo.fork || false }} - name: Prepare pre-requisites uses: ./.github/actions/prepare @@ -58,8 +46,10 @@ jobs: token: ${{ steps.auth.outputs.token }} - name: Configure npm authentication for npm registry + env: + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} run: | - echo "//registry.npmjs.org/:_authToken=${{ secrets.NPM_TOKEN }}" >> ~/.npmrc + echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" >> ~/.npmrc - name: Install dependencies run: pnpm install diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 96cb4d051..272701167 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -9,6 +9,10 @@ on: pull_request: branches: [main] +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + permissions: contents: read @@ -28,32 +32,16 @@ jobs: with: egress-policy: audit - - name: Check if app creds exist (base repo only) - id: has-app - run: | - present=true - if [ "${{ github.event.pull_request.head.repo.fork || false }}" = "true" ]; then present=false; fi - if [ -z "${{ vars.GH_APP_ID }}" ] || [ -z "${{ secrets.GH_APP_PRIVATE_KEY }}" ]; then present=false; fi - echo "present=$present" >> "$GITHUB_OUTPUT" + - name: Checkout + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - uses: actions/create-github-app-token@af35edadc00be37caa72ed9f3e6d5f7801bfdf09 # v1.11.7 - id: gh-app-token - if: steps.has-app.outputs.present == 'true' + - name: Resolve authentication token + id: auth + uses: ./.github/actions/auth-token with: app-id: ${{ vars.GH_APP_ID }} private-key: ${{ secrets.GH_APP_PRIVATE_KEY }} - - - name: Select token - id: auth - run: | - if [ "${{ steps.has-app.outputs.present }}" = "true" ]; then - echo "token=${{ steps.gh-app-token.outputs.token }}" >> "$GITHUB_OUTPUT" - else - echo "token=${{ github.token }}" >> "$GITHUB_OUTPUT" - fi - - - name: Checkout - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + is-fork: ${{ github.event.pull_request.head.repo.fork || false }} - name: Prepare pre-requisites uses: ./.github/actions/prepare @@ -61,8 +49,10 @@ jobs: token: ${{ steps.auth.outputs.token }} - name: Configure npm authentication for npm registry + env: + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} run: | - echo "//registry.npmjs.org/:_authToken=${{ secrets.NPM_TOKEN }}" >> ~/.npmrc + echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" >> ~/.npmrc - name: Install dependencies run: pnpm install @@ -77,5 +67,3 @@ jobs: - name: Test run: pnpm test - # It's okay if no tests exist yet - continue-on-error: true diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index a37850b45..e990d123a 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -9,6 +9,10 @@ on: pull_request: branches: [main] +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + permissions: contents: read @@ -23,32 +27,16 @@ jobs: with: egress-policy: audit - - name: Check if app creds exist (base repo only) - id: has-app - run: | - present=true - if [ "${{ github.event.pull_request.head.repo.fork || false }}" = "true" ]; then present=false; fi - if [ -z "${{ vars.GH_APP_ID }}" ] || [ -z "${{ secrets.GH_APP_PRIVATE_KEY }}" ]; then present=false; fi - echo "present=$present" >> "$GITHUB_OUTPUT" + - name: Checkout + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - uses: actions/create-github-app-token@af35edadc00be37caa72ed9f3e6d5f7801bfdf09 # v1.11.7 - id: gh-app-token - if: steps.has-app.outputs.present == 'true' + - name: Resolve authentication token + id: auth + uses: ./.github/actions/auth-token with: app-id: ${{ vars.GH_APP_ID }} private-key: ${{ secrets.GH_APP_PRIVATE_KEY }} - - - name: Select token - id: auth - run: | - if [ "${{ steps.has-app.outputs.present }}" = "true" ]; then - echo "token=${{ steps.gh-app-token.outputs.token }}" >> "$GITHUB_OUTPUT" - else - echo "token=${{ github.token }}" >> "$GITHUB_OUTPUT" - fi - - - name: Checkout - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + is-fork: ${{ github.event.pull_request.head.repo.fork || false }} - name: Prepare pre-requisites uses: ./.github/actions/prepare @@ -56,8 +44,10 @@ jobs: token: ${{ steps.auth.outputs.token }} - name: Configure npm authentication for npm registry + env: + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} run: | - echo "//registry.npmjs.org/:_authToken=${{ secrets.NPM_TOKEN }}" >> ~/.npmrc + echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" >> ~/.npmrc - name: Install dependencies run: pnpm install diff --git a/.github/workflows/dependencies.yml b/.github/workflows/dependencies.yml index c552ac91a..da1f88b11 100644 --- a/.github/workflows/dependencies.yml +++ b/.github/workflows/dependencies.yml @@ -22,41 +22,26 @@ jobs: with: egress-policy: audit - - name: Check if app creds exist (base repo only) - id: has-app - run: | - present=true - if [ "${{ github.event.pull_request.head.repo.fork || false }}" = "true" ]; then present=false; fi - if [ -z "${{ vars.GH_APP_ID }}" ] || [ -z "${{ secrets.GH_APP_PRIVATE_KEY }}" ]; then present=false; fi - echo "present=$present" >> "$GITHUB_OUTPUT" + - name: Checkout + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - uses: actions/create-github-app-token@af35edadc00be37caa72ed9f3e6d5f7801bfdf09 # v1.11.7 - id: gh-app-token - if: steps.has-app.outputs.present == 'true' + - name: Resolve authentication token + id: auth + uses: ./.github/actions/auth-token with: app-id: ${{ vars.GH_APP_ID }} private-key: ${{ secrets.GH_APP_PRIVATE_KEY }} - - name: Select token - id: auth - run: | - if [ "${{ steps.has-app.outputs.present }}" = "true" ]; then - echo "token=${{ steps.gh-app-token.outputs.token }}" >> "$GITHUB_OUTPUT" - else - echo "token=${{ github.token }}" >> "$GITHUB_OUTPUT" - fi - - - name: Checkout - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - name: Prepare pre-requisites uses: ./.github/actions/prepare with: token: ${{ steps.auth.outputs.token }} - name: Configure npm authentication for npm registry + env: + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} run: | - echo "//registry.npmjs.org/:_authToken=${{ secrets.NPM_TOKEN }}" >> ~/.npmrc + echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" >> ~/.npmrc - name: Install dependencies run: pnpm install diff --git a/.github/workflows/docker-prod.yaml b/.github/workflows/docker-prod.yaml index ee3f6038e..c658eab8f 100644 --- a/.github/workflows/docker-prod.yaml +++ b/.github/workflows/docker-prod.yaml @@ -10,7 +10,7 @@ on: # Prevent multiple production deployments from running simultaneously concurrency: group: production-deployment - cancel-in-progress: true + cancel-in-progress: false permissions: contents: read @@ -31,7 +31,7 @@ jobs: ROLE_TO_ASSUME: "arn:aws:iam::${{ secrets.RESEARCH_ACCOUNT_ID }}:role/GithubOIDCResearchAccountRole" steps: - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@4d991eb9b905ef189e4c376166672c3f2f230481 # v2.11.0 + uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0 with: egress-policy: audit @@ -58,7 +58,7 @@ jobs: platforms: "arm64" - name: Set up Docker Buildx - uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2 + uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0 - name: Set up AWS credentials via OIDC and role chaining uses: ./.github/actions/oidc @@ -137,7 +137,7 @@ jobs: id-token: write steps: - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@4d991eb9b905ef189e4c376166672c3f2f230481 # v2.11.0 + uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0 with: egress-policy: audit @@ -152,4 +152,4 @@ jobs: - name: AWS ECS force new deployment run: | - aws ecs update-service --cluster $ECS_CLUSTER --service $ECS_SERVICE --force-new-deployment --region $AWS_REGION + aws ecs update-service --cluster "$ECS_CLUSTER" --service "$ECS_SERVICE" --force-new-deployment --region "$AWS_REGION" diff --git a/.github/workflows/docker-stg.yaml b/.github/workflows/docker-stg.yaml index 6daf4475f..24093bff4 100644 --- a/.github/workflows/docker-stg.yaml +++ b/.github/workflows/docker-stg.yaml @@ -49,7 +49,7 @@ jobs: ROLE_TO_ASSUME: "arn:aws:iam::${{ secrets.RESEARCH_ACCOUNT_ID }}:role/GithubOIDCResearchAccountRole" steps: - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@4d991eb9b905ef189e4c376166672c3f2f230481 # v2.11.0 + uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0 with: egress-policy: audit @@ -62,7 +62,7 @@ jobs: platforms: "arm64" - name: Set up Docker Buildx - uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2 + uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0 - name: Set up AWS credentials via OIDC and role chaining uses: ./.github/actions/oidc @@ -143,7 +143,7 @@ jobs: id-token: write steps: - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@4d991eb9b905ef189e4c376166672c3f2f230481 # v2.11.0 + uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0 with: egress-policy: audit @@ -158,4 +158,4 @@ jobs: - name: AWS ECS force new deployment run: | - aws ecs update-service --cluster $ECS_CLUSTER --service $ECS_SERVICE --force-new-deployment --region $AWS_REGION + aws ecs update-service --cluster "$ECS_CLUSTER" --service "$ECS_SERVICE" --force-new-deployment --region "$AWS_REGION" diff --git a/.github/workflows/export-testing.yml b/.github/workflows/export-testing.yml index 804dbc191..92f6a7aed 100644 --- a/.github/workflows/export-testing.yml +++ b/.github/workflows/export-testing.yml @@ -11,6 +11,10 @@ on: pull_request: branches: [main] +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + permissions: contents: read @@ -31,32 +35,16 @@ jobs: with: egress-policy: audit - - name: Check if app creds exist (base repo only) - id: has-app - run: | - present=true - if [ "${{ github.event.pull_request.head.repo.fork || false }}" = "true" ]; then present=false; fi - if [ -z "${{ vars.GH_APP_ID }}" ] || [ -z "${{ secrets.GH_APP_PRIVATE_KEY }}" ]; then present=false; fi - echo "present=$present" >> "$GITHUB_OUTPUT" - - - uses: actions/create-github-app-token@af35edadc00be37caa72ed9f3e6d5f7801bfdf09 # v1.11.7 - id: gh-app-token - if: steps.has-app.outputs.present == 'true' + - name: Checkout + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + + - name: Resolve authentication token + id: auth + uses: ./.github/actions/auth-token with: app-id: ${{ vars.GH_APP_ID }} private-key: ${{ secrets.GH_APP_PRIVATE_KEY }} - - - name: Select token - id: auth - run: | - if [ "${{ steps.has-app.outputs.present }}" = "true" ]; then - echo "token=${{ steps.gh-app-token.outputs.token }}" >> "$GITHUB_OUTPUT" - else - echo "token=${{ github.token }}" >> "$GITHUB_OUTPUT" - fi - - - name: Checkout - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + is-fork: ${{ github.event.pull_request.head.repo.fork || false }} - name: Prepare pre-requisites uses: ./.github/actions/prepare @@ -64,8 +52,10 @@ jobs: token: ${{ steps.auth.outputs.token }} - name: Configure npm authentication for npm registry + env: + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} run: | - echo "//registry.npmjs.org/:_authToken=${{ secrets.NPM_TOKEN }}" >> ~/.npmrc + echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" >> ~/.npmrc - name: Install dependencies run: pnpm install @@ -119,32 +109,16 @@ jobs: with: egress-policy: audit - - name: Check if app creds exist (base repo only) - id: has-app - run: | - present=true - if [ "${{ github.event.pull_request.head.repo.fork || false }}" = "true" ]; then present=false; fi - if [ -z "${{ vars.GH_APP_ID }}" ] || [ -z "${{ secrets.GH_APP_PRIVATE_KEY }}" ]; then present=false; fi - echo "present=$present" >> "$GITHUB_OUTPUT" - - - uses: actions/create-github-app-token@af35edadc00be37caa72ed9f3e6d5f7801bfdf09 # v1.11.7 - id: gh-app-token - if: steps.has-app.outputs.present == 'true' + - name: Checkout + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + + - name: Resolve authentication token + id: auth + uses: ./.github/actions/auth-token with: app-id: ${{ vars.GH_APP_ID }} private-key: ${{ secrets.GH_APP_PRIVATE_KEY }} - - - name: Select token - id: auth - run: | - if [ "${{ steps.has-app.outputs.present }}" = "true" ]; then - echo "token=${{ steps.gh-app-token.outputs.token }}" >> "$GITHUB_OUTPUT" - else - echo "token=${{ github.token }}" >> "$GITHUB_OUTPUT" - fi - - - name: Checkout - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + is-fork: ${{ github.event.pull_request.head.repo.fork || false }} - name: Prepare pre-requisites uses: ./.github/actions/prepare @@ -152,8 +126,10 @@ jobs: token: ${{ steps.auth.outputs.token }} - name: Configure npm authentication for npm registry + env: + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} run: | - echo "//registry.npmjs.org/:_authToken=${{ secrets.NPM_TOKEN }}" >> ~/.npmrc + echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" >> ~/.npmrc - name: Install dependencies run: pnpm install @@ -163,7 +139,8 @@ jobs: env: NODE_OPTIONS: "--max-old-space-size=8192" - - name: Run packed export e2e test (${{ matrix.chain }}) - run: node apps/builder/src/export/cli/export-app.cjs export --env packed -c ${{ matrix.chain }} -o exports/ci-test-${{ matrix.chain }} + - name: Run packed export e2e test env: NODE_OPTIONS: "--max-old-space-size=8192" + CHAIN: ${{ matrix.chain }} + run: node apps/builder/src/export/cli/export-app.cjs export --env packed -c "$CHAIN" -o "exports/ci-test-$CHAIN" diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 955a9034d..05070a14c 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -7,6 +7,10 @@ on: pull_request: branches: [main] +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + permissions: contents: read @@ -22,32 +26,16 @@ jobs: with: egress-policy: audit - - name: Check if app creds exist (base repo only) - id: has-app - run: | - present=true - if [ "${{ github.event.pull_request.head.repo.fork || false }}" = "true" ]; then present=false; fi - if [ -z "${{ vars.GH_APP_ID }}" ] || [ -z "${{ secrets.GH_APP_PRIVATE_KEY }}" ]; then present=false; fi - echo "present=$present" >> "$GITHUB_OUTPUT" + - name: Checkout + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - uses: actions/create-github-app-token@af35edadc00be37caa72ed9f3e6d5f7801bfdf09 # v1.11.7 - id: gh-app-token - if: steps.has-app.outputs.present == 'true' + - name: Resolve authentication token + id: auth + uses: ./.github/actions/auth-token with: app-id: ${{ vars.GH_APP_ID }} private-key: ${{ secrets.GH_APP_PRIVATE_KEY }} - - - name: Select token - id: auth - run: | - if [ "${{ steps.has-app.outputs.present }}" = "true" ]; then - echo "token=${{ steps.gh-app-token.outputs.token }}" >> "$GITHUB_OUTPUT" - else - echo "token=${{ github.token }}" >> "$GITHUB_OUTPUT" - fi - - - name: Checkout Repo - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + is-fork: ${{ github.event.pull_request.head.repo.fork || false }} - name: Prepare pre-requisites uses: ./.github/actions/prepare @@ -55,8 +43,10 @@ jobs: token: ${{ steps.auth.outputs.token }} - name: Configure npm authentication for npm registry + env: + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} run: | - echo "//registry.npmjs.org/:_authToken=${{ secrets.NPM_TOKEN }}" >> ~/.npmrc + echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" >> ~/.npmrc - name: Install dependencies run: pnpm install diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index ca8bf99a7..ae6df08ac 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -25,20 +25,17 @@ jobs: security-events: write # Needed to publish results and get a badge (see publish_results below). id-token: write - # comment the permissions below if installing in a public repository. - # contents: read - # actions: read steps: - name: Harden Runner - uses: step-security/harden-runner@6c439dc8bdf85cadbbce9ed30d1c7b959517bc49 # v2.12.2 + uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0 with: egress-policy: audit - name: Checkout code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.5.4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false - name: Run analysis - uses: ossf/scorecard-action@05b42c624433fc40578a4040d5cf5e36ddca8cde # v2.4.2 + uses: ossf/scorecard-action@05b42c624433fc40578a4040d5cf5e36ddca8cde # v2.4.2 with: results_file: results.sarif results_format: sarif @@ -46,12 +43,12 @@ jobs: # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF # format to the repository Actions tab. - name: Upload artifact - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: name: SARIF file path: results.sarif retention-days: 5 - name: Upload SARIF to GitHub Code Scanning - uses: github/codeql-action/upload-sarif@51f77329afa6477de8c49fc9c7046c15b9a4e79d # v3.29.5 + uses: github/codeql-action/upload-sarif@51f77329afa6477de8c49fc9c7046c15b9a4e79d # v3.29.5 with: sarif_file: results.sarif diff --git a/.github/workflows/update-dependencies.yml b/.github/workflows/update-dependencies.yml index c8cf55bba..09b478464 100644 --- a/.github/workflows/update-dependencies.yml +++ b/.github/workflows/update-dependencies.yml @@ -15,30 +15,34 @@ jobs: update-deps: runs-on: ubuntu-latest permissions: - contents: read + contents: write + pull-requests: write steps: - name: Harden the runner (Audit all outbound calls) uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0 with: egress-policy: audit - - uses: actions/create-github-app-token@af35edadc00be37caa72ed9f3e6d5f7801bfdf09 # v1.11.7 - id: gh-app-token + - name: Checkout + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + + - name: Resolve authentication token + id: auth + uses: ./.github/actions/auth-token with: app-id: ${{ vars.GH_APP_ID }} private-key: ${{ secrets.GH_APP_PRIVATE_KEY }} - - name: Checkout Repo - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - name: Prepare pre-requisites uses: ./.github/actions/prepare with: - token: ${{ steps.gh-app-token.outputs.token }} + token: ${{ steps.auth.outputs.token }} - name: Configure npm authentication for npm registry + env: + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} run: | - echo "//registry.npmjs.org/:_authToken=${{ secrets.NPM_TOKEN }}" >> ~/.npmrc + echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" >> ~/.npmrc - name: Install dependencies run: pnpm install @@ -46,14 +50,14 @@ jobs: - name: Check for outdated dependencies id: outdated run: | - echo "OUTDATED_DEPS=$(pnpm outdated --format json)" >> $GITHUB_ENV + echo "OUTDATED_DEPS=$(pnpm outdated --format json)" >> "$GITHUB_ENV" continue-on-error: true - name: Create PR for dependency updates if: success() uses: peter-evans/create-pull-request@4e1beaa7521e8b457b572c090b25bd3db56bf1c5 # v5.0.3 with: - token: ${{ secrets.GITHUB_TOKEN }} + token: ${{ steps.auth.outputs.token }} commit-message: 'chore(deps): update dependencies' title: 'chore(deps): update dependencies' body: | From 26510ea285bf2e7321028b67c889f77e5e789781 Mon Sep 17 00:00:00 2001 From: Aleksandr Pasevin Date: Wed, 20 May 2026 17:49:58 +0300 Subject: [PATCH 2/3] fix(ci): drop redundant checkout from prepare composite The prepare composite was doing a second checkout on top of the one each workflow already runs. Removes it (and the now-unused token input) and drops the auth-token resolution from workflows that only needed it to feed prepare. update-dependencies keeps auth-token since it still feeds peter-evans/create-pull-request. Addresses review feedback on #337. Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/actions/prepare/action.yml | 12 ++---------- .github/workflows/check-versions.yml | 10 ---------- .github/workflows/ci.yml | 10 ---------- .github/workflows/coverage.yml | 10 ---------- .github/workflows/dependencies.yml | 9 --------- .github/workflows/docker-prod.yaml | 2 -- .github/workflows/export-testing.yml | 20 -------------------- .github/workflows/lint.yml | 10 ---------- .github/workflows/update-dependencies.yml | 2 -- 9 files changed, 2 insertions(+), 83 deletions(-) diff --git a/.github/actions/prepare/action.yml b/.github/actions/prepare/action.yml index 050675206..8fde488a3 100644 --- a/.github/actions/prepare/action.yml +++ b/.github/actions/prepare/action.yml @@ -1,20 +1,12 @@ --- name: Pre-requisites description: | - Setup Pre-requisites - -inputs: - token: - required: true + Setup pnpm, Node, and install workspace dependencies. Assumes the calling + workflow has already run actions/checkout. runs: using: composite steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - token: ${{ inputs.token }} - persist-credentials: true - - uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4.2.0 with: run_install: false diff --git a/.github/workflows/check-versions.yml b/.github/workflows/check-versions.yml index ab0c0a70a..126094afd 100644 --- a/.github/workflows/check-versions.yml +++ b/.github/workflows/check-versions.yml @@ -32,18 +32,8 @@ jobs: - name: Checkout uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - name: Resolve authentication token - id: auth - uses: ./.github/actions/auth-token - with: - app-id: ${{ vars.GH_APP_ID }} - private-key: ${{ secrets.GH_APP_PRIVATE_KEY }} - is-fork: ${{ github.event.pull_request.head.repo.fork || false }} - - name: Prepare pre-requisites uses: ./.github/actions/prepare - with: - token: ${{ steps.auth.outputs.token }} - name: Configure npm authentication for npm registry env: diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 272701167..a148a5565 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -35,18 +35,8 @@ jobs: - name: Checkout uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - name: Resolve authentication token - id: auth - uses: ./.github/actions/auth-token - with: - app-id: ${{ vars.GH_APP_ID }} - private-key: ${{ secrets.GH_APP_PRIVATE_KEY }} - is-fork: ${{ github.event.pull_request.head.repo.fork || false }} - - name: Prepare pre-requisites uses: ./.github/actions/prepare - with: - token: ${{ steps.auth.outputs.token }} - name: Configure npm authentication for npm registry env: diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index e990d123a..9de7332ce 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -30,18 +30,8 @@ jobs: - name: Checkout uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - name: Resolve authentication token - id: auth - uses: ./.github/actions/auth-token - with: - app-id: ${{ vars.GH_APP_ID }} - private-key: ${{ secrets.GH_APP_PRIVATE_KEY }} - is-fork: ${{ github.event.pull_request.head.repo.fork || false }} - - name: Prepare pre-requisites uses: ./.github/actions/prepare - with: - token: ${{ steps.auth.outputs.token }} - name: Configure npm authentication for npm registry env: diff --git a/.github/workflows/dependencies.yml b/.github/workflows/dependencies.yml index da1f88b11..0617e72e9 100644 --- a/.github/workflows/dependencies.yml +++ b/.github/workflows/dependencies.yml @@ -25,17 +25,8 @@ jobs: - name: Checkout uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - name: Resolve authentication token - id: auth - uses: ./.github/actions/auth-token - with: - app-id: ${{ vars.GH_APP_ID }} - private-key: ${{ secrets.GH_APP_PRIVATE_KEY }} - - name: Prepare pre-requisites uses: ./.github/actions/prepare - with: - token: ${{ steps.auth.outputs.token }} - name: Configure npm authentication for npm registry env: diff --git a/.github/workflows/docker-prod.yaml b/.github/workflows/docker-prod.yaml index c658eab8f..ee5f0f6c6 100644 --- a/.github/workflows/docker-prod.yaml +++ b/.github/workflows/docker-prod.yaml @@ -49,8 +49,6 @@ jobs: - name: Prepare pre-requisites uses: ./.github/actions/prepare - with: - token: ${{ steps.gh-app-token.outputs.token }} - name: Set up QEMU uses: docker/setup-qemu-action@29109295f81e9208d7d86ff1c6c12d2833863392 # v3.6.0 diff --git a/.github/workflows/export-testing.yml b/.github/workflows/export-testing.yml index 92f6a7aed..4094985f6 100644 --- a/.github/workflows/export-testing.yml +++ b/.github/workflows/export-testing.yml @@ -38,18 +38,8 @@ jobs: - name: Checkout uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - name: Resolve authentication token - id: auth - uses: ./.github/actions/auth-token - with: - app-id: ${{ vars.GH_APP_ID }} - private-key: ${{ secrets.GH_APP_PRIVATE_KEY }} - is-fork: ${{ github.event.pull_request.head.repo.fork || false }} - - name: Prepare pre-requisites uses: ./.github/actions/prepare - with: - token: ${{ steps.auth.outputs.token }} - name: Configure npm authentication for npm registry env: @@ -112,18 +102,8 @@ jobs: - name: Checkout uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - name: Resolve authentication token - id: auth - uses: ./.github/actions/auth-token - with: - app-id: ${{ vars.GH_APP_ID }} - private-key: ${{ secrets.GH_APP_PRIVATE_KEY }} - is-fork: ${{ github.event.pull_request.head.repo.fork || false }} - - name: Prepare pre-requisites uses: ./.github/actions/prepare - with: - token: ${{ steps.auth.outputs.token }} - name: Configure npm authentication for npm registry env: diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 05070a14c..1420d8fb1 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -29,18 +29,8 @@ jobs: - name: Checkout uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - name: Resolve authentication token - id: auth - uses: ./.github/actions/auth-token - with: - app-id: ${{ vars.GH_APP_ID }} - private-key: ${{ secrets.GH_APP_PRIVATE_KEY }} - is-fork: ${{ github.event.pull_request.head.repo.fork || false }} - - name: Prepare pre-requisites uses: ./.github/actions/prepare - with: - token: ${{ steps.auth.outputs.token }} - name: Configure npm authentication for npm registry env: diff --git a/.github/workflows/update-dependencies.yml b/.github/workflows/update-dependencies.yml index 09b478464..bd6740edc 100644 --- a/.github/workflows/update-dependencies.yml +++ b/.github/workflows/update-dependencies.yml @@ -35,8 +35,6 @@ jobs: - name: Prepare pre-requisites uses: ./.github/actions/prepare - with: - token: ${{ steps.auth.outputs.token }} - name: Configure npm authentication for npm registry env: From 3ed56a5af7f4d5a3955d3e320d41942945340fb7 Mon Sep 17 00:00:00 2001 From: Aleksandr Pasevin Date: Wed, 20 May 2026 18:03:13 +0300 Subject: [PATCH 3/3] revert(ci): leave e2e-export step body unchanged Matrix values aren't user-controllable, so the CHAIN env-var refactor is out of scope for the hardening PR. Restore the run line and step name to match main. Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/workflows/export-testing.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/export-testing.yml b/.github/workflows/export-testing.yml index 4094985f6..d2f9b1017 100644 --- a/.github/workflows/export-testing.yml +++ b/.github/workflows/export-testing.yml @@ -119,8 +119,7 @@ jobs: env: NODE_OPTIONS: "--max-old-space-size=8192" - - name: Run packed export e2e test + - name: Run packed export e2e test (${{ matrix.chain }}) + run: node apps/builder/src/export/cli/export-app.cjs export --env packed -c ${{ matrix.chain }} -o exports/ci-test-${{ matrix.chain }} env: NODE_OPTIONS: "--max-old-space-size=8192" - CHAIN: ${{ matrix.chain }} - run: node apps/builder/src/export/cli/export-app.cjs export --env packed -c "$CHAIN" -o "exports/ci-test-$CHAIN"