From b3e7ab5c54e2454ad16d2b91a4088bc4712dd5c7 Mon Sep 17 00:00:00 2001 From: Demetris Tsadiotis Date: Thu, 30 Jul 2026 17:18:50 +0300 Subject: [PATCH 1/2] ci: move workflows to GitHub-hosted runners and pin actions to SHAs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Hardening pass now that the repo is public. Three workflows (codex-parity, validate-codex-plugin, validate-cursor-plugin) trigger on pull_request and execute scripts from the PR's own tree. On a public repo with forking enabled that means any fork author could get code execution on a persistent, shared self-hosted runner — the same fleet that runs the jobs holding FASTEDGE_APP_PRIVATE_KEY, ANTHROPIC_API_KEY and OPENAI_API_KEY. All five workflows now run on ubuntu-latest. External actions are pinned to commit SHAs; create-github-app-token@v1 was a mutable major tag with access to the GitHub App private key. Each pin resolves to the commit its tag already pointed at, so no version change: checkout v6.1.0, setup-node v6.5.0, create-github-app-token v1.12.0. The three pull_request checkouts also set persist-credentials: false so untrusted PR code cannot read the token out of .git/config. --- .github/setup-node/action.yaml | 2 +- .github/workflows/codex-parity.yaml | 5 +++-- .github/workflows/release-plugin.yaml | 8 ++++---- .github/workflows/sync-reference-docs.yaml | 6 +++--- .github/workflows/validate-codex-plugin.yaml | 6 ++++-- .github/workflows/validate-cursor-plugin.yaml | 6 ++++-- 6 files changed, 19 insertions(+), 14 deletions(-) diff --git a/.github/setup-node/action.yaml b/.github/setup-node/action.yaml index 99a1eaa..fb61966 100644 --- a/.github/setup-node/action.yaml +++ b/.github/setup-node/action.yaml @@ -10,6 +10,6 @@ runs: using: "composite" steps: - name: Use Node.js ${{ inputs.node_version }} - uses: actions/setup-node@v6 + uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6.5.0 with: node-version: ${{ inputs.node_version }} diff --git a/.github/workflows/codex-parity.yaml b/.github/workflows/codex-parity.yaml index 580c8a7..c5b832d 100644 --- a/.github/workflows/codex-parity.yaml +++ b/.github/workflows/codex-parity.yaml @@ -18,14 +18,15 @@ permissions: jobs: codex-parity: - runs-on: [self-hosted, ubuntu-22-04, regular] + runs-on: ubuntu-latest if: ${{ !contains(github.event.pull_request.labels.*.name, 'skip-codex-parity') }} steps: - name: Checkout - uses: actions/checkout@v6 + uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.1.0 with: fetch-depth: 0 + persist-credentials: false - name: Check Codex parity run: bash scripts/check-codex-parity.sh "${{ github.event.pull_request.base.sha }}" "${{ github.sha }}" diff --git a/.github/workflows/release-plugin.yaml b/.github/workflows/release-plugin.yaml index 525a26d..c9fa60d 100644 --- a/.github/workflows/release-plugin.yaml +++ b/.github/workflows/release-plugin.yaml @@ -48,17 +48,17 @@ concurrency: jobs: release: - runs-on: [self-hosted, ubuntu-22-04, regular] + runs-on: ubuntu-latest steps: - name: Generate GitHub App token (this repo) id: app-token - uses: actions/create-github-app-token@v1 + uses: actions/create-github-app-token@d72941d797fd3113feb6b93fd0dec494b13a2547 # v1.12.0 with: app-id: ${{ secrets.FASTEDGE_APP_ID }} private-key: ${{ secrets.FASTEDGE_APP_PRIVATE_KEY }} - name: Checkout main - uses: actions/checkout@v6 + uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.1.0 with: fetch-depth: 0 ref: main @@ -179,7 +179,7 @@ jobs: - name: Generate cross-repo token for MCP server if: steps.detect.outputs.changed == 'true' || inputs.force == true id: mcp-token - uses: actions/create-github-app-token@v1 + uses: actions/create-github-app-token@d72941d797fd3113feb6b93fd0dec494b13a2547 # v1.12.0 with: app-id: ${{ secrets.FASTEDGE_APP_ID }} private-key: ${{ secrets.FASTEDGE_APP_PRIVATE_KEY }} diff --git a/.github/workflows/sync-reference-docs.yaml b/.github/workflows/sync-reference-docs.yaml index 7258683..0603f77 100644 --- a/.github/workflows/sync-reference-docs.yaml +++ b/.github/workflows/sync-reference-docs.yaml @@ -61,18 +61,18 @@ env: jobs: sync-reference-docs: - runs-on: [self-hosted, ubuntu-22-04, regular] + runs-on: ubuntu-latest steps: - name: Checkout plugin repo - uses: actions/checkout@v6 + uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.1.0 with: fetch-depth: 0 ref: ${{ github.ref }} - name: Generate GitHub App token id: app-token - uses: actions/create-github-app-token@v1 + uses: actions/create-github-app-token@d72941d797fd3113feb6b93fd0dec494b13a2547 # v1.12.0 with: app-id: ${{ secrets.FASTEDGE_APP_ID }} private-key: ${{ secrets.FASTEDGE_APP_PRIVATE_KEY }} diff --git a/.github/workflows/validate-codex-plugin.yaml b/.github/workflows/validate-codex-plugin.yaml index 0945c27..45178c0 100644 --- a/.github/workflows/validate-codex-plugin.yaml +++ b/.github/workflows/validate-codex-plugin.yaml @@ -27,11 +27,13 @@ permissions: jobs: validate-codex-plugin: - runs-on: [self-hosted, ubuntu-22-04, regular] + runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v6 + uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.1.0 + with: + persist-credentials: false - name: Setup Node.js uses: ./.github/setup-node diff --git a/.github/workflows/validate-cursor-plugin.yaml b/.github/workflows/validate-cursor-plugin.yaml index 2c653a3..2e2377c 100644 --- a/.github/workflows/validate-cursor-plugin.yaml +++ b/.github/workflows/validate-cursor-plugin.yaml @@ -26,11 +26,13 @@ permissions: jobs: validate-cursor-plugin: - runs-on: [self-hosted, ubuntu-22-04, regular] + runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v6 + uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.1.0 + with: + persist-credentials: false - name: Setup Node.js uses: ./.github/setup-node From fc2e33c8e274c5ba2339f4c9f3b81ec389a554da Mon Sep 17 00:00:00 2001 From: Demetris Tsadiotis Date: Thu, 30 Jul 2026 17:47:43 +0300 Subject: [PATCH 2/2] ci: scope sync-reference-docs secrets to the steps that need them MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ANTHROPIC_API_KEY and OPENAI_API_KEY were set at workflow level, putting them in the environment of every step — including actions/checkout, create-github-app-token and the composite setup-node action. They are only read by invoke-agent.sh, so they now live on the Sync reference docs step. The App token was written to $GITHUB_ENV, which persists it into every later step's environment for the rest of the job. It is now passed per step to the three that actually use it: Validate sources.json (validate-sources.sh calls gh api), Configure git credentials (gh auth setup-git), and Sync reference docs (fetch-repo.sh, manage-pr.sh and the git push via the gh credential helper). Checkout, token generation, Setup Node.js and Install Claude CLI now run with no secrets in scope. --- .github/workflows/sync-reference-docs.yaml | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/sync-reference-docs.yaml b/.github/workflows/sync-reference-docs.yaml index 0603f77..935c761 100644 --- a/.github/workflows/sync-reference-docs.yaml +++ b/.github/workflows/sync-reference-docs.yaml @@ -14,8 +14,8 @@ name: Sync Reference Docs # FASTEDGE_APP_ID — GitHub App numeric ID (fastedge-plugin-sync) # FASTEDGE_APP_PRIVATE_KEY — GitHub App private key (.pem) # Token generated via actions/create-github-app-token@v1 -# and exported as GH_TOKEN for all steps (validate, -# fetch, PR creation/updates, baseline tag pushes) +# and passed as GH_TOKEN to the steps that need it +# (validate, git credentials, sync). on: workflow_dispatch: @@ -55,10 +55,6 @@ permissions: contents: write # push annotated baseline tags + PR branch commits pull-requests: write # create / edit PRs via gh CLI -env: - ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} - OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} - jobs: sync-reference-docs: runs-on: ubuntu-latest @@ -77,13 +73,14 @@ jobs: app-id: ${{ secrets.FASTEDGE_APP_ID }} private-key: ${{ secrets.FASTEDGE_APP_PRIVATE_KEY }} - - name: Export token for gh CLI - run: echo "GH_TOKEN=${{ steps.app-token.outputs.token }}" >> "$GITHUB_ENV" - - name: Validate sources.json + env: + GH_TOKEN: ${{ steps.app-token.outputs.token }} run: bash scripts/sync/validate-sources.sh sources.json - name: Configure git credentials + env: + GH_TOKEN: ${{ steps.app-token.outputs.token }} run: gh auth setup-git - name: Setup Node.js @@ -94,6 +91,9 @@ jobs: - name: Sync reference docs env: + GH_TOKEN: ${{ steps.app-token.outputs.token }} + ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} # workflow_dispatch inputs (empty for repository_dispatch) DRY_RUN: ${{ inputs.dry_run || 'false' }} FORCE_RUN: ${{ inputs.force_run || 'false' }}