This is a fake badge that only works on one guarded door but opens the room full of developer secrets
CVE-2026-46354 is a signature-verification flaw in Coder's Azure instance identity flow. In affected releases, azureidentity.Validate() checks whether the signer chains to a trusted Azure certificate but fails to verify that the PKCS#7 signature actually protects the payload, so an attacker can tamper with content like a target vmId and still get a valid workspace-agent session token. The authoritative affected v2 ranges are all versions before 2.24.5, 2.29.0 before 2.29.13, 2.30.0 before 2.30.8, 2.31.0 before 2.31.12, 2.32.0-rc.0 before 2.32.2, and 2.33.0-rc.0 before 2.33.3.
In a vacuum this looks CRITICAL because the endpoint is unauthenticated and the follow-on impact is credential theft into source control and external auth providers. In real enterprises, the exposure population is materially smaller: the target must be a Coder deployment, on Azure, using azure-instance-identity for workspace agents, with the relevant API reachable, and the attacker still needs a target vmId. That friction is enough to pull it down from headline criticality, but not low enough to make it routine backlog work because successful exploitation hands over high-value developer secrets.
4 steps from start to impact.
Find a reachable Coder server using Azure agent identity
POST /api/v2/workspaceagents/azure-instance-identity path. Practical tooling is simple HTTP recon with curl plus fingerprinting from public app metadata, login pages, or prior knowledge of the target's developer platform. The bug does not matter if the deployment uses token auth instead of Azure instance identity.- Target runs Coder in an affected version range
- Target has Azure-backed workspaces using
azure-instance-identity - Relevant API path is reachable from the attacker position
- Many enterprises do not run Coder at all
- Many Coder deployments are not on Azure or do not use
azure-instance-identity - Internal-only Coder deployments remove direct unauthenticated internet reachability
Obtain a valid-looking Azure certificate and target vmId
vmId, which is a UUIDv4. That requirement is real friction because it usually implies prior visibility into the target environment, leaked logs, SSRF/log access, or another foothold.- Attacker can source an Azure IMDS signing certificate
- Attacker knows or can infer the target workspace VM's
vmId
vmIdis not guessable at internet scale- Enterprises with good log hygiene and secret handling make
vmIddiscovery less likely
vmId often blends into prior compromise telemetry.Forge the PKCS#7 envelope and request an agent token
- Affected server version
- Forged request reaches the vulnerable endpoint
- Victim
vmIdmatches an active or relevant workspace agent
- WAFs or API gateways restricting the endpoint can block direct abuse
- Non-Azure or token-based agent auth removes this path entirely
/api/v2/workspaceagents/azure-instance-identity; most generic vuln scanners will miss the exploit chain unless they understand Coder's Azure auth flow.Cash out with agent APIs for secrets and code access
curl or any REST client against documented API paths, and the blast radius can extend into source code repos and CI/CD-connected services under the workspace owner's identity.- Stolen agent token is valid
- Workspace has external auth, Git keys, or secrets configured
- Some workspaces may have minimal secrets or no external auth integration
- Short-lived tokens and rapid secret rotation reduce dwell time
/workspaceagents/me/gitsshkey and /workspaceagents/me/external-auth; EDR on developer endpoints will not see this because the abuse is server-side.The supporting signals.
| In-the-wild status | No evidence found of active exploitation in primary sources reviewed, and the CVE is not KEV-listed. |
|---|---|
| KEV status | Absent from the CISA Known Exploited Vulnerabilities Catalog at assessment time. |
| PoC availability | No standalone public exploit repo surfaced in indexed searches. Public weaponization details exist in the GitHub advisory and the fix PR, which is enough for a capable operator to re-create the attack. |
| EPSS | No primary FIRST EPSS value was retrievable from indexed sources during this assessment; treat EPSS as unavailable/immature rather than reassuringly low. FIRST's API reference is here. |
| CVSS / CNA signal | The GitHub/Coder advisory publishes CVSS 9.1 Critical with vector CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N, emphasizing unauthenticated network exploitation and high confidentiality/integrity impact. |
| Affected versions | <2.24.5, 2.29.0-2.29.12, 2.30.0-2.30.7, 2.31.0-2.31.11, 2.32.0-rc.0 through 2.32.1, and 2.33.0-rc.0 through 2.33.2 per the vendor advisory. |
| Fixed versions | Backported fixes are available in 2.24.5, 2.29.13, 2.30.8, 2.31.12, 2.32.2, and 2.33.3. |
| Exposure reality | This is not every Coder deployment. Exploitability depends on Azure-backed workspaces using azure-instance-identity; token-auth agent setups are the documented workaround and remove this attack path. |
| Scanning / exposure data | No trustworthy GreyNoise/Shodan/Censys/FOFA count for this specific endpoint surfaced in indexed results. Operationally, exposure should be measured as internet-facing Coder + Azure identity auth enabled, not 'all Coder hosts'. |
| Disclosure / credits | GitHub shows the advisory published on 2026-05-13 and credits Ben Tran (bencalif) and Anthropic Security Team (ANT-2026-22445). |
noisgate verdict.
The decisive downgrade from headline criticality is the exposure filter: this only bites Coder deployments on Azure that specifically use azure-instance-identity, and the attacker still needs the victim vmId. That narrows real-world reachable population substantially, but once the path lands it exposes developer tokens, Git keys, and workspace secrets, which keeps it firmly in HIGH.
Why this verdict
- Unauthenticated remote path is real: the vulnerable endpoint does not require login, so if a qualifying Coder deployment is reachable, exploitation is operationally simple.
- Exposure population is much smaller than the CVSS story: the chain requires Coder, on Azure, with
azure-instance-identityenabled for workspace agents; that is a compound prerequisite that removes a large fraction of enterprises from scope. vmIdknowledge is meaningful friction: the advisory itself notes this typically requires prior access or visibility, which makes the bug less internet-scalable than a true one-shot anonymous exploit.- Blast radius is high when it lands: agent tokens can lead to Git SSH keys, plaintext OAuth tokens, and workspace secrets, so successful exploitation can pivot into source code and delivery systems.
Why not higher?
This is not a universal pre-auth internet bug across all Coder deployments. The Azure-only auth mode requirement plus the need to know a target vmId are compounding constraints, and there is no KEV listing or confirmed in-the-wild abuse in the reviewed sources.
Why not lower?
Once the prerequisites are met, the attacker does not need credentials or user interaction and can directly mint an agent session token. That token can expose exactly the kind of developer secrets that turn a niche bug into a serious enterprise intrusion path.
What to do — in priority order.
- Switch affected templates to token auth — Use the vendor workaround and replace
azure-instance-identitywithtokenauthentication for workspace agents. This removes the vulnerable trust path entirely and should be deployed within 30 days for a HIGH finding, or faster for any internet-facing Coder fleet. - Restrict the Azure identity endpoint — Put
/api/v2/workspaceagents/azure-instance-identitybehind network controls that only permit expected source ranges or internal paths. If your Coder control plane is internet-facing, reduce reachability now and complete the restriction within 30 days. - Rotate agent-reachable secrets — Prioritize Git SSH keys, external OAuth tokens, and high-value workspace secrets that could be retrieved after token theft. Rotate the credentials most likely to be present in developer workspaces within 30 days if you cannot prove the path was never exposed.
- Alert on agent token cash-out APIs — Log and alert on unusual use of
/workspaceagents/me/gitsshkey,/workspaceagents/me/external-auth, and spikes ofazure-instance-identityPOSTs. Build detections and dashboards within 30 days to catch post-exploitation before patch completion.
- User MFA does not stop this path because exploitation targets an unauthenticated server-side workspace-agent endpoint, not an interactive user login.
- Endpoint EDR on developer laptops does not reliably help because the attacker can steal tokens and secrets directly from the Coder control plane/API path.
- Generic WAF signatures are weak here unless you explicitly restrict or allowlist the endpoint; this is a logic flaw, not a noisy payload pattern.
Crowdsourced verification payload.
Run this on the Coder server host, inside the Coder container, or on a CI worker inspecting the deployed image and template repo. Invoke it as bash check_cve_2026_46354.sh 2.31.11 /opt/coder/templates or omit the version argument to let it try coder version; no root is required unless your template directory needs elevated read access.
#!/usr/bin/env bash
# check_cve_2026_46354.sh
# Exit codes: 0=PATCHED, 1=VULNERABLE, 2=UNKNOWN, 3=usage/error
set -euo pipefail
VERSION_INPUT="${1:-}"
SCAN_DIR="${2:-.}"
usage() {
echo "Usage: $0 [version] [template_or_repo_dir]"
echo "Example: $0 2.31.11 /opt/coder/templates"
}
normalize_version() {
local v="$1"
v="${v#v}"
echo "$v"
}
extract_local_version() {
local out=""
if command -v coder >/dev/null 2>&1; then
out="$(coder version 2>/dev/null || true)"
if [[ -z "$out" ]]; then
out="$(coder --version 2>/dev/null || true)"
fi
fi
echo "$out" | grep -Eo 'v?[0-9]+\.[0-9]+\.[0-9]+([.-]rc\.[0-9]+)?' | head -n1 || true
}
version_lt() {
# true if $1 < $2 for stable x.y.z versions
local a="$1" b="$2"
[[ "$(printf '%s\n%s\n' "$a" "$b" | sort -V | head -n1)" == "$a" && "$a" != "$b" ]]
}
is_vulnerable_version() {
local v="$1"
# Release candidates explicitly called out by advisory
if [[ "$v" =~ ^2\.32\.0-rc\.[0-9]+$ ]]; then return 0; fi
if [[ "$v" =~ ^2\.33\.[0-2]$ ]]; then return 0; fi
if [[ "$v" =~ ^2\.33\.0-rc\.[0-9]+$ ]]; then return 0; fi
# Stable affected branches
if [[ "$v" =~ ^2\.32\.[0-1]$ ]]; then return 0; fi
if [[ "$v" =~ ^2\.31\.([0-9]|1[01])$ ]]; then return 0; fi
if [[ "$v" =~ ^2\.30\.[0-7]$ ]]; then return 0; fi
if [[ "$v" =~ ^2\.29\.([0-9]|1[0-2])$ ]]; then return 0; fi
# All versions before 2.24.5 are affected per advisory
if [[ "$v" =~ ^2\.[0-9]+\.[0-9]+$ ]]; then
if version_lt "$v" "2.24.5"; then return 0; fi
fi
return 1
}
if [[ -z "$VERSION_INPUT" ]]; then
VERSION_INPUT="$(extract_local_version)"
fi
if [[ -z "$VERSION_INPUT" ]]; then
echo "UNKNOWN: could not determine Coder version automatically; pass it explicitly."
exit 2
fi
VERSION="$(normalize_version "$VERSION_INPUT")"
if [[ ! "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+([.-]rc\.[0-9]+)?$ ]]; then
echo "UNKNOWN: unrecognized version format: $VERSION"
exit 2
fi
USES_AZURE_INSTANCE_IDENTITY="no"
if [[ -d "$SCAN_DIR" ]]; then
if grep -RIsq --exclude-dir=.git --exclude='*.png' --exclude='*.jpg' --exclude='*.jpeg' --exclude='*.gif' 'azure-instance-identity' "$SCAN_DIR"; then
USES_AZURE_INSTANCE_IDENTITY="yes"
fi
fi
if is_vulnerable_version "$VERSION"; then
if [[ "$USES_AZURE_INSTANCE_IDENTITY" == "yes" ]]; then
echo "VULNERABLE: Coder $VERSION is in an affected range and '$SCAN_DIR' references azure-instance-identity."
exit 1
else
echo "UNKNOWN: Coder $VERSION is in an affected range, but azure-instance-identity was not found under '$SCAN_DIR'. Verify runtime templates/configs before closing."
exit 2
fi
else
echo "PATCHED: Coder $VERSION is not in a listed affected range for CVE-2026-46354."
exit 0
fi
If you remember one thing.
azure-instance-identity, then either switch those templates to token auth or lock down the affected endpoint first. For this HIGH verdict, the noisgate mitigation SLA is within 30 days for compensating controls, and the noisgate remediation SLA is within 180 days for moving every affected server onto one of the fixed releases (2.24.5, 2.29.13, 2.30.8, 2.31.12, 2.32.2, or 2.33.3).Sources
What defenders are saying.
Crowdsourced verification outputs.
Results submitted by users who ran the verification payload against their environment.