A booby-trapped business card that only detonates when the detective picks it up with tweezers under a magnifying glass
CVE-2026-102870 is a code-injection flaw in the Blazor WebAssembly debug proxy (BrowserDebugHost) bundled in Microsoft.AspNetCore.Components.WebAssembly.Server and .DevServer. The debug proxy evaluates developer expressions by generating and compiling C# source on the fly — but it embeds application-originated values (ToString() results, descriptions, class names) into that generated source *without consistent escaping*. If a malicious value lands in a field a developer inspects, the payload breaks out of the generated string literal and executes arbitrary code on the developer's machine. Affected versions are Microsoft.AspNetCore.Components.WebAssembly.Server 10.0.0–10.0.13 and 11.0.0-preview.1 through 11.0.0-rc.2. The initial fix shipped October 13 in .NET 10.0.13 was incomplete; the corrected release is .NET 10.0.14 (October 25, 2026). Visual Studio 2022 v17.14 and Visual Studio 2026 v18.10+ are also affected via the bundled SDK.
Microsoft rates this Important / 8.8 HIGH — and the CVSS math is technically valid (AV:N/AC:L/PR:N/UI:R), but the score dramatically overstates real-world risk. The AV:N reflects that malicious data arrives over the network, not that the debug proxy itself is internet-reachable. Exploitation requires a triple-gated user interaction: (1) attacker-controlled data present in the debugged app, (2) a Blazor WASM debug session running against that data, and (3) the developer actively evaluating an expression containing the poisoned value. This is a development-time tooling bug, not a production attack surface. No production ASP.NET Core server is vulnerable. The realistic severity is MEDIUM ~5.5 once you account for the narrow developer-only exposure and the absence of any exploitation activity.
5 steps from start to impact.
Poison the data source
ToString() result, or class name. No special tooling is needed beyond access to the data source.- Write access to a data source consumed by the target Blazor WASM app
- Knowledge that the target team develops a Blazor WebAssembly application
- Attacker needs to know (or guess) that the target team uses Blazor WASM specifically, not Blazor Server or another SPA framework
- The poisoned value must land in a field a developer would plausibly inspect during debugging — not buried in an ignored column
Developer launches Blazor WASM debug session
BrowserDebugHost debug proxy spins up and begins proxying CDP (Chrome DevTools Protocol) traffic between the IDE and the browser running the WASM app.- Developer is using a vulnerable .NET 10.0.0–10.0.13 SDK or .NET 11 preview/RC < rc.3
- Developer launches a debug (F5) session, not a no-debug (Ctrl+F5) run
- Only Blazor WebAssembly developers are affected — Blazor Server, MVC, Razor Pages, and minimal API developers are out of scope
- The debug proxy only runs during active debugging; production
dotnet runordotnet publishnever invokes it - Many orgs use containers or remote dev environments where the debug proxy may not be active
Application loads the poisoned data
- The Blazor app's workflow during the debug session must hit the poisoned data path
- The debug session must be connected to the data source containing the malicious data (not a sanitized test database)
- Many teams use seed/mock data for local debugging, not live production databases
- API gateways or ORMs may truncate or sanitize the special characters needed for the injection
Developer evaluates a tainted expression
Runtime.evaluate request to the debug proxy. The proxy takes the tainted value and embeds it into dynamically generated C# source code for compilation.- Developer must actively interact with the debugger near the tainted data
- The specific expression evaluated must surface the malicious value (e.g., viewing the object's
ToString()or a property that contains the payload)
- This requires conscious, manual action by the developer — it does not trigger automatically on breakpoint hit unless auto-expand is configured for the tainted object
- The developer would need to inspect the specific field containing the payload, which may not be obvious or interesting during normal debugging
devenv.exe or dotnet during a debug session, but this would be novel detection logic not commonly deployedCode injection and execution on developer machine
- All prior steps must chain successfully
- The injected C# must be syntactically valid to compile
- The generated code context constrains what syntax will compile — the attacker needs to craft a payload that cleanly escapes the string literal AND produces valid C# in the surrounding generated code
- Character encoding, escaping layers, or IDE-specific serialization may mangle the payload before it reaches the code generation step
BrowserDebugHost.exe spawning cmd.exe, powershell.exe, or network connections to unexpected hosts). No known scanner signature or Nuclei template exists for this CVE.Microsoft.AspNetCore.Components.WebAssembly.Server and .DevServer NuGet references are ≥ 10.0.14. For .NET 11 preview users, update to rc.3. This is a MEDIUM verdict — no noisgate mitigation SLA applies. Target the 365-day noisgate remediation SLA window, though updating developer tooling is typically low-friction and can be done sooner via normal SDK update cadence.BrowserDebugHost. Enterprise Visual Studio deployments managed via VSIX or admin update channels should push this as part of normal tooling updates within the 365-day remediation window.BrowserDebugHost.exe spawning unexpected child processes (cmd.exe, powershell.exe, net.exe, whoami.exe) or making outbound network connections to non-localhost destinations during debug sessions. This provides detection-in-depth but does not prevent exploitation.- WAF / NGFW rules — The debug proxy runs on localhost during development. No network traffic passes through perimeter or application firewalls. WAF rules cannot inspect or block this attack path.
- Production .NET runtime patching — Updating the .NET runtime on production servers has zero effect on this CVE. The vulnerable component (
BrowserDebugHost) is a development-time tool that is never deployed to production. - Network segmentation of production databases — While generally good practice, this only helps if the *development* data source is also segmented. The attack targets the dev environment, not production infrastructure.
The supporting signals.
| In-the-Wild Exploitation | None observed. Microsoft rates exploitation as "Less Likely". Not listed on CISA KEV. No campaigns or threat actor attribution identified. |
|---|---|
| Proof-of-Concept Availability | No public PoC found. No repositories on GitHub named after CVE-2026-102870. Not indexed on pocindex.io. No Nuclei template, ExploitDB entry, or Metasploit module. The attack requires crafting a C# injection payload that survives the debug proxy's code generation context — non-trivial but achievable by a skilled researcher. |
| EPSS Score | 0.91% (59.6th percentile) — below the 6% threshold commonly used to flag likely-exploited vulns. Consistent with "development tooling bug unlikely to see mass exploitation." |
| CISA KEV Status | Not listed. No federal mandate to patch on an emergency timeline. |
| CVSS Vector | CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H — base 8.8, temporal 7.7 (E:U/RL:O/RC:C). The AV:N is technically correct (data arrives over the network) but misleading: the debug proxy is not a remotely-reachable service. UI:R understates the interaction — it requires a specific debugging workflow, not just clicking a link. |
| Affected Versions | Microsoft.AspNetCore.Components.WebAssembly.Server and .DevServer 10.0.0–10.0.13 (.NET 10), 11.0.0-preview.1 through 11.0.0-rc.2 (.NET 11 preview). Also bundled in Visual Studio 2022 v17.14 (<17.14.43) and Visual Studio 2026 v18.10/18.11/18.12. |
| Fixed Versions | .NET SDK 10.0.14 (runtime 10.0.14, released October 25, 2026). .NET 11 11.0.0-rc.3.26522.148. NuGet package Microsoft.AspNetCore.Components.WebAssembly.Server ≥ 10.0.14. Note: the October 13 release (10.0.13) had an incomplete fix — the corrected BrowserDebugHost packaging shipped October 25. |
| Scanning / Exposure | Zero internet-facing attack surface. The Blazor WASM debug proxy (BrowserDebugHost) listens only on localhost during debug sessions and is never deployed to production. Shodan/Censys/GreyNoise scans are irrelevant for this CVE. |
| Disclosure Timeline | October 13, 2026: Initial disclosure + incomplete fix in .NET 10.0.13. October 25, 2026: Corrected out-of-band release in .NET 10.0.14 with fixed BrowserDebugHost packaging. |
| Reporter / Credits | Not publicly attributed in the Microsoft advisory or dotnet/announcements issue. |
Sources.
Why this verdict
- Development-only attack surface (major downgrade): This vulnerability exists exclusively in the Blazor WebAssembly debug proxy, a component that runs only during active development debugging sessions. Production ASP.NET Core servers, containers, and published applications never invoke
BrowserDebugHost. The entire production installed base of ASP.NET Core — the population that drives the vendor's HIGH rating — is completely unaffected. - Triple-gated user interaction (major downgrade): CVSS scores
UI:Ras a single bit, but this chain requires three independent user actions: (1) running a Blazor WASM debug session specifically, (2) against a data source containing the attacker's payload, (3) and then manually evaluating an expression that surfaces the poisoned value. Each gate independently narrows the exploitation window. This is categorically different from "user clicks a link." - Niche component scope (moderate downgrade): Blazor WebAssembly is a subset of the ASP.NET Core ecosystem. Among .NET developers, Blazor WASM adoption is a fraction of total ASP.NET Core usage. The affected developer population is small, and only those debugging against untrusted/live data sources are in the blast radius.
- No exploitation activity (supporting factor): Microsoft rates exploitation "Less Likely." EPSS is 0.91%. No public PoC exists. No KEV listing. No observed campaigns. The initial fix was incomplete, suggesting limited external pressure to weaponize.
- Role multiplier: The Blazor WASM debug proxy runs exclusively on developer workstations (low-value role by infrastructure standards). It does not exist on domain controllers, edge appliances, CI/CD runners (which don't run interactive debug sessions), hypervisors, backup infrastructure, or any other high-value role in the catalog. A successful exploit yields code execution on one developer's machine — host-level blast radius, not domain/fleet/supply-chain scale. A sophisticated attacker could pivot from a compromised dev machine to source code or CI credentials, but that requires additional steps outside this vulnerability's scope. The high-value-role floor does not apply.
Why not higher?
The CVSS 8.8 / HIGH vendor rating would be appropriate if this were a production web application vulnerability exploitable by any user visiting a website. It is not. The debug proxy has zero production deployment footprint, zero internet-facing attack surface, and requires a specific multi-step developer interaction during an active debugging session. Upgrading to HIGH would conflate a development tooling quirk with a remotely exploitable production service, misallocating enterprise patching resources away from actual perimeter or server-side risks.
Why not lower?
Code execution on a developer machine is not trivial. Developers typically have access to source code repositories, CI/CD pipeline credentials, package publishing tokens, and elevated permissions in development infrastructure. A targeted attacker (e.g., poisoning a shared development database or a third-party API consumed during development) could use this as an initial access vector to eventually compromise a build pipeline or inject malicious code into a release artifact. The impact on a single successfully exploited machine is genuinely high (C:H/I:H/A:H), preventing a drop to LOW.
Crowdsourced verification payload.
Run on each developer workstation or build server where Blazor WebAssembly projects are developed. No admin privileges required — just read access to project directories. Invoke: powershell -ExecutionPolicy Bypass -File Check-CVE2026102870.ps1 -SearchPath C:\src
#Requires -Version 5.1
<#
Check-CVE2026102870.ps1
Detects vulnerable Blazor WebAssembly debug proxy (CVE-2026-102870)
Exit 0 = PATCHED, Exit 1 = VULNERABLE, Exit 2 = UNKNOWN
#>
param([string]$SearchPath = '.')
$VulnPkgs = @(
'Microsoft.AspNetCore.Components.WebAssembly.Server',
'Microsoft.AspNetCore.Components.WebAssembly.DevServer'
)
$SafeVer10 = [version]'10.0.14'
$found = $false
$vuln = $false
# --- Check 1: .NET SDK version ---
Write-Host '[*] Checking installed .NET SDKs...'
try {
$sdks = & dotnet --list-sdks 2>$null
foreach ($line in $sdks) {
if ($line -match '^(10\.0\.(\d+))') {
$found = $true
$sdkPatch = [int]$Matches[2]
# SDK 10.0.114 ships runtime 10.0.14; SDK patch >= 403 also maps to fixed runtime
if ($sdkPatch -lt 114 -and $sdkPatch -lt 403) {
Write-Host "[!] VULNERABLE SDK: $($Matches[1])" -ForegroundColor Red
$vuln = $true
} else {
Write-Host "[+] Patched SDK: $($Matches[1])" -ForegroundColor Green
}
}
if ($line -match '^(11\.0\.0-(preview|rc\.[12]))') {
$found = $true
Write-Host "[!] VULNERABLE SDK (pre-rc.3): $($Matches[1])" -ForegroundColor Red
$vuln = $true
}
}
} catch { Write-Host '[?] dotnet CLI not found' -ForegroundColor Yellow }
# --- Check 2: NuGet package references in project files ---
Write-Host "`n[*] Scanning project files under $SearchPath ..."
$projs = Get-ChildItem -Path $SearchPath -Recurse -Include '*.csproj','*.fsproj','*.vbproj' -ErrorAction SilentlyContinue
foreach ($p in $projs) {
try {
[xml]$xml = Get-Content $p.FullName -ErrorAction Stop
foreach ($ref in $xml.SelectNodes('//PackageReference')) {
$name = $ref.GetAttribute('Include')
$ver = $ref.GetAttribute('Version')
if ($VulnPkgs -contains $name -and $ver) {
$found = $true
$clean = $ver -replace '-.*',''
if ($ver -match '^10\.' -and [version]$clean -lt $SafeVer10) {
Write-Host "[!] VULNERABLE: $($p.FullName) -> $name $ver" -ForegroundColor Red
$vuln = $true
} elseif ($ver -match '^11\.0\.0-(preview|rc\.[12])') {
Write-Host "[!] VULNERABLE: $($p.FullName) -> $name $ver" -ForegroundColor Red
$vuln = $true
} else {
Write-Host "[+] OK: $($p.FullName) -> $name $ver" -ForegroundColor Green
}
}
}
} catch {}
}
# --- Verdict ---
Write-Host ''
if (-not $found) {
Write-Host 'UNKNOWN - No .NET 10/11 SDK or Blazor WASM package references found' -ForegroundColor Yellow
exit 2
} elseif ($vuln) {
Write-Host 'VULNERABLE - CVE-2026-102870: Update SDK to 10.0.14+ and NuGet packages' -ForegroundColor Red
exit 1
} else {
Write-Host 'PATCHED - No vulnerable Blazor WASM debug proxy versions detected' -ForegroundColor Green
exit 0
}