Feb 10, 2026·6 min read·32 visits
The .NET COSE parser fails to handle CBOR 'indefinite-length' maps correctly. A loop condition comparing an integer to null evaluates to false, causing the parser to skip validating the message headers. This allows attackers to forge signatures and spoof identities.
A critical logic error in the Microsoft .NET 'System.Security.Cryptography.Cose' library allows attackers to bypass signature verification. By utilizing CBOR indefinite-length encoding, an attacker can trick the parser into skipping the Protected Header bucket entirely. This results in the acceptance of spoofed messages because critical security parameters—like the signature algorithm—are never validated.
COSE (CBOR Object Signing and Encryption) is essentially the binary, cool cousin of JSON Web Tokens (JWT). It is the backbone of modern protocols like WebAuthn (FIDO2) and various IoT security standards. When you log into a website using your fingerprint or FaceID, there's a good chance COSE is handling the cryptographic handshake under the hood.
But here is the problem: Parsing binary formats is hard. Unlike JSON, which is just text, CBOR (Concise Binary Object Representation) has multiple ways to say the same thing. You can say, "Here comes a map with 5 items," or you can say, "Here starts a map, keep reading until I say stop." That second method is called indefinite-length encoding.
CVE-2026-21218 is what happens when a developer assumes everyone plays by the first rule. It’s a spoofing vulnerability that arises not from complex buffer overflows or heap spraying, but from a simple, almost philosophical question in C#: What happens when you ask if zero is less than null?
The vulnerability lives in System.Security.Cryptography.Cose, specifically in how it parses the Protected Headers. These headers contain critical metadata, such as the alg (algorithm) used to sign the message or crit (critical) headers that the verifier must understand.
In the .NET implementation, the parser used a standard for loop to iterate through the map elements. It relied on reader.ReadStartMap() to get the number of items. Here is the catch: if the CBOR map uses indefinite-length encoding (marked by byte 0xBF), the ReadStartMap() method returns null (because the length is unknown).
The code looked something like this:
int? length = reader.ReadStartMap();
for (int i = 0; i < length; i++)
{
// Parse critical headers
}In C#, the comparison i < length when length is null evaluates to false. It doesn't throw an exception; it just silently decides the condition is not met. Consequently, the loop body—the part responsible for validating the signature algorithm and checking critical constraints—is skipped entirely. The code thinks it parsed an empty map and moves on, leaving the door wide open.
Let's look at the fix, which highlights exactly how dangerous the original logic was. The developers had to rip out the length-based for loop and replace it with a state-based while loop that actually looks at the data stream.
The Vulnerable Pattern:
// The 'length' is null for indefinite maps.
// The loop never runs. The headers are ignored.
int? length = reader.ReadStartMap();
for (int i = 0; i < length; i++)
{
DecodeHeader(reader);
}The Fixed Code (Patch 6abb139):
reader.ReadStartMap();
// Now we don't care about the length count.
// We keep reading until we hit the 'EndMap' marker.
while (true)
{
CborReaderState state = reader.PeekState();
if (state == CborReaderState.EndMap)
{
reader.ReadEndMap();
break;
}
DecodeHeader(reader);
}By checking the state of the reader (PeekState) instead of trusting a nullable integer count, the parser is forced to process every byte of the header, regardless of how the attacker encoded it. This effectively closes the bypass.
To exploit this, an attacker doesn't need to steal a private key. They just need to confuse the bouncer. Here is how a spoofing attack plays out:
CoseSign1 message.0xA1 for a map of size 1), the attacker starts the map with 0xBF (Start Indefinite Map) and immediately closes it with 0xFF (Break), or includes malicious headers inside it.The Result: The .NET parser reads the 0xBF, gets null for the length, and skips the header validation loop. It doesn't see an algorithm header. It doesn't see any critical constraints. If the application logic defaults to a specific algorithm or fails to check if headers were actually processed, it proceeds to "verify" the signature against an empty set of constraints—or worse, assumes the message is valid because no validation errors were thrown.
> [!NOTE]
> This is particularly devastating for the crit (Critical) header parameter. RFC 9052 mandates that if a crit header is present, the verifier must understand it or reject the message. By using indefinite encoding, the attacker can hide headers that would otherwise cause the message to be rejected.
This isn't just a parsing error; it's an Integrity violation of the highest order (CVSS I:H).
Identity Spoofing: If your application uses COSE for authentication (like verifying a signed token), an attacker can forge a token that looks valid to the system but was never signed by the real private key.
IoT Command Injection: Many IoT devices use COSE to sign firmware updates or command messages. An attacker could send a "Shutdown" or "Unlock" command signed by... nobody. The parser, skipping the validation logic, might accept the command as legitimate, leading to physical consequences.
Data Forgery: In financial or medical systems exchanging signed records, this allows an attacker to inject false data records that appear to be cryptographically verified.
Microsoft released the fix in the February 2026 Patch Tuesday. The remediation is straightforward: Update your .NET runtime.
Fixed Versions:
If you are manually managing NuGet packages, ensure System.Security.Cryptography.Cose is updated to the latest servicing version. For developers writing their own CBOR parsers: Never trust the length. Always implement a state-based reader that handles both definite and indefinite lengths, or explicitly reject indefinite-length encoding if your spec allows it (Canonical CBOR usually prohibits it, but parsers must be robust).
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N| Product | Affected Versions | Fixed Version |
|---|---|---|
.NET 8.0 Microsoft | < 8.0.24 | 8.0.24 |
.NET 9.0 Microsoft | < 9.0.13 | 9.0.13 |
.NET 10.0 Microsoft | < 10.0.3 | 10.0.3 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-166 |
| Attack Vector | Network |
| CVSS Score | 7.5 (High) |
| Impact | Integrity Loss (Spoofing) |
| Root Cause | Logic error in indefinite-length CBOR parsing |
| Exploit Status | Plausible / Trivial Logic |
The software does not handle or incorrectly handles a missing special element, which can lead to unexpected behavior.