# e2e: scope copilot GitHub token to the copilot-cli agent only

`eb32a04`→[main](/content/gh/entireio/cli/commits/main/index.html)·

Soph·2w ago·3 files·+31 added/-7 removed

The E2E workflows that run agents in a shared/single job were handing the
copilot GitHub token to every agent. A third-party agent CLI (opencode,
gemini-cli, cursor-cli, factoryai-droid, codex) would receive a usable
GitHub token in its process environment — credentials it has no need for.

Fix, without reverting the single-matrix design:
- e2e.yml, e2e-checkpoint-store.yml: COPILOT_GITHUB_TOKEN is now set only for
the copilot-cli matrix leg (`matrix.agent == 'copilot-cli' && github.token
|| ''`), in both the bootstrap and test steps.
- e2e-isolated.yml: same per-agent guard on the COPILOT_GITHUB_TOKEN secret
(`inputs.agent == 'copilot-cli' && secrets.COPILOT_GITHUB_TOKEN || ''`).
- e2e.yml, e2e-checkpoint-store.yml: checkout now runs with
persist-credentials: false so the copilot-scoped GITHUB_TOKEN isn't left in
.git/config for an agent process to read. (The job-level
`copilot-requests: write` permission must stay — GitHub does not allow matrix
expressions in `permissions:` — but the token is no longer reachable by
non-copilot agents via env or disk.)

e2e-checkpoints-v2.yml already compartmentalizes copilot in its own
copilot-cli-only job, so it needs no change.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

## Changes

3

- .github/workflows
   
   - Me2e-checkpoint-store.yml+13/-3
   
   - Me2e-isolated.yml+4/-2
   
   - Me2e.yml+14/-2

```
55 unmodified lines

permissions:
  actions: read
  contents: read
  # Granted for every leg so copilot-cli works in the matrix; harmless for others.
  # Needed by the copilot-cli leg. GitHub does not allow matrix expressions in
  # `permissions:`, so this scope is granted to every leg's GITHUB_TOKEN. The
  # token is kept away from non-copilot agents in two ways: it is only placed
  # in COPILOT_GITHUB_TOKEN for the copilot-cli leg (see env blocks below), and
  # checkout runs with persist-credentials: false so it is not left in
  # .git/config for an agent process to read.
  copilot-requests: write
strategy:
  fail-fast: false
```

```yaml
- name: Checkout repository
  uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
  with:
    # Don't persist the (copilot-scoped) GITHUB_TOKEN in .git/config, where
    # an agent process running in the checkout could read it.
    persist-credentials: false
```

```yaml
- name: Install system dependencies
  run: |
    OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
    CURSOR_API_KEY: ${{ secrets.CURSOR_API_KEY }}
    FACTORY_API_KEY: ${{ secrets.FACTORY_API_KEY }}
    COPILOT_GITHUB_TOKEN: ${{ github.token }}
    # Only the copilot-cli leg gets the token; other agents must not receive it.
    COPILOT_GITHUB_TOKEN: ${{ matrix.agent == 'copilot-cli' && github.token || '' }}
    run: go run ./e2e/bootstrap ${{ matrix.agent }}
```

```yaml
- name: Run isolated test
  run: |
    E2E_CODEX_MODEL: ${{ inputs.agent == 'codex' && 'gpt-5.4-mini' || '' }}
    CURSOR_API_KEY: ${{ secrets.CURSOR_API_KEY }}
    FACTORY_API_KEY: ${{ secrets.FACTORY_API_KEY }}
    COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
    # Only copilot-cli gets the token; other agents must not receive it.
    COPILOT_GITHUB_TOKEN: ${{ inputs.agent == 'copilot-cli' && secrets.COPILOT_GITHUB_TOKEN || '' }}
    E2E_ARTIFACT_DIR: ${{ github.workspace }}/e2e-artifacts
    E2E_ENTIRE_BIN: /usr/local/bin/entire
    run: |
```

The above content has been cleaned according to the specified requirements.
