How this bug class keeps getting shipped
The pattern surfaces again this week, in two unrelated products from two unrelated vendors, filed under two unrelated CWE labels. Strip the marketing nouns off and the shape is identical. Two parsers in the same request pipeline disagree about what a string means. One of them is enforcing a security decision. The other is doing the work. The gap between them is the vulnerability.
This bug class has many aliases: HTTP parser confusion, path confusion, URI normalization bypass, dual-decode. The anatomy is always the same.
The lead: an unauthenticated admin bypass in a management plane
On 2026-10-13, Cisco published an advisory for CVE-2026-76504, an authentication bypass in Catalyst SD-WAN Manager. The vendor's own description is unusually precise about the mechanism:
> This vulnerability is due to improper handling of URI encoding in an HTTP request, which allows the request to bypass an authentication rule that is intended to restrict access to a specific API endpoint.
The API has a session-based authentication layer, implemented as an authentication rule: a filter that inspects the request URI and decides whether the request may proceed. The handler behind the rule is the real API endpoint. For the attack to work, the rule and the handler must examine the same incoming URI and reach different conclusions about which endpoint it addresses.
That mismatch is the entire class. Here is the generic shape of it, drawn as two requests against a placeholder deployment at example.com:
GET /dataservice/admin/users HTTP/1.1
Host: example.com
HTTP/1.1 401 Unauthorized
GET /dataservice/%61dmin/users HTTP/1.1
Host: example.com
HTTP/1.1 200 OK
The second request reaches the handler because the authentication rule performs a literal match on the raw path and does not see admin. The handler, further down the stack, percent-decodes the path before dispatching, and serves the privileged endpoint. The attacker needed no credentials. Cisco states that a successful exploit grants the privileges of the admin user.
The reason this keeps shipping is almost always structural. The authentication component is written to be defensive and literal: it rejects what it does not recognise. The handler, developed months later by a different team, is written to be permissive: it accepts anything the user might reasonably send. Permissive decoding downstream of a literal check is the whole flaw. The same shape also appears with mixed case (/Admin), trailing dots (/admin.), path parameters (/admin;x=1), redundant slashes (//admin), overlong UTF-8, backslash on Windows paths, and in HTTP/2 pseudo-header rewrites. Each is its own sub-literature.
Am I exposed?
For CVE-2026-76504 specifically, the only reliable answer is to apply the fixed software release Cisco published; the advisory explicitly notes there are no workarounds. For the class, ask these questions before addressing any individual product:
- Where in your management plane does an authentication rule read a raw URI from the request line, and is the handler behind it in the same process (same parser) or a different one?
- Does your reverse proxy canonicalize paths before forwarding them, and does the backend trust that canonicalization or redo it?
- Do your access logs preserve the raw request-URI as the client sent it, or has it been normalized before it reaches the SIEM? If normalized, you cannot see this class in historical data.
A retro-hunt worth running: for any high-privilege API path, extract raw request-URIs from the last 30 days and bucket them by their decoded, lower-cased, redundant-slash-collapsed form. Any raw bucket not already represented by its canonical form is a candidate for review. A 403 at the raw form followed by a 200 at a decoded form from the same source address, within seconds, is close to a positive signature.
The reinforcement: a path traversal that just hit KEV
CISA added CVE-2021-3199 to the Known Exploited Vulnerabilities catalog on 2026-10-08. The product is ONLYOFFICE Docs. The flaw is described as a path traversal via a /.. sequence in an image upload parameter, exploitable when JWT is used, leading to remote code execution.
This is the same class with the roles swapped. The security decision is "the user is authenticated, and the request body is a valid JWT-signed upload." The handler then takes a filename-shaped parameter from the upload and uses it as a path on the server's filesystem. The authentication layer examined JWT claims. It did not examine that parameter. The filesystem call does the opposite: it ignores JWT claims and reads the parameter directly. A /.. segment walks the storage path upwards, and a write into an executable location closes the loop to code execution.
Both bugs share the same root cause. In each case, the component that made the security decision examined a different projection of the request than the component that took the privileged action. In the Catalyst SD-WAN Manager case, the two projections are two decodings of the request-URI. In the ONLYOFFICE Docs case, they are two different fields of the request entirely. The class is "authority decided on projection A, action taken on projection B."
CISA's current KEV remediation directive, BOD 26-04 (Prioritizing Security Updates Based on Risk, effective 2026-06-10), obligates federal civilian executive branch agencies to remediate KEV entries and inherits the KEV criteria from the directive it superseded. CVE-2021-3199 is now in scope under that directive. The vendor guidance in the KEV entry is sharper than usual: the affected product may be end-of-life, and users are advised to discontinue use or move to a supported version rather than rely on a patch.
The engineering fix
The defensive pattern that kills this class is the same one every time, and it is boring enough that teams keep skipping it:
- Normalize once, at the edge, before any authorization check runs. Percent-decode, Unicode-normalize, resolve
.., collapse redundant separators. Reject anything not already in canonical form at the authorization boundary, rather than quietly rewriting it. - Make the authorization layer and the handler share a parser. If they cannot share the parser, they must share a post-parse representation: a structured object, not a string.
- Deny by default. An authentication rule written as "block these paths" is a bug waiting to be filed. Write it as "allow these paths, deny everything else," and derive the allow-list from the handler table rather than from a reviewer's memory.
- Add adversarial fuzzing of the authorization boundary itself, not just the handlers. The handlers are not where this class lives.
A product that gets those four right ships this bug class far less often than one that does not. The two advisories above are this week's reminder of what the alternative looks like.
Verifiable security.