FlawOpen

flawopen.com/Teardowns/cve-2026-76504-cisco-sdwan-api-authentication-bypass

● CVE-2026-76504 · CVSS 9.8[1] · Critical
FlawOpen Security Research

CVE-2026-76504: Cisco SD-WAN Manager Authentication Bypass

CVE-2026-76504 lets an unauthenticated remote attacker bypass an API authentication rule in Cisco Catalyst SD-WAN Manager and obtain admin-level API access. Cisco confirms active exploitation; upgrade to the fixed release for your branch and investigate the manager before assuming it is clean.[1], [5]

CVSS vectorCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H[1]
💡 Plain English Explainer (ELI5)

Think of a guarded door whose security check recognizes one written form of its address. An attacker changes the address's spelling with URI encoding, and one part of the system treats it as the same door while the security rule does not. Cisco says this mismatch let a request skip authentication and reach the API as an administrator. The repair is to handle the address consistently and enforce the same access rule; for operators, Cisco's supported fix is a software upgrade.[1]

Core Concepts & Subsystem Terms

URI encoding
A way to represent characters in a URL path with percent-encoded bytes. Different layers must decode and compare the path consistently.[1], [7]
Authentication bypass
A request reaches a protected function without the system establishing the caller's identity as required.[1]
API session rule
The manager's rule for deciding whether an API request has a valid authenticated session before it reaches an endpoint.[1]
CWE-177
Improper Handling of URL Encoding: inconsistent processing of encoded URL data can undermine a security decision. Cisco assigns this weakness to the CVE.[1], [7]

Framework mappings

Root Cause Analysis

Cisco attributes CVE-2026-76504 to improper handling of URI encoding in HTTP requests within Catalyst SD-WAN Manager's API session-based authentication. A crafted request can bypass an authentication rule meant to restrict a specific API endpoint, granting access as the admin user. Cisco rates it CVSS 3.1 9.8 Critical, says the product is affected regardless of system configuration, and reports that PSIRT knew of active exploitation in September 2026. The advisory gives an encoded j_security_check request as an IOC example and explicitly warns that any one URI-encoded character can be used; do not treat that one sample as a complete detection signature. Cisco publishes no vulnerable source code or patch diff, so the code pair below is an illustrative authorization design, not Cisco source or a reproduction. Cisco lists fixed releases by branch and says there is no workaround that fully addresses the flaw. Network restrictions and the Live Protect shield are temporary mitigations; the shield can affect legitimate logins and does not replace upgrading.[1], [5]

CVE-2026-76504 fixed releases by deployment

Deployment / branchFixed releaseRequired action
On-prem releases earlier than 20.9Move to a supported branch with a listed fixed release.Migrate; do not remain on an earlier unsupported branch.
On-prem 20.9 branch20.9.10.1Upgrade every manager to this release or later in the supported branch.
On-prem 20.12 branch20.12.8.2Upgrade every manager to this release or later in the supported branch.
On-prem 20.15 branch20.15.6.1Upgrade every manager to this release or later in the supported branch.
On-prem 20.18 branch20.18.4.1Upgrade every manager to this release or later in the supported branch.
On-prem 26.1 branch26.1.2.1Upgrade every manager to this release or later in the supported branch.
On-prem 26.2 branch26.2.1Upgrade every manager to this release or later in the supported branch.
Cisco SD-WAN Cloud (Cisco Managed)20.15.605 or later; Cisco says the hosted service is fixed.Confirm this is the managed service; no customer action is required for its rollout.

Step-by-Step Attack Flow

Step 1

A remote request reaches the manager API

No account or user interaction is required. Internet exposure increases risk; the vendor says the flaw applies regardless of system configuration.[1]

Step 2

URI-encoded path data bypasses an authentication rule

Cisco identifies inconsistent URI-encoding handling in API session authentication. Public material does not disclose the vulnerable source implementation.[1]

Step 3

The API treats the request as admin

Successful exploitation grants admin-user privileges. Cisco confirms active exploitation but does not publish a complete post-access chain.[1], [5]

Step 4

Upgrade and investigate

Collect admin-tech files first, upgrade all managers to the correct fixed release, then ask Cisco TAC to scan the evidence. Do not wait for TAC before upgrading.[1], [2]

Source Code: Flaw vs. Secure Implementation

Cisco does not publish the vulnerable source or patch diff. This Python example shows a general design rule, not Cisco code: route matching and authorization must use one validated canonical request target, and protected endpoints must require an authenticated principal. Use the router/framework's documented normalization semantics; do not add ad hoc decoding or double-decode paths. The supported remediation for CVE-2026-76504 is to upgrade to Cisco's branch-specific fixed release.[1], [7]

Source excerpt: Illustrative Python URI canonicalization and authorization boundary; not Cisco source

UNPATCHED FLAW
from urllib.parse import unquote, urlsplit


def dispatch(raw_target, session, routes):
    # One layer checks the still-encoded path.
    path_for_auth = urlsplit(raw_target).path
    if path_for_auth.startswith("/api/") and session is None:
        raise PermissionError("authentication required")

    # A later layer decodes before route lookup. The two decisions can disagree.
    route_path = unquote(path_for_auth)
    return routes[route_path]()
HARDENED SECURE PATCH
import re
from urllib.parse import unquote, urlsplit


def canonical_path(raw_target):
    raw_path = urlsplit(raw_target).path
    if re.search(r"%(?![0-9A-Fa-f]{2})", raw_path):
        raise ValueError("malformed URI encoding")

    path = unquote(raw_path, errors="strict")
    if "%" in path or "\\" in path:
        raise ValueError("ambiguous path encoding")
    if any(part in {".", ".."} for part in path.split("/")):
        raise ValueError("path traversal segment")
    return path


def dispatch(raw_target, session, routes):
    path = canonical_path(raw_target)  # Decode and validate exactly once.
    route = routes.get(path)
    if route is None:
        raise LookupError("route not found")

    requires_authentication, handler = route
    if requires_authentication and session is None:
        raise PermissionError("authentication required")
    return handler()

Engineering & System Hardening Checklist

Sources