Skip to content

fix: add COPILOT_PROVIDER_* to strict-mode allowlist, skip token validation in BYOK mode, and document Copilot BYOK#29411

Merged
pelikhan merged 6 commits intomainfrom
copilot/docs-copilot-provider-variables
May 1, 2026
Merged

fix: add COPILOT_PROVIDER_* to strict-mode allowlist, skip token validation in BYOK mode, and document Copilot BYOK#29411
pelikhan merged 6 commits intomainfrom
copilot/docs-copilot-provider-variables

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented May 1, 2026

COPILOT_PROVIDER_* variables for Copilot BYOK (external LLM provider) mode were blocked by strict-mode validation and entirely undocumented, making it impossible to configure an external provider without warnings or errors. Additionally, the COPILOT_GITHUB_TOKEN validation step would incorrectly run even when a BYOK provider credential was configured.

Changes

  • Strict-mode allowlist (copilot_engine.go) — COPILOT_PROVIDER_BASE_URL, COPILOT_PROVIDER_API_KEY, and COPILOT_PROVIDER_BEARER_TOKEN added unconditionally to GetRequiredSecretNames. This lets ${{ secrets.* }} references for these keys pass strict-mode validation in engine.env and flow through FilterEnvForSecrets to the execution step.

  • BYOK token validation skip (copilot_engine_installation.go) — GetSecretValidationStep now returns an empty step (skipping COPILOT_GITHUB_TOKEN validation) when COPILOT_PROVIDER_API_KEY or COPILOT_PROVIDER_BEARER_TOKEN is present in engine.env. In BYOK mode the external provider handles authentication, so requiring a GitHub token would break BYOK-only workflows.

  • Helper (engine_helpers.go) — Added engineEnvHasKey helper for safely checking whether a key exists in engine.env.

  • Constants (engine_constants.go) — Named constants for the three BYOK secret-bearing env var names.

  • Tests (env_secrets_validation_test.go, secret_validation_test.go) — Five new cases covering each BYOK secret var individually, a full config, and mixed BYOK + unrelated secret (still fails); plus two cases verifying the validation skip when COPILOT_PROVIDER_API_KEY or COPILOT_PROVIDER_BEARER_TOKEN is set.

  • Docs (engines.md) — New "Copilot Bring Your Own Key (BYOK) Mode" section with full variable reference table and examples.

Example

engine:
  id: copilot
  env:
    COPILOT_PROVIDER_BASE_URL: ${{ secrets.PROVIDER_BASE_URL }}  # activates BYOK
    COPILOT_MODEL: claude-sonnet-4                                # required by most providers
    COPILOT_PROVIDER_API_KEY: ${{ secrets.PROVIDER_API_KEY }}    # cloud providers only
    # COPILOT_PROVIDER_TYPE: anthropic                           # default: openai

network:
  allowed:
    - defaults
    - your-provider-domain.example.com

Credentials are isolated in the AWF API proxy sidecar and do not reach the agent container. When COPILOT_PROVIDER_API_KEY or COPILOT_PROVIDER_BEARER_TOKEN is set, the COPILOT_GITHUB_TOKEN validation step is skipped automatically.

Copilot AI changed the title [WIP] Document COPILOT_PROVIDER_* variables and update allowlist fix: add COPILOT_PROVIDER_* to strict-mode allowlist and document Copilot BYOK mode May 1, 2026
Copilot AI requested a review from pelikhan May 1, 2026 00:30
@pelikhan pelikhan marked this pull request as ready for review May 1, 2026 00:31
@pelikhan pelikhan requested review from Copilot and lpcox May 1, 2026 00:31
@pelikhan
Copy link
Copy Markdown
Collaborator

pelikhan commented May 1, 2026

@copilot when the COPILOT_PROVIDER_API_KEY env var is set, do not attempt to validate the COPILOT_GITHUB_TOKEN in the validate step.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Enables Copilot BYOK (external provider) configuration by allowing COPILOT_PROVIDER_* secret-bearing variables through strict-mode validation, and documents how to use BYOK mode.

Changes:

  • Allowlists COPILOT_PROVIDER_BASE_URL, COPILOT_PROVIDER_API_KEY, and COPILOT_PROVIDER_BEARER_TOKEN in Copilot engine required secret names (to pass strict-mode env secret validation and env filtering).
  • Introduces named constants for the BYOK env var keys.
  • Adds strict-mode test cases covering the BYOK env vars and mixed allowed+disallowed secrets.
  • Documents Copilot BYOK mode, variables, and examples in engine reference docs.
