Repository navigation
Agentic session (COPILOT_AGENT_SESSION_ID) makes az account get-access-token launch interactive browser login on silent-token failure #34211
Description
Describe the bug
With a non-empty COPILOT_AGENT_SESSION_ID, which Copilot agent hosts set for the shells they start, any UserCredential.acquire_token call whose silent result makes check_result raise AuthenticationError enters the interactive authentication fallback, even for non-SSH requests such as az account get-access-token. Without the variable, the same failure returns the error and an az login hint.
Cause, in src/azure-cli-core/azure/cli/core/auth/msal_credentials.py, UserCredential.acquire_token:
- The agentic-session block (added with
agentic_session.py) always setskwargs["data"]["client_session"] = agentic_session_id. - On
AuthenticationError, the existing fallback uses'data' in kwargsto detect VM SSH (az ssh):if 'data' in kwargs: logger.warning(ex) result = self._acquire_token_interactive(scopes, **kwargs) else: raise
az account get-access-tokenreaches this throughProfile.get_raw_token, which callscred.acquire_token(scopes)withoutdata. Agentic mode now always populatesdata, so this branch fires for any such failing request. The code's own comment says non-SSH scenarios should "not launch browser, but show the error message andaz logincommand instead."
This code is unchanged on the current dev branch.
Impact in practice: tools that shell out to az run it non-interactively with a timeout; here that was .NET Azure.Identity 1.21.0 AzureCliCredential via DefaultAzureCredential. Each affected failing call attempts interactive authentication and opens a browser sign-in tab. When the SDK times out it kills the process it launched, but the Python process kept running (PPID 1) with a 127.0.0.1 listening socket (see Additional context). A test suite making five such calls per run left orphans in bursts of five; we found 55 orphaned az account get-access-token Python processes on one machine.
Related command
az account get-access-token --output json --resource https://cognitiveservices.azure.com --tenant <tenant-id>
(this is exactly what Azure.Identity's AzureCliCredential runs)
Errors
With COPILOT_AGENT_SESSION_ID unset, the command fails fast as expected:
ERROR: AADSTS530004: AcceptCompliantDevice setting isn't configured for this organization. The admin needs to configure this setting to allow external users access to protected resources. ...
Run the command below to authenticate interactively; additional arguments may be added as needed:
az logout
az login --tenant "<tenant-id>" --scope "https://cognitiveservices.azure.com/.default"
With it set, the command does not exit with the authentication error. It logs the error as a warning and enters interactive authentication. With BROWSER=/usr/bin/true the process stayed running with a Python LISTEN socket on 127.0.0.1:<port>; without it, the default browser opens a sign-in page.
Issue script & Debug output
Repro needs a signed-in user account for which silent token acquisition fails in the target tenant (e.g. a guest/external account blocked by Conditional Access, or any interaction_required / MFA claims case). BROWSER=/usr/bin/true stops a real browser opening but still shows the interactive flow starting.
TENANT='<tenant-id>' # replace with a real tenant ID
R=https://cognitiveservices.azure.com
# 1. Expected behaviour: fails immediately with AADSTS... and the `az login` hint
env -u COPILOT_AGENT_SESSION_ID az account get-access-token --resource $R --tenant $TENANT
# 2. Bug: starts interactive auth-code flow and hangs
COPILOT_AGENT_SESSION_ID=test BROWSER=/usr/bin/true \
az account get-access-token --resource $R --tenant $TENANT --debug
# in another shell: lsof -nP -iTCP -sTCP:LISTEN | grep -i python -> 127.0.0.1:<port>Expected behavior
Agentic-session mode should not change the failure behaviour. A failed silent token request outside az ssh should raise the AuthenticationError with the az login hint, exactly as without COPILOT_AGENT_SESSION_ID. In particular, az account get-access-token, which is called by SDK credentials in non-interactive contexts, should never open a browser.
Suggested fix: detect the SSH case explicitly instead of relying on 'data' in kwargs. The SSH path supplies a data dict containing token_type: "ssh-cert" (plus req_cnf and key_id), so the fallback could check (kwargs.get("data") or {}).get("token_type") == "ssh-cert". A smaller fix is to record whether the caller supplied data before the agentic block adds client_session, though that keeps the older, broader heuristic.
Environment Summary
azure-cli 2.90.0 (Homebrew)
msal 1.36.0
Python 3.14.7
OS macOS 27.0.1 (arm64)
COPILOT_AGENT_SESSION_ID set by the GitHub Copilot agent host
Additional context
- Related, separate: Homebrew's
azwrapper (.../bin/az) runspython -Im azure.cli "$@"withoutexec, which adds a shell process between the caller and Python. Terminating only that shell can leave Python running. .NET Azure.Identity launches az through/bin/sh -cand callsProcess.Kill()without killing the process tree, which is what we observed. Usingexecin the wrapper would remove this layer, though full cleanup also depends on how the caller launches and terminates the process. - Workaround for affected users: unset
COPILOT_AGENT_SESSION_IDfor SDK/test processes, or make sure the defaultazaccount can get tokens silently for the tenants it is asked about.
Activity
yonzhan commentedon Oct 11, 2026
Thank you for opening this issue, we will look into it.
3 remaining items
isra-fel commentedon Oct 13, 2026
Not intended for get-access-token to pop up browser - will repro first.
microsoft-github-policy-service commentedon Oct 13, 2026
🔔 Routing this issue to @Azure/act-identity-squad.
microsoft-github-policy-service commentedon Oct 13, 2026
🔔 Routing this issue to @Azure/act-observability-squad.
isra-fel commentedon Oct 13, 2026
Though I couldn't reproduce this easily (requires a tenant that could trigger a MFA failure) the root cause analysis looks legit to me. Thanks for reporting!
microsoft-github-policy-service commentedon Oct 14, 2026
🔔 Routing this issue to @Azure/act-identity-squad.
microsoft-github-policy-service commentedon Oct 14, 2026
🔔 Routing this issue to @Azure/act-identity-squad.
x-engineering-agent commentedon Oct 14, 2026
X Engineering Agent Bug Analysis
Confidence: Low (0.40)
Summary
In an agentic session, failed non-SSH access-token acquisition enters browser authentication instead of preserving AuthenticationError and login guidance.
Likely root cause
Agent-session metadata creates kwargs[data], invalidating the data-presence heuristic used to recognize SSH-certificate requests in the AuthenticationError fallback.
Affected code
src/azure-cli-core/azure/cli/core/auth/msal_credentials.py›UserCredential.acquire_tokensrc/azure-cli-core/azure/cli/core/_profile.py›Profile.get_raw_token(line 418)src/azure-cli-core/azure/cli/core/auth/tests/test_agentic_session.py›TestUserCredentialAgenticSessionRuled out
Proposed change
Identify SSH certificate requests by the explicit token_type=ssh-cert marker rather than data presence. Preserve agent-session metadata, broker claims, cache behavior, genuine SSH interactive fallback and ordinary AuthenticationError/login guidance.
Workaround
Unset COPILOT_AGENT_SESSION_ID only for affected SDK/test subprocesses when acceptable; this avoids the mistaken fallback but does not fix the underlying authentication failure.
Technical details
Evidence
Test plan
Add mocked failure-path tests in auth/tests/test_agentic_session.py: session unset/set, broker off/on, ordinary and unrelated data must propagate AuthenticationError without interactive calls; explicit SSH certificate data must retain fallback. Assert metadata and guidance, and cover Profile.get_raw_token failure. No Azure recordings are needed for these deterministic credential-unit regressions; tenant-specific live behavior remains unverified.
Generated code: Handwritten code. The root cause is azure-cli-core/auth/msal_credentials.py, outside generated AAZ output.
Out of scope: Homebrew wrapper exec semantics and SDK process-tree cleanup are separate changes.
Live reproduction (BAMI sandbox) — Inconclusive
Verdict: Inconclusive: the sandbox could not run the reproduction to the end.
Reason: the sandbox identity cannot sign in to or access the resources involved.
The analysis above is based on reading the code only, so its confidence is capped at low.
Commands ran in an isolated Azure sandbox subscription from a validated ReproSpec; output is redacted.
Posted by x-engineering-agent (Fixer)