Repository navigation
Reject unwireable cross-job provider-env macros on engine.env (follow-up to #1372) #1375
Description
Follow-up to #1372.
#1372 is fixed by adding the typed engine.provider (BYOK) block with compiler-owned in-job Azure CLI token minting: a same-job secret AW_PROVIDER_BEARER_TOKEN is wired into COPILOT_PROVIDER_API_KEY (the credential env var the AWF api-proxy sidecar actually reads and forwards as Authorization: Bearer <value>), so a Foundry token resolves at runtime. That change is additive: the raw engine.env COPILOT_PROVIDER_* passthrough (including the broken cross-job $(Setup.FOUNDRY_TOKEN) macro) still compiles.
This issue tracks two deferred hardenings of the legacy raw engine.env provider path (both out of scope for the additive #1372 fix, both low urgency since engine.provider is now the sanctioned surface).
1. Reject the unwireable cross-job $(<Job>.<Var>) macro
Reject the cross-job output-macro form on raw engine.env provider keys at compile time, with an actionable error pointing users to engine.provider (or a same-job / pipeline / variable-group $(VAR) secret).
Scope:
- In
validate_engine_env_entry(src/engine.rs), for provider-expr keys, classify the macro: allow single-identifier$(VAR)(resolves same-job/pipeline), reject dotted cross-job$(a.b)(never resolves in a stepenv:block -> empty -> managed-identity 403). - Keep
${{ }}/$[...]/##vso[rejections unchanged. - Tests + docs note.
Explicitly NOT a codemod: rewriting the old $(Setup.*) + setup: mint pattern into engine.provider would require parsing an arbitrary inline az bash script (fragile, cannot produce a complete block); there is no live in-repo usage; and the pattern is already runtime-broken. The compile-time error is the migration nudge.
2. Drop COPILOT_PROVIDER_BEARER_TOKEN from the raw-env allowlist
The AWF api-proxy sidecar (which ado-aw always enables for BYOK) has no COPILOT_PROVIDER_BEARER_TOKEN concept — its BYOK credential is read exclusively from COPILOT_PROVIDER_API_KEY (verified against AWF v0.27.9 containers/api-proxy/providers/copilot.js + provider-env-constants.js, whose COPILOT_ENV lists only GITHUB_TOKEN, PROVIDER_API_KEY, PROVIDER_TYPE, PROVIDER_BASE_URL, API_TARGET, API_BASE_PATH).
Yet COPILOT_PROVIDER_BEARER_TOKEN is still listed in COPILOT_PROVIDER_EXPR_ENV_KEYS and COPILOT_BYOM_CREDENTIAL_ENV_KEYS (src/engine.rs) — carried over from #1264. A user who sets COPILOT_PROVIDER_BEARER_TOKEN directly in engine.env would have it --exclude-env'd from the container (so no leak) but never consumed by the sidecar -> silently unauthenticated (same 403 class). The engine.provider.token path was corrected to plumb COPILOT_PROVIDER_API_KEY instead; the raw-env allowlist should follow.
Scope:
- Remove
COPILOT_PROVIDER_BEARER_TOKENfromCOPILOT_PROVIDER_EXPR_ENV_KEYSandCOPILOT_BYOM_CREDENTIAL_ENV_KEYS(src/engine.rs), so the raw-env path only advertises the keys the sidecar actually reads. - If retained for any non-sidecar/direct-CLI edge case, at minimum document that it is inert through the api-proxy and emit a warning.
- Update
docs/engine.md+site/.../engine.mdx(theengine.envexception note currently listsCOPILOT_PROVIDER_BEARER_TOKEN) and tests.
Activity
github-actions commentedon Jul 6, 2026
🏷️ Triaged
Labeled as enhancement, rust, agentic-workflows.
Why: This is a planned compile-time guardrail addition (not a regression) that adds validation logic to
validate_engine_env_entryinsrc/engine.rsto reject unwireable cross-job$(a.b)macro forms on provider-env keys — scoped Rust compiler work that directly affectsengine.envfront-matter authoring behavior.Automated triage — a maintainer can adjust labels anytime.
feat(engine): add engine.provider (BYOK) with in-job Azure CLI token …