Show a summary per file
File Description
pkg/workflow/copilot_engine.go Adds BYOK COPILOT_PROVIDER_* keys to the Copilot engine strict-mode/secret allowlist via GetRequiredSecretNames.
pkg/constants/engine_constants.go Defines constants for BYOK provider env var names.
pkg/workflow/env_secrets_validation_test.go Adds strict-mode tests validating the BYOK env vars are allowed (and unrelated secrets still fail).
docs/src/content/docs/reference/engines.md Adds a BYOK mode section with variable reference table and configuration examples.

Copilot's findings

Tip

Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comments suppressed due to low confidence (1)

docs/src/content/docs/reference/engines.md:254

  • This note says other COPILOT_PROVIDER_* variables “may also use ${{ secrets.* }} syntax”. With strict-mode validation, ${{ secrets.* }} references in engine.env are only permitted for the allowlisted credential keys; using secrets syntax for non-allowlisted provider config vars would still error. Please clarify (e.g., plain strings recommended; secrets syntax only works for the credential keys, or in non-strict mode).
> `COPILOT_PROVIDER_BASE_URL`, `COPILOT_PROVIDER_API_KEY`, and `COPILOT_PROVIDER_BEARER_TOKEN` are
> recognised as engine credentials and are allowed to carry `${{ secrets.* }}` references in
> `engine.env` without triggering the strict-mode "secrets in env" warning. Other
> `COPILOT_PROVIDER_*` variables (type, model, token limits) hold non-sensitive configuration and
> can be set as plain strings. They may also use `${{ secrets.* }}` syntax if you prefer to keep
  • Files reviewed: 4/4 changed files
  • Comments generated: 1


The Copilot engine supports routing requests to an external LLM provider instead of GitHub's default routing. This is useful when you want to use a different model or provider (e.g., OpenAI, Anthropic, Azure OpenAI, or a local Ollama/vLLM instance) while still using the Copilot CLI tooling.

Set `COPILOT_PROVIDER_BASE_URL` in `engine.env` to activate BYOK mode. All `COPILOT_PROVIDER_*` secret variables are allowed in `engine.env` under strict mode — they are not leaked to the agent container.
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 1, 2026

🧪 Test Quality Sentinel Report

Test Quality Score: 66/100

⚠️ Acceptable, with suggestions

Metric Value
New/modified tests analyzed 5 table-driven rows in TestValidateEngineEnvSecrets
✅ Design tests (behavioral contracts) 5 (100%)
⚠️ Implementation tests (low value) 0 (0%)
Tests with error/edge cases 1 (20%)
Duplicate test clusters 0
Test inflation detected ⚠️ Yes (77 test lines vs ~31 prod lines ≈ 2.5:1)
🚨 Coding-guideline violations None

Test Classification Details

View all 5 test rows
Test File Classification Issues Detected
engine.env with COPILOT_PROVIDER_BASE_URL secret is allowed in strict mode (BYOK) pkg/workflow/env_secrets_validation_test.go ✅ Design Happy path only
engine.env with COPILOT_PROVIDER_API_KEY secret is allowed in strict mode (BYOK) pkg/workflow/env_secrets_validation_test.go ✅ Design Happy path only
engine.env with COPILOT_PROVIDER_BEARER_TOKEN secret is allowed in strict mode (BYOK) pkg/workflow/env_secrets_validation_test.go ✅ Design Happy path only
engine.env with full BYOK config (URL + API key + model) is allowed in strict mode pkg/workflow/env_secrets_validation_test.go ✅ Design Happy path only
engine.env with BYOK vars and an unrelated secret still fails in strict mode pkg/workflow/env_secrets_validation_test.go ✅ Design ✅ Has error path

Suggestions (Non-blocking)

⚠️ Test Inflation

The test file gained 77 lines while the production code changed by ~31 lines (~2.5:1 ratio). This is mainly because each BYOK variable has its own individual test row. This is acceptable for clarity, but consider collapsing rows 1–3 (single-variable BYOK tests) into a single parameterized sub-table to reduce repetition.

⚠️ Low Edge-Case Coverage (20%)

Only 1 of 5 rows tests a failure path. Consider adding:

  • A row where a non-copilot engine uses a COPILOT_PROVIDER_* var in strict mode — should it be allowed or rejected?
  • A row where COPILOT_PROVIDER_BASE_URL is set to a plain string (not a secret expression) in strict mode — verifies the allowlist applies only when secrets are involved.

