You applied the April Patch Tuesday updates, ran your deployment pipeline, and moved on with your week. Then, on 21 April, Microsoft dropped an emergency out-of-band release: .NET 10.0.7. Not a routine servicing update — an urgent patch for CVE-2026-40372, a CVSS 9.1 critical vulnerability in Microsoft.AspNetCore.DataProtection. The component that protects your authentication cookies, anti-forgery tokens, and any other secrets you feed through IDataProtector.Protect.
The short version: on every non-Windows platform, the managed authenticated encryptor was computing its HMAC tag over the wrong bytes of the payload and then discarding the result. That meant the authentication step in "authenticated encryption" was not authenticating anything. An attacker who could intercept or inject a payload could forge cookies and escalate privileges without ever touching the encryption key.
If you run ASP.NET Core on Linux — which is to say, if you run it in Docker, on Azure App Service for Linux, on AWS, or on practically any cloud-native deployment — you need to patch immediately. Here is what went wrong, why, and how to verify you are safe.
The timeline
The story begins with the regular April 2026 Patch Tuesday release on 14 April. That update shipped .NET 10.0.6 with fixes for several CVEs, including SMTP header injection and XML recursion bombs. Business as usual.
Within days, users started reporting that their applications were throwing CryptographicException with the message "The payload was invalid" when trying to unprotect data that had been protected under 10.0.5. The decryption regression was tracked in aspnetcore#66335, and the stack traces pointed squarely at ManagedAuthenticatedEncryptor.CalculateAndValidateMac().
As the ASP.NET Core team investigated the regression, they discovered something worse: the regression was a symptom of a deeper bug that had been present since .NET 10.0.0. The HMAC validation in the managed encryptor had never been correct. The 10.0.6 servicing change merely shifted the failure mode from silently broken to loudly broken — and that loud failure is what exposed the underlying vulnerability.
How Data Protection authenticates payloads
Before diving into the bug, it helps to understand what a Data Protection payload looks like. When you call IDataProtector.Protect(plaintext), the system produces a byte array with this structure:
| Magic Header (4 bytes) | Key ID (16 bytes) | Key Modifier (16 bytes) | IV (16 bytes) | Ciphertext (variable) | HMAC Tag (32 bytes) |
The magic header and key ID identify which key ring entry to use. The key modifier feeds into a key derivation function (SP800-108 in CTR mode with HMAC-SHA512) to derive two subkeys: one for AES-256-CBC encryption and one for HMAC-SHA256 validation.
The critical part is the HMAC tag at the end. It is computed over the IV and ciphertext bytes only — not the key modifier, because the modifier is already mixed into the key derivation. During decryption, the system recomputes the HMAC over the same range and compares it using a time-constant comparison. If the tags do not match, the payload is rejected.
That is how it is supposed to work. The CNG-based encryptor on Windows has done this correctly since the Data Protection system was introduced. The managed encryptor, used everywhere else, had a different story.
The bug: HMAC over the wrong bytes
The ManagedAuthenticatedEncryptor class handles all authenticated encryption on non-Windows platforms. Its encrypt path is roughly:
- Generate a random key modifier and IV
- Derive encryption and validation subkeys from the master key + key modifier
- Encrypt the plaintext with AES-256-CBC
- Compute HMAC-SHA256 over the IV and ciphertext
- Assemble the payload:
keyModifier | IV | ciphertext | hmacTag
Step 4 is where the bug lived. The managed encryptor was computing the HMAC over the wrong byte range of the output buffer. Instead of covering IV | ciphertext, the slice calculation was off — it was hashing a range that included parts of the key modifier or missed parts of the ciphertext, depending on the payload size. Worse, the computed hash was then written to a location that did not correspond to the HMAC tag field in the final payload, effectively discarding it.
The result: the HMAC tag in every payload produced by the managed encryptor was uninitialised or stale memory. And during decryption, the validation logic suffered from the same offset error, meaning it was checking the wrong bytes against the wrong tag. Two wrongs made a right — decryption "worked" because both sides were consistently wrong in the same way.
// Simplified illustration of the bug (not actual source)
// The HMAC should cover IV + ciphertext
var ivAndCiphertext = buffer.Slice(keyModifierLength, ivLength + ciphertextLength);
// But the buggy code computed something like:
var wrongSlice = buffer.Slice(wrongOffset, wrongLength);
HMACSHA256.HashData(validationSubkey, wrongSlice, wrongDestination);
// The tag landed in the wrong place or was overwritten
Why it matters: CWE-347 in practice
CVE-2026-40372 is classified as CWE-347: Improper Verification of Cryptographic Signature. The CVSS 3.1 vector tells the story:
AV:N / AC:L / PR:N / UI:N / S:U / C:H / I:H / A:N
- Network-accessible — the attacker sends a crafted HTTP request
- Low complexity — no race conditions or special configurations needed
- No privileges required — works against unauthenticated endpoints
- No user interaction — no phishing or social engineering needed
- High confidentiality and integrity impact — read files, modify data, escalate to SYSTEM
In concrete terms: if you use cookie authentication (which is the default for ASP.NET Core Identity, Blazor Server, and many SPA setups), an attacker who understands the payload format can construct a forged authentication cookie with arbitrary claims — an admin role, a different user ID, whatever they like. The HMAC validation that should reject the forgery was not functioning.
Anti-forgery tokens, TempData protected via Data Protection, and any custom uses of IDataProtector were equally affected.
Who is affected
The vulnerability scope depends on which encryptor your application uses:
Affected by default:
- Any ASP.NET Core 10.0 application running on Linux, macOS, or any non-Windows platform. The Data Protection system automatically selects the managed encryptor (
ManagedAuthenticatedEncryptor) when CNG is not available. - Self-contained deployments on non-Windows that bundle the vulnerable
Microsoft.AspNetCore.DataProtectionversions 10.0.0 through 10.0.6.
Affected by configuration:
- Windows applications that explicitly opted into managed algorithms via
UseCustomCryptographicAlgorithmswith aManagedAuthenticatedEncryptorConfiguration. - Applications targeting
net462ornetstandard2.0that referenceMicrosoft.AspNetCore.DataProtection10.0.0–10.0.6.
Not affected:
- Windows applications using the default configuration (CNG-based encryptor).
- Applications running .NET 8 or .NET 9 — the buggy code path was introduced during .NET 10 development and was never backported.
- Applications that do not use Data Protection at all (rare for ASP.NET Core, since it underpins authentication cookies and anti-forgery).
// IMPORTANT
If you deploy to Linux containers — which includes most Docker-based, Kubernetes, and cloud-native setups — you are in the "affected by default" category. This is not a niche configuration.
How to fix it
Update to .NET 10.0.7. The fix corrects the byte range used for HMAC computation in both the encrypt and decrypt paths of ManagedAuthenticatedEncryptor.
If you use the .NET SDK:
dotnet --list-sdks
# Verify 10.0.xxx is installed, then update
dotnet workload update
If you reference the package directly:
<PackageVersion Include="Microsoft.AspNetCore.DataProtection" Version="10.0.7" />
For self-contained deployments, you need to rebuild against the updated runtime. Framework-dependent deployments pick up the fix automatically once the host has the 10.0.7 runtime installed.
Verify the installed version:
dotnet --info | grep "Microsoft.AspNetCore.App 10.0"
You should see 10.0.7 or later. If you still see 10.0.6 or earlier, the update has not been applied.
// TIP
If you manage deployments across multiple environments, use a health check endpoint that reports the runtime version. This makes it straightforward to verify the patch has been rolled out everywhere.
The decryption regression angle
There is a secondary concern. If your application protected data under .NET 10.0.5 or earlier (using the buggy HMAC), that data has an incorrect HMAC tag baked into it. After updating to 10.0.7, the now-correct HMAC validation will reject those old payloads.
For authentication cookies, this is a non-issue — users simply get logged out and re-authenticate. The cookies are short-lived by design.
For long-lived protected data (encrypted configuration values, tokens stored in a database, etc.), you may need to re-protect those values after updating. The Data Protection system's key rotation handles this transparently for most use cases, but if you have stored protected payloads outside the normal key management flow, audit them.
// WARNING
Do not disable HMAC validation or downgrade to work around the decryption regression. The regression is the correct behaviour — it means validation is finally working. Downgrading re-exposes the vulnerability.
Common pitfalls
"We're on Windows, so we're fine." Probably, but check. If anyone on your team configured UseCustomCryptographicAlgorithms with ManagedAuthenticatedEncryptorConfiguration — perhaps for FIPS compliance or cross-platform key portability — you are using the managed path regardless of the OS.
"We don't use cookies, we use JWT bearer tokens." Data Protection is not just for cookies. Anti-forgery tokens, TempData, and any explicit IDataProtector usage go through the same pipeline. If your API has a Razor-based admin panel, a Blazor component, or uses [ValidateAntiForgeryToken] anywhere, you are exposed.
"We'll update next sprint." This is a CVSS 9.1 with network access, no privileges, and no user interaction. The exploit is straightforward once an attacker understands the payload format, which is publicly documented. Treat this as a same-day patch.
"We're on .NET 8 LTS, this doesn't affect us." Correct. The managed encryptor bug was introduced in .NET 10.0.0. If you are on .NET 8 or .NET 9, you are not affected by this specific CVE. But do still apply the regular April 2026 servicing updates for the other vulnerabilities.
Summary
- CVE-2026-40372 is a CVSS 9.1 critical vulnerability in
Microsoft.AspNetCore.DataProtectionversions 10.0.0 through 10.0.6. - The managed authenticated encryptor computed its HMAC over the wrong bytes and discarded the result, effectively disabling payload authentication.
- Every ASP.NET Core 10 application on Linux or macOS was affected by default. Windows applications using custom managed algorithms were also affected.
- An attacker could forge authentication cookies and escalate privileges without possessing the encryption key.
- The fix is .NET 10.0.7, released as an emergency out-of-band update on 21 April 2026.
- Update immediately, rebuild self-contained deployments, and verify with
dotnet --info. - Expect short-lived data (cookies) to be invalidated after the update — this is correct and expected behaviour.