Executive Summary
CVE-2026-20182 is a critical (CVSS 10.0, CWE-287) authentication bypass in the Cisco Catalyst SD-WAN Controller — historically called “vSmart” — that lets an unauthenticated remote attacker promote themselves to a fully authenticated peer of the controller. The bug lives in vdaemon, the DTLS control-plane service running on UDP 12346, and is triggered by a single missing branch in vbond_proc_challenge_ack(): when a CHALLENGE_ACK message arrives with device_type = 2 (vHub), the function falls through every verification path and unconditionally sets the per-peer authenticated flag.
From there the attacker is a peer of the SD-WAN control plane and can send MSG_VMANAGE_TO_PEER (type 14) requests that the controller treats as legitimate vManage automation. The handler for those messages opens /home/vmanage-admin/.ssh/authorized_keys in append mode and writes the attacker’s public key into it — no sanitisation, no validation. The attacker then SSHes in as the high-privileged vmanage-admin service account on TCP 830 (NETCONF-over-SSH) and runs arbitrary configuration commands against the entire SD-WAN fabric. Discovered by Stephen Fewer and Jonah Burgess at Rapid7 and disclosed in coordination with Cisco; a Metasploit module (auxiliary/admin/networking/cisco_sdwan_vhub_auth_bypass) shipped alongside the writeup. Fixed releases are available across every supported branch — upgrade now.