Language Support

Tests analyzed:

  • 🟨 JavaScript: 0 tests

Verdict

Check passed. 0% of new tests are implementation tests (threshold: 30%). All 5 new test rows verify observable behavioral contracts of the strict-mode allowlist. Minor improvement suggestions are non-blocking.


📖 Understanding Test Classifications

Design Tests (High Value) verify what the system does:

  • Assert on observable outputs, return values, or state changes
  • Cover error paths and boundary conditions
  • Would catch a behavioral regression if deleted
  • Remain valid even after internal refactoring

Implementation Tests (Low Value) verify how the system does it:

  • Assert on internal function calls (mocking internals)
  • Only test the happy path with typical inputs
  • Break during legitimate refactoring even when behavior is correct
  • Give false assurance: they pass even when the system is wrong

Goal: Shift toward tests that describe the system's behavioral contract — the promises it makes to its users and collaborators.

References: §25196318142

🧪 Test quality analysis by Test Quality Sentinel · ● 448.1K ·

Copy link
Copy Markdown
Contributor

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Test Quality Sentinel: 66/100. Test quality is acceptable — 0% of new tests are implementation tests (threshold: 30%). All 5 new BYOK test rows verify observable behavioral contracts. Minor non-blocking suggestions posted in the comment above.

…e allowlist

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 1, 2026

Commit pushed: 536acf1

🏗️ ADR gate enforced by Design Decision Gate 🏗️

…als are set

Agent-Logs-Url: https://github.com/github/gh-aw/sessions/d9b49ef2-5519-430d-a591-dadae0dae3ab

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented May 1, 2026

@copilot when the COPILOT_PROVIDER_API_KEY env var is set, do not attempt to validate the COPILOT_GITHUB_TOKEN in the validate step.

Done in d98f29b. GetSecretValidationStep now returns an empty step (skipping COPILOT_GITHUB_TOKEN validation) when either COPILOT_PROVIDER_API_KEY or COPILOT_PROVIDER_BEARER_TOKEN is present in engine.env, since in BYOK mode the external provider handles authentication. Added a small engineEnvHasKey helper and two new test cases covering both bearer token and API key variants.

Copilot AI changed the title fix: add COPILOT_PROVIDER_* to strict-mode allowlist and document Copilot BYOK mode fix: add COPILOT_PROVIDER_* to strict-mode allowlist, skip token validation in BYOK mode, and document Copilot BYOK May 1, 2026
@pelikhan
Copy link
Copy Markdown
Collaborator

pelikhan commented May 1, 2026

@copilot review all comments

…mode allowlisted

Agent-Logs-Url: https://github.com/github/gh-aw/sessions/84d354ca-8822-4976-8584-2ab664b36dc3

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented May 1, 2026

@copilot review all comments

Addressed in 736b55a — the docs now explicitly list the three allowlisted variables (COPILOT_PROVIDER_BASE_URL, COPILOT_PROVIDER_API_KEY, COPILOT_PROVIDER_BEARER_TOKEN) instead of implying an open-ended COPILOT_PROVIDER_* wildcard. All other review feedback was already addressed in earlier commits.

@pelikhan
Copy link
Copy Markdown
Collaborator

pelikhan commented May 1, 2026

…cluding BYOK constants

Agent-Logs-Url: https://github.com/github/gh-aw/sessions/5ed16059-c8f5-4d09-8d5d-00ad34f529f8

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented May 1, 2026

@copilot review https://github.com/github/gh-aw/actions/runs/25197657635/job/73882238664

