# [CRIT] [GHSA / CRITICAL] CVE-2026-46354: Coder: PKCS#7 signature bypass in Azure instance identity allows unauthenticated agent token theft

**Source:** GitHub Security Advisories
**Published:** 2026-05-19
**Article:** https://github.com/advisories/GHSA-6x44-w3xg-hqqf

## Threat Profile

Coder: PKCS#7 signature bypass in Azure instance identity allows unauthenticated agent token theft

## Summary

`azureidentity.Validate()` verifies that the PKCS#7 signer certificate chains to a trusted Azure CA but never verifies the PKCS#7 signature itself. An attacker can embed a legitimate Azure certificate alongside arbitrary content e.g. `{"vmId":"<target>"}` and the forged `vmId` will be accepted returning the victim workspace agent's session token.

**No authentication is required.** The…

## Indicators of Compromise (high-fidelity only)

- **CVE:** `CVE-2026-46354`

## MITRE ATT&CK Techniques

- **T1190** — Exploit Public-Facing Application
- **T1528** — Steal Application Access Token
- **T1098.001** — Account Manipulation: Additional Cloud Credentials
- **T1133** — External Remote Services
- **T1552.004** — Unsecured Credentials: Private Keys

## Kill chain phases observed

_(none detected from narrative keywords)_

## Recommended hunts

### Coder CVE-2026-46354 - Burst of azure-instance-identity POSTs (vmId enumeration / forged PKCS#7)

`UC_249_2` · phase: **exploit** · confidence: **Medium** · AI-generated for this article

**Splunk SPL (CIM):**
```spl
| tstats summariesonly=t count from datamodel=Web where Web.http_method="POST" Web.uri_path="/api/v2/workspaceagents/azure-instance-identity" by Web.src Web.dest Web.status _time span=10m | `drop_dm_object_name(Web)` | stats sum(count) as attempts, values(status) as observed_status, dc(_time) as distinct_buckets, min(_time) as firstTime, max(_time) as lastTime by src, dest | where attempts >= 5 | convert ctime(firstTime) ctime(lastTime) | sort - attempts
```

### Coder CVE-2026-46354 - Agent token redemption: PKCS#7 POST followed by gitsshkey / external-auth GET

`UC_249_3` · phase: **actions** · confidence: **High** · AI-generated for this article

**Splunk SPL (CIM):**
```spl
| tstats summariesonly=t count from datamodel=Web where Web.http_method IN ("POST","GET") AND (Web.uri_path="/api/v2/workspaceagents/azure-instance-identity" OR Web.uri_path="/api/v2/workspaceagents/me/gitsshkey" OR Web.uri_path="/api/v2/workspaceagents/me/external-auth") by Web.src Web.dest Web.uri_path Web.http_method Web.status _time | `drop_dm_object_name(Web)` | eval event_type=case(http_method="POST" AND uri_path="/api/v2/workspaceagents/azure-instance-identity","auth", uri_path IN ("/api/v2/workspaceagents/me/gitsshkey","/api/v2/workspaceagents/me/external-auth"),"exfil") | stats min(eval(if(event_type="auth",_time,null()))) as first_auth max(eval(if(event_type="exfil",_time,null()))) as first_exfil values(uri_path) as endpoints_touched values(status) as status_codes count by src, dest | where isnotnull(first_auth) AND isnotnull(first_exfil) AND first_exfil > first_auth AND (first_exfil - first_auth) <= 1800 | eval delay_seconds = first_exfil - first_auth | convert ctime(first_auth) ctime(first_exfil) | sort - count
```

### Coder CVE-2026-46354 - Inventory of vulnerable Coder v2 versions

`UC_249_4` · phase: **recon** · confidence: **High** · AI-generated for this article

**Splunk SPL (CIM):**
```spl
| tstats summariesonly=t count, min(_time) as firstSeen, max(_time) as lastSeen from datamodel=Vulnerabilities where Vulnerabilities.cve="CVE-2026-46354" by Vulnerabilities.dest, Vulnerabilities.signature, Vulnerabilities.severity, Vulnerabilities.cve | `drop_dm_object_name(Vulnerabilities)` | convert ctime(firstSeen) ctime(lastSeen) | sort - lastSeen
```

**Defender KQL:**
```kql
DeviceTvmSoftwareVulnerabilities
| where CveId == "CVE-2026-46354"
| join kind=leftouter (
    DeviceInfo
    | summarize arg_max(Timestamp, PublicIP, IsInternetFacing, OSPlatform, MachineGroup) by DeviceId
  ) on DeviceId
| project DeviceName, SoftwareVendor, SoftwareName, SoftwareVersion, RecommendedSecurityUpdate, VulnerabilitySeverityLevel, PublicIP, IsInternetFacing, OSPlatform, MachineGroup
| order by IsInternetFacing desc, VulnerabilitySeverityLevel desc
```

### OAuth consent / suspicious app grant

`UC_OAUTH_ABUSE` · phase: **actions** · confidence: **High**

**Splunk SPL (CIM):**
```spl
| tstats `summariesonly` count min(_time) as firstTime max(_time) as lastTime
    from datamodel=Authentication.Authentication
    where Authentication.action="success"
      AND Authentication.signature IN (
        "Consent to application",
        "Add app role assignment grant to user",
        "Add OAuth2PermissionGrant",
        "Add delegated permission grant")
    by Authentication.user, Authentication.app, Authentication.src, Authentication.signature
| `drop_dm_object_name(Authentication)`
```

**Defender KQL:**
```kql
CloudAppEvents
| where Timestamp > ago(7d)
| where ActionType in ("Consent to application.","Add OAuth2PermissionGrant.","Add delegated permission grant.")
| project Timestamp, AccountObjectId, AccountDisplayName, ActivityType,
          ActivityObjects, IPAddress, UserAgent
```

### IOC-driven hunts (use shared templates)

These are standard IOC-substitution hunts — the canonical SPL and KQL live once in [`_TEMPLATES.md`](../_TEMPLATES.md), so we don't repeat the same boilerplate on every CVE / hash / network-IOC briefing.

- **Asset exposure — vulnerability matches article CVE(s)** ([template](../_TEMPLATES.md#asset-exposure)) — phase: **recon**, confidence: **High**
  - CVE(s): `CVE-2026-46354`


## Why this matters

Severity classified as **CRIT** based on: CVE present, 5 use case(s) fired, 5 technique(s) inferred. Read the full article for actor attribution, tooling details, and any defanged IOCs in the body that aren't visible in the RSS summary.