At a Glance
| Field | Value |
|---|---|
| CVE | CVE-2026-20182 |
| CVSS v3.1 base score | 10.0 (Critical) |
| CVSS vector | AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H |
| CWE | CWE-287 (Improper Authentication) |
| Affected product | Cisco Catalyst SD-WAN Controller (formerly vSmart) |
| Affected component | vdaemon — UDP 12346 (DTLS control plane) |
| Vulnerable function | vbond_proc_challenge_ack() |
| Attack vector | Remote, network, unauthenticated |
| Post-auth primitive | MSG_VMANAGE_TO_PEER — arbitrary ~vmanage-admin/.ssh/authorized_keys append |
| Discoverers | Stephen Fewer & Jonah Burgess (Rapid7) |
| Public exploit | Metasploit: auxiliary/admin/networking/cisco_sdwan_vhub_auth_bypass (PR #21463) |
| Vendor advisory | cisco-sa-sdwan-rpa2-v69WY2SW |
| Patch status | FIXED — see remediation table below |
Overview
The Cisco Catalyst SD-WAN Controller is the control-plane brain of a Catalyst SD-WAN deployment: it runs OMP, distributes routing state to the data-plane edge devices, and is the trust anchor that the rest of the fabric peers with. The advisory describes a previously-unknown bypass in the controller’s DTLS-based inter-controller peering service. It is distinct from the earlier CVE-2026-20127 issue — same module, different bug, not a patch bypass — and the attack is reachable from any host that can deliver UDP packets to port 12346 on the controller.
Once authenticated as a peer, the attacker can pivot to MSG_VMANAGE_TO_PEER — a message type intended for automated vManage-to-controller administration — and use it to write SSH public keys directly into the vmanage-admin account’s authorized_keys file. vmanage-admin is a high-privileged service account exposed by NETCONF-over-SSH on TCP 830, so the SSH-key write turns into full configuration-level control of the SD-WAN fabric. Net effect: any host with network reach to UDP 12346 on the controller can become a privileged operator of the entire SD-WAN deployment.
Technical Analysis
The SD-WAN controller exposes a small, well-defined attack surface on the network: OpenSSH on TCP 22, NETCONF-over-SSH on TCP 830, and the vdaemon DTLS control plane on UDP 12346. The first two are authentication-gated; the third is the one that goes wrong here.
| Port | Protocol | Service |
|---|---|---|
| 22 | TCP | SSH (OpenSSH) |
| 830 | TCP | NETCONF over SSH |
| 12346 | UDP | vdaemon DTLS control plane |
UDP 12346 carries inter-controller peering: OMP routing updates, control-plane peer state, and the handshake by which a new device is admitted as a recognised peer. The peering protocol is multi-phase. After a DTLS handshake (during which the certificate is parsed but, per the writeup, errors are logged and the connection continues), the controller sends a CHALLENGE message containing 256 random bytes. The peer responds with a CHALLENGE_ACK that the controller is supposed to verify against the peer’s claimed device type. The controller then sends CHALLENGE_ACK_ACK, the peer sends Hello, and the peer transitions to UP — an active member of the SD-WAN control plane.
Attacker vSmart
| |
|──── DTLS Handshake (any cert) ───────────>| ← cert verify logs error but returns OK
| |
|<──── CHALLENGE (msg_type=8) ──────────────│ ← 256 random bytes + TLVs
| |
|──── CHALLENGE_ACK (msg_type=9) ──────────>| ← device_type=2 (vHub) → NO VERIFICATION
| |
|<──── CHALLENGE_ACK_ACK (msg_type=10) ─────│ ← peer->authenticated = 1
| |
|──── Hello (msg_type=5) ──────────────────>| ← passes auth check, peer goes UP
| |
|<──── Hello (msg_type=5) ──────────────────│ ← peer-type:vhub, new-state:up
The vdaemon wire format is a 12-byte header followed by the message-specific payload. The first byte’s low nibble identifies the message type (CHALLENGE, CHALLENGE_ACK, Hello, etc.); the second byte’s high nibble carries the claimed device type, which is the field at the centre of this vulnerability.
| Byte offset | Byte size | Field | Notes |
|---|---|---|---|
| 0 | 1 | msg_type | Low nibble = type, high nibble = version |
| 1 | 1 | device_info | High nibble = device_type, low nibble = flags |
| 2 | 1 | flags | Standard value of 0xA0 |
| 3 | 1 | padding | Always 0x00 |
| 4–7 | 4 | domain_id | Big-endian uint32 |
| 8–11 | 4 | site_id | Big-endian uint32 |
| Value | Device type | Role |
|---|---|---|
| 1 | vEdge | Data-plane router |
| 2 | vHub | Hub router |
| 3 | vSmart | Control-plane controller |
| 4 | vBond | Orchestrator (trust anchor) |
| 5 | vManage | Management plane |
| 6 | ZTP | Zero-touch provisioning |
The vulnerability is in vbond_proc_challenge_ack(), the function that processes the CHALLENGE_ACK message and decides whether to mark the peer as authenticated. The function uses a chain of if statements keyed on device_type; each branch performs the verification appropriate to that type. The decompilation below makes the structure obvious — and the gap obvious too.
// vdaemon!vbond_proc_challenge_ack()
// After extracting serial number from peer certificate via
// X509_get_serialNumber() / ASN1_INTEGER_to_BN() / BN_bn2hex()
// ...snip...
if ( *(_DWORD *)(a3 + 8) == 3 || *(_DWORD *)(a3 + 8) == 5 ) // <--- [1]
{
// vSmart (type 3) or vManage (type 5): Certificate chain verification
v24 = is_serial_duplicate(v22, *(_DWORD *)(a3 + 8), ...);
if ( v24 )
{
if ( (unsigned __int8)vbond_peer_dup_check(a1, a2, v24, ...) ) // <--- [2]
{
v19 = 36; // ERR: Duplicate Serial
goto LABEL_179; // REJECT
}
}
}
// ...snip...
// Second verification block - additional cert & state checks
if ( *(_DWORD *)(a3 + 8) == 3 && *(_DWORD *)(a1 + 8) == 3 // <--- [3]
|| *(_DWORD *)(a3 + 8) == 5 && *(_DWORD *)(a1 + 8) == 3
|| *(_DWORD *)(a3 + 8) == 5 && *(_DWORD *)(a1 + 8) == 5
|| *(_DWORD *)(a3 + 8) == 5 && *(_DWORD *)(a1 + 8) == 4
|| *(_DWORD *)(a3 + 8) == 3 && *(_DWORD *)(a1 + 8) == 4 )
{
v19 = vdaemon_dtls_verify_peer_cert(a2); // Full certificate verification
if ( v19 )
v18 = 0;
vdaemon_send_challenge_ack_ack(a1, *(_QWORD *)(a2 + 1232), a2, v18);
if ( v18 != 1 )
goto LABEL_179; // REJECT on verification failure
vbond_send_ssh_keys_to_vmanage_peer(a1, a2);
}
if ( *(_DWORD *)(a3 + 8) == 1 // <--- [4]
&& (dword_2A1A28 == 4 || dword_2A1A28 == 3 || dword_2A1A28 == 5) )
{
// vEdge (type 1): Hardware/virtual edge certificate verification
// ... challenge signature, board ID, OTP verification ...
if ( vdaemon_verify_peer_bidcert(a2, ...) )
goto LABEL_179; // REJECT on failure
}
// *** NO CODE PATH FOR device_type == 2 (vHub) *** // <--- [5]
*(_BYTE *)(a2 + 70) = 1; // peer->authenticated = true // <--- [6]
return 0LL; // Success
The pattern is clean: each device class has its own verification branch, but vHub (type 2) has none. Whether by deliberate “vHubs are trust-anchored elsewhere” logic or by a missing else-branch, the practical effect at runtime is that a CHALLENGE_ACK declaring device_type = 2 skips every guard and falls through to the unconditional peer->authenticated = 1 at marker [6].
| Device type | Value | Verification | Result |
|---|---|---|---|
| vEdge | 1 | HW cert, challenge signature, board ID, OTP | Verified |
| vHub | 2 | None | Falls through to peer->authenticated = 1 |
| vSmart | 3 | Cert chain, serial lookup, duplicate check | Verified |
| vBond | 4 | N/A (trust anchor — handled elsewhere) | — |
| vManage | 5 | Cert chain, serial lookup, duplicate check | Verified |
The next question is whether the attacker can reach vbond_proc_challenge_ack() without being authenticated already. The dispatch gate inside vbond_proc_msg() explicitly allows the CHALLENGE family of messages (and Hello, Data, TEAR_DOWN, a few more) on a peer whose authenticated flag is still 0 — precisely because those messages are how the peer becomes authenticated.
// vdaemon!vbond_proc_msg()
// Pre-dispatch authentication gate:
if ( *(_BYTE *)(v100 + 70) != 1 // <--- [1]
&& *(_DWORD *)(a3 + 4) != 5 // msg != Hello
&& *(_DWORD *)(a3 + 4) != 8 // msg != CHALLENGE
&& *(_DWORD *)(a3 + 4) != 9 // msg != CHALLENGE_ACK
&& *(_DWORD *)(a3 + 4) // msg != NEW_CHALLENGE_ACK
&& *(_DWORD *)(a3 + 4) != 10 // msg != CHALLENGE_ACK_ACK
&& *(_DWORD *)(a3 + 4) != 7 // msg != Data
&& *(_DWORD *)(a3 + 4) != 11 // msg != TEAR_DOWN
// ...snip...
)
{
// ...snip...
// "Received an unexpected message from an un-authenticated device"
return 20;
}
Hello is also in that allowlist, but Hello itself has a secondary check inside its handler: after a CHALLENGE_ACK_ACK has been processed, the Hello handler verifies that peer->authenticated is 1 before transitioning the peer to UP. So the sequence the attacker needs is exactly the natural one: CHALLENGE_ACK to flip the flag, then Hello to advance the peer state machine.
// Case 5 (Hello) in vbond_proc_msg - line 20362
case 5:
// ...snip...
if ( *(_BYTE *)(v100 + 70) != 1 ) // <--- [2]
{
// "Received an unexpected HELLO from un-authenticated device"
// ... cleanup and reject ...
return 0LL;
}
// Process Hello normally - peer transitions to UP
Once the peer is UP, the attacker has access to the messages the dispatcher gates behind authentication. The most useful of those is MSG_VMANAGE_TO_PEER (message type 14), the channel by which vManage automates peer configuration. Its handler, vbond_proc_vmanage_to_peer(), opens /home/vmanage-admin/.ssh/authorized_keys for append and writes the supplied key buffer with fputs() — no sanitisation, no per-call authorisation, no rate limit.
// vdaemon!vbond_proc_vmanage_to_peer()
// ...snip...
stream = fopen("/home/vmanage-admin/.ssh/authorized_keys", "a+"); // <--- [1]
if ( stream )
{
if ( (unsigned __int8)read_key_data((const char *)(a3 + 32), stream) != 1 && *(_BYTE *)(a3 + 32) )
{
if ( dword_241120 > 6 )
syslog(
191,
"%s[%d]: %%%s-%d: sshkey not present, writing to file",
"vbond_proc_vmanage_to_peer",
2368LL,
aVdaemonDbgMisc,
7LL);
fputs((const char *)(a3 + 32), stream); // <--- [2]
}
fclose(stream);
}
// ...snip...
The on-the-wire MSG_VMANAGE_TO_PEER body is laid out as 768 bytes of key buffer followed by a one-byte TLV count of 0; the key buffer itself is wrapped in a leading newline, the literal SSH public-key bytes, a trailing newline, a null terminator, and zero padding to the end of the field.
| Offset | Size | Field |
|---|---|---|
| 0–767 | 768 | Key buffer ("n" + ssh_pubkey + "n" + "x00" + zero padding) |
| 768 | 1 | TLV count = 0 |
MSG_VMANAGE_TO_PEER body layout used for SSH-key injection. Source: original article.Exploitation
Rapid7 published a Metasploit auxiliary module — auxiliary/admin/networking/cisco_sdwan_vhub_auth_bypass — that performs the bypass end-to-end against a target Catalyst SD-WAN Controller. The walk-through in the advisory targets v20.12.6.1 running at 192.168.80.11 from an attacker at 192.168.80.130.

cisco_sdwan_vhub_auth_bypass. Source: original article.msf6 auxiliary(admin/networking/cisco_sdwan_vhub_auth_bypass) > set RHOSTS 192.168.80.11
msf6 auxiliary(admin/networking/cisco_sdwan_vhub_auth_bypass) > run
The module generates an RSA key-pair on the fly, walks the DTLS-handshake-into-CHALLENGE_ACK-with-device_type=2 path to flip peer->authenticated to 1, sends a Hello to bring the peer UP, then issues a MSG_VMANAGE_TO_PEER request carrying the attacker’s public key. The private key is dropped into the Metasploit loot directory.

With the injected key in vmanage-admin’s authorized_keys, a standard SSH client connects to the NETCONF-over-SSH service on TCP 830:
ssh -i /home/cryptocat/.msf4/loot/20260501115947_default_192.168.80.11_cisco.sdwan.sshk_491665.pem [email protected] -p 830

vmanage-admin. Source: original article.From the NETCONF session, a textbook <get-config> RPC pulls the controller’s running configuration. At this point the attacker has authoritative configuration control over the SD-WAN fabric.
<?xml version="1.0" encoding="UTF-8"?><hello xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"><capabilities><capability>urn:ietf:params:netconf:base:1.0</capability></capabilities></hello>]]>]]><rpc message-id="101" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"><get-config><source><running/></source></get-config></rpc>]]>]]>