Fixed in 8fdf765. The CI failure was TestGetRequiredSecretNames_Copilot/basic_secrets_without_MCP asserting exactly 1 secret, but our change unconditionally adds the 3 BYOK constants to GetRequiredSecretNames, making it 4. Updated the test to expect all 4 (COPILOT_GITHUB_TOKEN + the 3 BYOK keys) and verified locally — all tests in pkg/workflow pass.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • https://api.github.com/graphql
    • Triggering command: /usr/bin/gh /usr/bin/gh api graphql -f query=query($owner: String!, $name: String!) { repository(owner: $owner, name: $name) { hasDiscussionsEnabled } } -f owner=github -f name=gh-aw (http block)
  • https://api.github.com/repos/actions/ai-inference/git/ref/tags/v1
    • Triggering command: /usr/bin/gh gh api /repos/actions/ai-inference/git/ref/tags/v1 --jq [.object.sha, .object.type] | @tsv --noprofile (http block)
  • https://api.github.com/repos/actions/checkout/git/ref/tags/v3
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v3 --jq [.object.sha, .object.type] | @tsv (http block)
  • https://api.github.com/repos/actions/checkout/git/ref/tags/v5
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v5 --jq [.object.sha, .object.type] | @tsv (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v5 --jq [.object.sha, .object.type] | @tsv xterm-color (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v5 --jq [.object.sha, .object.type] | @tsv /ref/tags/v9 (http block)
  • https://api.github.com/repos/actions/checkout/git/ref/tags/v6
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v6 --jq [.object.sha, .object.type] | @tsv (http block)
  • https://api.github.com/repos/actions/github-script/git/ref/tags/v8
    • Triggering command: /usr/bin/gh gh api /repos/actions/github-script/git/ref/tags/v8 --jq [.object.sha, .object.type] | @tsv --show-toplevel (http block)
  • https://api.github.com/repos/actions/github-script/git/ref/tags/v9
    • Triggering command: /usr/bin/gh gh api /repos/actions/github-script/git/ref/tags/v9 --jq [.object.sha, .object.type] | @tsv set-url origin /snap/bin/bash (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/github-script/git/ref/tags/v9 --jq [.object.sha, .object.type] | @tsv --abbrev-ref HEAD /opt/pipx_bin/bash (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/github-script/git/ref/tags/v9 --jq [.object.sha, .object.type] | @tsv --abbrev-ref HEAD /usr/local/.ghcup/bin/bash (http block)
  • https://api.github.com/repos/actions/setup-go/git/ref/tags/v4
    • Triggering command: /usr/bin/gh gh api /repos/actions/setup-go/git/ref/tags/v4 --jq [.object.sha, .object.type] | @tsv --abbrev-ref HEAD /snap/bin/bash (http block)
  • https://api.github.com/repos/actions/setup-node/git/ref/tags/v4
    • Triggering command: /usr/bin/gh gh api /repos/actions/setup-node/git/ref/tags/v4 --jq [.object.sha, .object.type] | @tsv (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/setup-node/git/ref/tags/v4 --jq [.object.sha, .object.type] | @tsv set-url origin /opt/hostedtoolcache/go/1.25.8/x64/bin/bash (http block)
  • https://api.github.com/repos/actions/setup-node/git/ref/tags/v6
    • Triggering command: /usr/bin/gh gh api /repos/actions/setup-node/git/ref/tags/v6 --jq [.object.sha, .object.type] | @tsv (http block)
  • https://api.github.com/repos/actions/upload-artifact/git/ref/tags/v4
    • Triggering command: /usr/bin/gh gh api /repos/actions/upload-artifact/git/ref/tags/v4 --jq [.object.sha, .object.type] | @tsv (http block)
  • https://api.github.com/repos/github/gh-aw-actions/git/ref/tags/v0.1.2
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw-actions/git/ref/tags/v0.1.2 --jq [.object.sha, .object.type] | @tsv set-url origin /home/REDACTED/.config/composer/vendor/bin/bash (http block)
  • https://api.github.com/repos/github/gh-aw-actions/git/ref/tags/v1.0.0
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw-actions/git/ref/tags/v1.0.0 --jq [.object.sha, .object.type] | @tsv riables^{commit} (http block)
  • https://api.github.com/repos/github/gh-aw-actions/git/ref/tags/v1.2.3
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw-actions/git/ref/tags/v1.2.3 --jq [.object.sha, .object.type] | @tsv (http block)
  • https://api.github.com/repos/github/gh-aw/git/ref/tags/v0.47.4
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v0.47.4 --jq [.object.sha, .object.type] | @tsv --show-toplevel (http block)
  • https://api.github.com/repos/github/gh-aw/git/ref/tags/v1.0.0
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v1.0.0 --jq [.object.sha, .object.type] | @tsv (http block)
  • https://api.github.com/repos/nonexistent/action/git/ref/tags/v999.999.999
    • Triggering command: /usr/bin/gh gh api /repos/nonexistent/action/git/ref/tags/v999.999.999 --jq [.object.sha, .object.type] | @tsv (http block)

If you need me to access, download, or install something from one of these locations, you can either:

@pelikhan pelikhan merged commit 0952fa8 into main May 1, 2026
@pelikhan pelikhan deleted the copilot/docs-copilot-provider-variables branch May 1, 2026 01:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

docs: COPILOT_PROVIDER_* variables not documented and strict-mode allowlist not updated

3 participants