A mislabeled envelope that only explodes if you swap between two very specific mailboxes in the right order
CVE-2026-70197 is a memory corruption vulnerability in .NET's System.Net.Sockets layer, exclusively on Windows. When a developer reuses a single SocketAsyncEventArgs object across both IPv4 and IPv6 datagram (UDP) sockets, the runtime caches a native address buffer sized for the first address family (16-byte SOCKADDR_IN). When the socket switches to IPv6, ReceiveFromAsync writes a 28-byte SOCKADDR_IN6 into that 16-byte buffer, overwriting 12 bytes of adjacent heap memory with attacker-influenced data from the incoming UDP packet's source address fields. Affected runtimes span .NET 8.0.0–8.0.32, .NET 9.0.0–9.0.21, .NET 10.0.0–10.0.13, and .NET 11 preview/RC builds prior to rc.3.26522.148. Visual Studio 2022 v17.14 and Visual Studio 2026 v18.10 are also affected via their bundled runtimes. Critically, the initial October 13, 2026 Patch Tuesday fix was incomplete — Microsoft re-released corrected updates on October 25, meaning organizations that patched promptly on the 13th are still vulnerable and must patch again.
Microsoft rates this HIGH / 8.1, which is defensible for the theoretical impact: unauthenticated, network-reachable RCE with full CIA compromise. However, the CVSS vector already carries AC:H, acknowledging that triggering the bug demands a specific application-level code pattern — UDP datagram sockets reusing SocketAsyncEventArgs across address families. The vast majority of .NET workloads are ASP.NET Core web apps on TCP/HTTP that never touch this code path. Windows-only scope further narrows the blast radius. With no public PoC, no in-the-wild exploitation, EPSS at 0.79%, and Microsoft's own assessment of 'Exploitation Less Likely,' the real-world urgency is materially lower than the headline score suggests. We downgrade to 7.1 while maintaining HIGH because successful exploitation still yields full unauthenticated RCE on the affected host.
Bottom line: Under the noisgate mitigation SLA for HIGH, deploy compensating controls — audit your .NET apps for the vulnerable UDP socket pattern and restrict inbound UDP at the firewall — within 30 days. Under the noisgate remediation SLA, roll out the October 25 corrected .NET runtime patches (8.0.33, 9.0.22, 10.0.14) within 180 days. Self-contained applications must be rebuilt and redeployed; a shared runtime update alone will not protect them. If your fleet has no .NET UDP services on Windows, document that finding and deprioritize.
5 steps from start to impact.
Locate a .NET UDP service on Windows
System.Net.Sockets.Socket bound to a UDP port and call ReceiveFromAsync via a SocketAsyncEventArgs instance. Real-world examples include custom DNS resolvers, game servers, SIP/VoIP stacks, or IoT gateways built on .NET. HTTP/REST/gRPC services running on Kestrel (TCP) are not affected. No known weaponized scanner exists for this step.- Target host runs Windows
- A .NET 8/9/10/11 application listens on a UDP port
- The application uses SocketAsyncEventArgs for async UDP receive operations
- Most .NET applications are HTTP/TCP web services that never use raw UDP sockets
- UDP services built with SocketAsyncEventArgs (vs. simpler ReceiveFrom or UdpClient) are an advanced and uncommon pattern
- Port scanning identifies UDP listeners but cannot determine if they're .NET-backed
dotnet list package --vulnerable) are the primary detection path.Force address-family switch on the cached buffer
SocketAsyncEventArgs instance to have previously been used on an IPv4 socket, caching a 16-byte SOCKADDR_IN native address buffer. The same instance must then be reused on an IPv6 socket, where ReceiveFromAsync expects the 28-byte SOCKADDR_IN6 structure. The attacker must understand the application's socket lifecycle to induce this transition — e.g., by connecting first over IPv4 then sending the exploit payload over IPv6. This is the core of the AC:H rating and requires application-specific knowledge.- Application reuses SocketAsyncEventArgs across IPv4 and IPv6 datagram sockets
- Attacker can send traffic to the application over both address families
- Timing aligns with the SocketAsyncEventArgs reuse cycle
- Many applications bind to a single address family or use dual-stack sockets that don't trigger the reuse bug
- The attacker needs to reverse-engineer the application's internal socket pooling — this is not a generic network spray
- If the app creates fresh SocketAsyncEventArgs per operation, the bug never fires
Trigger the out-of-bounds write via crafted UDP datagram
ReceiveFromAsync completes, the .NET runtime writes the 28-byte SOCKADDR_IN6 source address into the 16-byte buffer, overwriting 12 bytes of adjacent heap memory. The attacker influences the overwritten data through the source IPv6 address and flow-info fields in their packet, but control is limited to the structure of SOCKADDR_IN6.- Network path to the UDP port is not firewalled
- The undersized buffer condition is active at receive time
- The overwrite is 12 bytes of SOCKADDR_IN6 structure data — limited attacker control compared to a classic buffer overflow
- Heap layout must be favorable for the overwrite to corrupt an exploitable structure
Weaponize heap corruption into control-flow hijack
- Favorable heap layout at time of overwrite
- Knowledge of target .NET runtime version for heap structure offsets
- Ability to place controlled data in adjacent heap allocations via repeated UDP packets (heap spray)
- Windows ASLR + DEP + CFG on modern builds significantly complicate exploitation
- The .NET garbage collector non-deterministically reorganizes managed heap
- 12 bytes of SOCKADDR data is a very constrained overwrite primitive
- No public exploit exists — this is a theoretical chain
Achieve code execution as the .NET service account
- Successful heap corruption and control-flow hijack from step 4
- Process-level sandboxing, container isolation, or AppLocker limits post-exploitation impact
- Network segmentation and micro-segmentation limit lateral movement
- Services running under least-privilege accounts constrain the attacker's capabilities
SocketAsyncEventArgs combined with SocketType.Dgram or ProtocolType.Udp and ReceiveFromAsync. If no applications use this pattern, your effective risk drops to near-zero. Use grep -r 'SocketAsyncEventArgs' --include='*.cs' across your .NET repos and check for dual address-family usage. Deploy within 30 days per the noisgate mitigation SLA for HIGH. This is the single highest-leverage action because it can eliminate risk entirely for most organizations.dotnet --list-runtimes. Deploy within 180 days per the noisgate remediation SLA for HIGH. Prioritize hosts running confirmed UDP .NET services for early waves.- Web Application Firewall (WAF): This is a UDP socket-layer vulnerability, not an HTTP flaw. WAFs inspect HTTP/HTTPS traffic and have zero visibility into raw UDP datagrams. A WAF will not see or block the attack payload.
- IDS/IPS UDP signature: No public exploit exists, so there is no signature to write. The malicious payload is a standard UDP datagram with a crafted IPv6 source address — indistinguishable from legitimate traffic at the network layer without deep application context.
- ASLR/DEP/CFG alone: These Windows mitigations raise the exploitation bar significantly but do not prevent the out-of-bounds write itself. They make reliable RCE harder but not impossible. Do not treat them as a substitute for patching.
- Moving to .NET Framework 4.x: The vulnerability is in modern .NET (8+), and .NET Framework 4.x uses a completely different socket implementation. However, migrating a modern application to a legacy, feature-frozen framework to avoid one CVE is irrational and introduces far greater risk.
The supporting signals.
| In-the-Wild Exploitation | None reported. Microsoft assesses *Exploitation Less Likely*. Not listed in CISA KEV catalog. No known campaigns or threat actor activity targeting this CVE. |
|---|---|
| Proof of Concept | No public PoC found. Checked GitHub for repos named after CVE-2026-70197 — none exist. No entries on ExploitDB. No nuclei templates. The SecureWithUmer/CVE-2026-PoCs community collection does not include this CVE. The memory corruption primitive (12-byte SOCKADDR heap overwrite) is described in the advisory but no working exploit chain has been published. |
| EPSS | 0.788% probability of exploitation in next 30 days (55.9th percentile). Well below the actionable exploitation threshold. Consistent with Microsoft's 'Less Likely' assessment. |
| CISA KEV Status | Not listed as of 2026-10-27. No federal mandate for expedited patching under BOD 22-01. |
| CVSS Vector Interpretation | CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H — Unauthenticated network RCE with high attack complexity. The AC:H is the critical modifier: the attacker cannot spray this generically; they need a specific application code pattern (SocketAsyncEventArgs IPv4↔IPv6 reuse on UDP). Temporal score: 7.1 (no exploit code, no active exploitation). |
| Affected Versions | .NET 8.0.0–8.0.32, .NET 9.0.0–9.0.21, .NET 10.0.0–10.0.13, .NET 11.0.0-preview.1 through rc.3.26522.147. Visual Studio 2022 v17.14 and VS 2026 v18.10. Windows only — only Microsoft.NETCore.App.Runtime.win-arm, win-arm64, win-x64, win-x86 NuGet packages are affected. Linux and macOS runtimes are not vulnerable. |
| Fixed Versions | October 25 corrected release (the Oct 13 initial fix was incomplete): .NET 8.0.33, 9.0.22, 10.0.14, 11.0.0-rc.3.26522.148. Corresponding SDK versions: 8.0.426+, 9.0.319+, 10.0.402+. Self-contained applications must be rebuilt — host-level runtime updates do not patch bundled runtimes. |
| Scanning / Exposure | No GreyNoise tags, Shodan honeypot hits, or Censys scan data specific to this CVE. The vulnerability targets a .NET application-level code pattern (UDP SocketAsyncEventArgs), which is not externally fingerprinted by internet scanners. Exposure assessment requires internal application inventory and code review. |
| Disclosure Timeline | Published 2026-10-13 (October Patch Tuesday). Initial patch found incomplete. Corrected out-of-band release 2026-10-25. WSUS Scan Cab updated 2026-10-25 at 7:00 PM PDT — admins who downloaded before that time must re-acquire. |
| Reporter | Not publicly credited in the MSRC advisory or GHSA-4mpw-cpwj-hxxj. |
Sources.
Why this verdict
- Narrow code path required: The vulnerability only triggers when a .NET application reuses
SocketAsyncEventArgsacross IPv4 and IPv6 UDP datagram sockets on Windows. The vast majority of .NET workloads are ASP.NET Core HTTP/TCP services that never exercise this code path. Conservatively, fewer than 5% of enterprise .NET deployments use raw UDP sockets with the specific SocketAsyncEventArgs reuse pattern. This compounding prerequisite significantly reduces the reachable population beyond what AC:H alone captures. - No weaponization exists: No public PoC, no in-the-wild exploitation, EPSS at 0.79% (55.9th percentile), and Microsoft's own 'Exploitation Less Likely' assessment all confirm this is not an actively threatened vector. The 12-byte heap overwrite is constrained to SOCKADDR_IN6 structure data — not arbitrary bytes — making reliable RCE development against a GC-managed, ASLR+DEP+CFG-hardened Windows host non-trivial even for a skilled attacker.
- Windows-only scope: Linux and macOS .NET deployments are entirely unaffected. In modern enterprise environments where ~30-40% of .NET server workloads now run on Linux (particularly in containerized/Kubernetes deployments), this materially reduces the exposed fleet.
- Incomplete initial patch adds operational friction: The October 13 fix was insufficient, and the corrected release came October 25. Organizations that patched on Patch Tuesday must patch again. While this is an operational nuisance, it does not change the threat level — it means defenders should verify against the 8.0.33/9.0.22/10.0.14 versions specifically.
- Role multiplier: .NET is a general-purpose runtime, not a canonical high-value-role component. On a *typical web server* (ASP.NET Core on Kestrel/TCP), the vulnerable code path is unreachable — verdict is moot. On a *custom UDP network service* (game server, DNS proxy, SIP stack, custom protocol handler), the chain succeeds and yields host-level RCE — blast radius is the host and whatever the service account can reach. On a *hypothetical .NET-based management-plane service handling UDP* (e.g., custom SNMP trap receiver, network discovery), the blast radius could extend to management network access — but this is an edge case representing well under 1% of .NET installs. No canonical high-value role (domain controller, hypervisor, identity provider, certificate authority, backup server, network edge appliance) runs the vulnerable .NET UDP socket pattern by default. The floor holds at HIGH due to the unauthenticated RCE impact on the affected subset, but does not rise to CRITICAL because no high-value-role component canonically exercises this code path.
Why not higher?
CRITICAL requires either active exploitation, a widely reachable default-configuration code path, or a canonical high-value target where the chain succeeds with fleet/domain/supply-chain impact. None apply. The vulnerability demands a niche UDP socket programming pattern that most .NET applications simply do not use, there is no public exploit code, no in-the-wild activity, and EPSS sits at the 55th percentile. The 12-byte SOCKADDR heap overwrite is a constrained primitive against modern Windows mitigations (ASLR, DEP, CFG, GC heap randomization). No infrastructure-tier Microsoft product (AD, Exchange, SQL Server, IIS) uses the vulnerable socket pattern by default.
Why not lower?
MEDIUM would understate the impact for .NET applications that DO use this code path. The vulnerability is unauthenticated, network-reachable, requires no user interaction, and yields full RCE — a combination that warrants urgent attention for the affected subset. The heap corruption primitive operates in native memory where .NET's managed-code safety guarantees do not apply. For a defender running a custom .NET UDP service on Windows exposed to untrusted networks, this is a genuine pre-auth RCE with SYSTEM-level impact. Maintaining HIGH ensures those specific deployments patch with appropriate urgency within the 30-day mitigation / 180-day remediation SLA.
Crowdsourced verification payload.
Run on each Windows target host where .NET applications are deployed. Standard user privileges are sufficient. Execute: powershell -ExecutionPolicy Bypass -File .\Check-CVE-2026-70197.ps1. Checks shared .NET runtimes against the October 25 corrected versions. Does not detect self-contained app bundles — those require separate application-level SBOM or file-version checks.
#Requires -Version 5.1
<#
.SYNOPSIS
CVE-2026-70197 - .NET SocketAsyncEventArgs OOB Write Checker
.DESCRIPTION
Checks installed Microsoft.NETCore.App runtimes against the
October 25, 2026 corrected patch versions (8.0.33, 9.0.22,
10.0.14, 11.0.0-rc.3.26522.148). Windows-only vulnerability.
Exit 0 = PATCHED | Exit 1 = VULNERABLE | Exit 2 = UNKNOWN
#>
# Guard: Windows-only CVE
if ($env:OS -ne 'Windows_NT') {
Write-Host 'PATCHED - CVE-2026-70197 affects Windows only. This host is not Windows.'
exit 0
}
# Check for dotnet CLI
$dotnetCmd = Get-Command dotnet -ErrorAction SilentlyContinue
if (-not $dotnetCmd) {
Write-Host 'UNKNOWN - dotnet CLI not found in PATH.'
Write-Host ' .NET may not be installed, or only self-contained apps are present.'
Write-Host ' For self-contained apps, check the bundled runtime version manually.'
exit 2
}
# List installed runtimes
try {
$lines = & dotnet --list-runtimes 2>&1
if ($LASTEXITCODE -ne 0) { throw $lines }
} catch {
Write-Host "UNKNOWN - 'dotnet --list-runtimes' failed: $_"
exit 2
}
# October 25, 2026 corrected patch versions
$patchMap = @{
'8' = [version]'8.0.33'
'9' = [version]'9.0.22'
'10' = [version]'10.0.14'
}
$foundAffectedBranch = $false
$vulnerable = $false
foreach ($line in $lines) {
if ($line -match '^Microsoft\.NETCore\.App\s+(\d+)\.(\d+)\.(\d+)') {
$major = $Matches[1]
$ver = [version]"$($Matches[1]).$($Matches[2]).$($Matches[3])"
if ($patchMap.ContainsKey($major)) {
$foundAffectedBranch = $true
$req = $patchMap[$major]
if ($ver -lt $req) {
Write-Host "VULNERABLE - .NET $major runtime $ver < required $req"
$vulnerable = $true
} else {
Write-Host "OK - .NET $major runtime $ver >= $req"
}
}
elseif ($major -eq '11') {
$foundAffectedBranch = $true
# .NET 11 preview/RC: patched at rc.3.26522.148
if ($line -match '(preview\.|rc\.[12]\.)') {
Write-Host "VULNERABLE - .NET 11 pre-release: $($line.Trim())"
$vulnerable = $true
} else {
Write-Host "OK - .NET 11 appears at rc.3+ or GA"
}
}
# .NET 6, 7, or other majors: not affected by this CVE
}
}
if (-not $foundAffectedBranch) {
Write-Host 'PATCHED - No .NET 8/9/10/11 runtimes found. Only unaffected versions installed.'
exit 0
}
if ($vulnerable) {
Write-Host "`nVULNERABLE - One or more .NET runtimes need the October 25, 2026 corrected update."
Write-Host 'Action: Install .NET 8.0.33 / 9.0.22 / 10.0.14 / 11.0.0-rc.3.26522.148 or later.'
exit 1
} else {
Write-Host "`nPATCHED - All detected .NET runtimes at or above corrected patch versions."
exit 0
}