get-config output from the compromised controller. Source: original article.Remediation
Cisco has released fixed software for every supported release branch; there is no workaround. Upgrade to the relevant first-fixed release for your branch:
| Cisco Catalyst SD-WAN release | First fixed release |
|---|---|
| Earlier than 20.9* | Migrate to a fixed release |
| 20.9 | 20.9.9.1 |
| 20.10 | 20.12.7.1 |
| 20.11* | 20.12.7.1 |
| 20.12 | 20.12.5.4, 20.12.6.2, 20.12.7.1 |
| 20.13* | 20.15.5.2 |
| 20.14* | 20.15.5.2 |
| 20.15 | 20.15.4.4, 20.15.5.2 |
| 20.16* | 20.18.2.2 |
| 20.18 | 20.18.2.2 |
| 26.1.1 | 26.1.1.1 |
Vendor Statement
Cisco values the role of the security research community in helping maintain a secure ecosystem and we appreciate the collaboration with Rapid7. We have released a software update to remediate the identified vulnerability. We remain committed to transparent communication and to providing our customers with the robust security and resilience they expect.
Cisco, via the Rapid7 advisory
Credit
CVE-2026-20182 was discovered and reported by Stephen Fewer (Senior Principal Security Researcher) and Jonah Burgess (Senior Security Researcher) at Rapid7, and disclosed in accordance with Rapid7’s vulnerability disclosure policy.
Disclosure Timeline
| Date | Event |
|---|---|
| 2026-03-09 | Initial Rapid7 outreach to Cisco; technical writeup & exploit code disclosed. |
| 2026-03-11 | Cisco confirms receipt; suggests May 7, 2026 disclosure date. |
| 2026-03-20 | Cisco confirms findings; CVE will be reserved. |
| 2026-04-21 | Cisco provides CVE identifier & remediation guidance. |
| 2026-04-24 | Cisco provides fix versions, CWE/CVSS alignment, requests May 14 disclosure date. |
| 2026-05-14 | Public disclosure (this advisory). |
| 2026-05-15 | Metasploit module link added to the advisory. |
Key Takeaways
- The vulnerability is structural: every other device type in
vbond_proc_challenge_ack()has an explicit verification branch, anddevice_type = 2(vHub) has none. Missing-else-branch bugs in trust-boundary state machines are a recurring class — not a Cisco-specific accident. - An unauthenticated remote attacker reaching UDP 12346 can become a fully authenticated SD-WAN peer with a single CHALLENGE_ACK and a single Hello. No race condition, no timing, no special token.
- The post-auth primitive (
MSG_VMANAGE_TO_PEER→ rawfputs()append to/home/vmanage-admin/.ssh/authorized_keys) is itself an unsanitised write to a privileged credentials file. Once the auth gate falls, the rest of the chain is mechanical. - The pivot from the bypass to
vmanage-adminNETCONF is a deliberate use of the controller’s own automation surface — the attacker becomes a vManage automation peer, not a shell user, and the SD-WAN fabric treats their RPCs as legitimate. - The
vmanage-adminaccount is a high-privileged service identity, not a human admin role. Its presence on TCP 830 widens the blast radius far beyond a single controller box. - Public exploitation is one Metasploit module away.
auxiliary/admin/networking/cisco_sdwan_vhub_auth_bypassdrops the SSH key, returns the loot path, and connects you. Asset owners should assume opportunistic scanning. - Cisco fixed it; no workarounds. Patch state, not configuration state, is the only mitigation that matters for this bug.
Defensive Recommendations
- Upgrade now. Move every Catalyst SD-WAN Controller to the first fixed release for its branch (table above). End-of-software-maintenance branches (20.11, 20.13, 20.14, 20.16, and anything earlier than 20.9) need a migration, not a patch.
- Restrict UDP 12346 reachability. The controller’s vdaemon DTLS port should only be reachable from the legitimate inter-controller peer set. Audit the upstream ACLs / security-zone policies; treat any host outside that set that can reach UDP 12346 as a CVE-2026-20182 exposure.
- Audit
/home/vmanage-admin/.ssh/authorized_keys. Inspect the file on every controller you operate. Any key whose fingerprint you do not recognise should be treated as an injection IoC. Capture the file before patching and again after. - Hunt for NETCONF sessions on TCP 830 by source IP. Legitimate NETCONF traffic should come from a small, well-known set of vManage hosts. Any TCP 830 session originating outside that set is high-fidelity.
- Watch
vdaemonsyslog for the “sshkey not present, writing to file” message. That string is emitted byvbond_proc_vmanage_to_peer()at debug level 7 immediately before the SSH-key write. It is a high-signal detection if you can elevate logging in the rollout window. - Treat any
peer-type:vhub, new-state:uplog entry on a controller as suspect. A vHub coming online unexpectedly — especially from a peer IP not in your topology — is the exact UP-transition fingerprint of the exploit chain. - Rotate
vmanage-admincredentials and SSH host keys after patching. Treat any controller that was on a vulnerable build as potentially keyed by a third party; a post-patch SSH-key inventory + rotation pass closes that loop. - Add Rapid7 InsightVM / Nexpose authenticated check. If you operate one of those products, the May 14, 2026 content release ships an authenticated check for CVE-2026-20182 — turn it on and confirm clean across the fleet before declaring the rollout done.
Conclusion
CVE-2026-20182 is the rarer kind of network-protocol bug: it is not a parser overflow, a heap corruption, or a chained logic flaw — it is a single missing branch in a per-device-type verification ladder, sitting at the front of the SD-WAN control plane’s authentication state machine, and the consequences cascade all the way to NETCONF-over-SSH control of the entire fabric. The structural lesson is one network engineers know well: if your auth ladder enumerates device types, the “else” branch matters as much as the explicit ones. The operational lesson is shorter: upgrade now, audit authorized_keys on every controller, and assume any peer reachable from outside your trusted inter-controller set may have used the window. The canonical reference remains the Rapid7 advisory together with Cisco’s cisco-sa-sdwan-rpa2-v69WY2SW.
References
- Rapid7 advisory — Jonah Burgess & Stephen Fewer (May 14, 2026)
- Cisco Security Advisory — cisco-sa-sdwan-rpa2-v69WY2SW
- Metasploit Framework PR #21463 —
cisco_sdwan_vhub_auth_bypass - Related CVE-2026-20127 — Cisco Talos writeup
- CWE-287 — Improper Authentication
- CVSS 3.1 calculator — CVE-2026-20182 vector
- Cisco SD-WAN end-of-software-maintenance listing
- Cisco Catalyst SD-WAN compatibility & supported releases
- Rapid7 Vulnerability Disclosure Policy
Original text: “CVE-2026-20182: Critical authentication bypass in Cisco Catalyst SD-WAN Controller (FIXED)” by Jonah Burgess & Stephen Fewer at Rapid7 (May 14, 2026).

