high Threat analysis

Cisco Catalyst SD-WAN Manager CVE-2026-20262: KEV Path Traversal in the Management Plane

CISA added Cisco Catalyst SD-WAN Manager CVE-2026-20262 to KEV on 2026-06-15 with a 2026-06-29 due date. Cisco says authenticated attackers with at least write access can abuse a web-UI file-upload path traversal to create or overwrite files on affected systems across all SD-WAN deployment types.

#cisco#sd-wan#cisa-kev#path-traversal#management-plane#zero-day
On this page 0% read

    Executive Summary

    CISA added CVE-2026-20262 to the Known Exploited Vulnerabilities catalog on 2026-06-15 and set a 2026-06-29 remediation due date CISA KEV. CISA classifies the issue as a Cisco Catalyst SD-WAN Manager Directory or Path Traversal Vulnerability and says it can let an authenticated remote attacker create or overwrite any file on the affected system CISA KEV.

    Cisco’s advisory describes the flaw in the SD-WAN Manager web UI: user-supplied input is not properly validated during a file upload process, so an attacker with valid credentials and at least write access can send a crafted HTTP request to a management API endpoint and write files on the underlying OS Cisco. Cisco also says the issue affects all deployment types, including on-premises, Cisco-managed cloud, Cloud-Pro, and FedRAMP, and that there are no workarounds Cisco.

    Key Facts

    Cve: CVE-2026-20262

    Vendor: Cisco

    Product: Catalyst SD-WAN Manager

    Former Product Name: SD-WAN vManage

    Kev Added: 2026-06-15

    Kev Due: 2026-06-29

    Vulnerability: authenticated file-upload path traversal leading to file creation / overwrite

    Cwe: CWE-22

    Cvss V31: 6.5

    Required Access: valid credentials with at least write access

    Affected Deployment Types:

    • On-prem deployment
    • Cisco SD-WAN Cloud-Pro
    • Cisco SD-WAN Cloud (Cisco Managed)
    • Cisco SD-WAN for Government (FedRAMP)

    First Fixed Releases:

    • 20[.]9[.]9[.]2
    • 20[.]12[.]7[.]2
    • 20[.]15[.]4[.]5
    • 20[.]15[.]5[.]3
    • 20[.]18[.]3[.]1
    • 26[.]1[.]1[.]2

    High Value Evidence:

    • request admin-tech
    • CSCwu18441
    • management-plane HTTP request logs
    • admin-tech bundles from each control component

    Evidence Assessment

    • confirmed: CISA lists CVE-2026-20262 as known exploited and assigns a due date of 2026-06-29 CISA KEV.
    • confirmed: Cisco says the flaw affects the SD-WAN Manager web UI, requires valid credentials with at least write access, and can create or overwrite arbitrary files on the underlying OS Cisco.
    • confirmed: Cisco maps the issue to bug CSCwu18441, lists the fixed release trains, and says there are no workarounds Cisco.
    • confirmed: NVD classifies the weakness as CWE-22 and mirrors the Cisco description of authenticated file creation / overwrite in the management UI NVD.
    • unknown: Cisco has not published attacker attribution, filenames, hashes, or a public exploit chain in the sources reviewed here.

    Impact Determination

    ClassificationCriteriaRequired evidenceHandling decision
    Confirmed compromiseUnexpected file creation or overwrite, unexpected admin-tech changes, or suspicious management-plane file-upload activity on an affected SD-WAN control component.admin-tech bundle, web UI/API logs, process activity, and filesystem diffs.Isolate the control component, preserve evidence, and treat the management plane as compromised until reviewed.
    Presumed exposedSD-WAN Manager is present, management access is enabled, and the release is below a fixed build.Exact release output, deployment type, and credential scope.Patch to a fixed build and audit recent file-upload activity.
    Potentially exposedSD-WAN Manager is inventoried but the exact release or access model is incomplete.Inventory and version evidence.Collect release and credential scope before declaring exposure.
    Not exposedNo affected product is present, or a fixed release is verified and review is negative.Inventory, version proof, and negative log review.Archive closure evidence.
    UnknownRequired logs, version data, or deployment records are missing.Named gap with owner and time window.Keep the management plane in scope until the gap is closed.

    Timeline

    • 2026-06-15: Cisco advisory for CVE-2026-20262 is published and CISA adds the issue to KEV Cisco CISA KEV.
    • 2026-06-15: CISA publishes the KEV feed with a 2026-06-29 due date CISA KEV.
    • 2026-06-16: Defensive analysis should prioritize current control-plane inventory and log review because the product is publicly known to be exploited CISA KEV.

    Technical Analysis

    This is a management-plane file-write bug, not a perimeter RCE. The threat surface is Cisco Catalyst SD-WAN Manager’s web UI and file-upload path handling. If an attacker already has credentials with write access, they can craft a request that causes the appliance to create or overwrite files on the underlying OS. That can become a stepping stone to root if the written file lands in a sensitive location or alters an execution path Cisco NVD [1].

    Cisco’s statement that there are no workarounds matters operationally: defenders should assume exposure remains until a fixed release is installed and the control-plane logs are reviewed. The most useful immediate question is not “is the CVE patched?” but “did anyone with write-capable management credentials touch the file-upload path during the exposure window?” Cisco CISA KEV [1].

    Affected Assets and Blast Radius

    Asset Selectors:

    • Catalyst SD-WAN Manager
    • Catalyst SD-WAN Controller
    • Catalyst SD-WAN Validator
    • SD-WAN management-plane accounts with write access

    High Value Evidence:

    • admin-tech bundles from each control component
    • management-plane HTTP request logs
    • release metadata showing the exact Cisco train and patch level

    Downstream Risk:

    • unauthorized SD-WAN configuration changes
    • overwrite of files used by the underlying OS
    • escalation from management-plane write access to root-level impact

    Indicators of Compromise

    The sources reviewed do not publish a full IOC set. Use the following selectors to scope telemetry and to hunt for suspicious management-plane use:

    Literal Selectors

    • CVE-2026-20262
    • CSCwu18441
    • request admin-tech
    • Catalyst SD-WAN Manager
    • vManage
    • 20[.]9[.]9[.]2
    • 20[.]12[.]7[.]2
    • 20[.]15[.]4[.]5
    • 20[.]15[.]5[.]3
    • 20[.]18[.]3[.]1
    • 26[.]1[.]1[.]2

    Traversal Encodings

    • ../
    • %2e%2e/
    • %2e%2e%2f
    • ..%2f

    Detection and Hunting

    Hunt Manifest: cisco-sdwan-manager-cve-2026-20262-kev-hunt-1

    • Title: SD-WAN control-plane log and exported telemetry scope
    • Question: Does the telemetry scope contain indicators associated with Cisco Catalyst SD-WAN Manager CVE-2026-20262?
    • Telemetry Family: log
    • Telemetry Context: SD-WAN admin-tech bundles, web UI access logs, and exported host telemetry
    • Positive Signal: Matches to bug ID, traversal encodings, or suspicious admin-tech activity from write-capable accounts
    #!/usr/bin/env python3
    """Scan a repository or telemetry export for Cisco CVE-2026-20262 indicators."""
    
    import argparse
    import json
    import re
    from dataclasses import dataclass
    from pathlib import Path
    from typing import Iterable
    
    DEFAULT_OUT = "hp-cisco-sdwan-manager-cve-2026-20262-kev-scope"
    DEFAULT_IOCS = "iocs.json"
    IGNORE_DIRS = {".git", "node_modules", "dist", "__pycache__", ".astro", ".next", "coverage"}
    MAX_FILE_BYTES = 2_000_000
    
    
    @dataclass(frozen=True)
    class Indicator:
        kind: str
        value: str
        label: str
        compiled: re.Pattern[str] | None = None
    
    
    def load_iocs(path: Path) -> dict:
        with path.open("r", encoding="utf-8") as fh:
            data = json.load(fh)
        if "literal_indicators" not in data or "regex_indicators" not in data:
            raise ValueError("iocs.json must define literal_indicators and regex_indicators")
        return data
    
    
    def build_indicators(iocs: dict) -> list[Indicator]:
        indicators: list[Indicator] = []
        for literal in iocs.get("literal_indicators", []):
            indicators.append(Indicator(kind="literal", value=literal, label=literal))
        for pattern in iocs.get("regex_indicators", []):
            indicators.append(
                Indicator(
                    kind="regex",
                    value=pattern,
                    label=pattern,
                    compiled=re.compile(pattern, re.IGNORECASE),
                )
            )
        return indicators
    
    
    def iter_files(root: Path) -> Iterable[Path]:
        for path in root.rglob("*"):
            if path.is_dir():
                continue
            if any(part in IGNORE_DIRS for part in path.parts):
                continue
            yield path
    
    
    def read_text(path: Path) -> str | None:
        try:
            if path.stat().st_size > MAX_FILE_BYTES:
                return None
            return path.read_text(encoding="utf-8", errors="ignore")
        except OSError:
            return None
    
    
    def scan_text(path: Path, text: str, indicators: list[Indicator]) -> list[dict]:
        hits: list[dict] = []
        for lineno, line in enumerate(text.splitlines(), start=1):
            for indicator in indicators:
                if indicator.kind == "literal":
                    if indicator.value and indicator.value in line:
                        hits.append(
                            {
                                "file": str(path),
                                "line": lineno,
                                "kind": indicator.kind,
                                "indicator": indicator.value,
                                "content": line.strip(),
                            }
                        )
                else:
                    assert indicator.compiled is not None
                    if indicator.compiled.search(line):
                        hits.append(
                            {
                                "file": str(path),
                                "line": lineno,
                                "kind": indicator.kind,
                                "indicator": indicator.value,
                                "content": line.strip(),
                            }
                        )
        return hits
    
    
    def scan_root(root: Path, indicators: list[Indicator]) -> list[dict]:
        matches: list[dict] = []
        if not root.exists():
            return matches
        for file_path in iter_files(root):
            text = read_text(file_path)
            if text is None:
                continue
            matches.extend(scan_text(file_path, text, indicators))
        return matches
    
    
    def write_matches(path: Path, matches: list[dict]) -> None:
        lines = [
            f"{m['file']}:{m['line']}:{m['kind']}:{m['indicator']}:{m['content']}"
            for m in matches
        ]
        path.write_text("\n".join(lines) + ("\n" if lines else ""), encoding="utf-8")
    
    
    def main() -> int:
        parser = argparse.ArgumentParser(description=__doc__)
        parser.add_argument("--scan-root", type=Path, default=Path("."), help="Directory to scan")
        parser.add_argument("--out-dir", type=Path, default=Path(DEFAULT_OUT), help="Output directory")
        parser.add_argument("--iocs", type=Path, default=Path(DEFAULT_IOCS), help="IOC manifest path")
        parser.add_argument("--log-root", type=Path, default=None, help="Optional log directory to scan separately")
        args = parser.parse_args()
    
        iocs = load_iocs(args.iocs)
        indicators = build_indicators(iocs)
    
        args.out_dir.mkdir(parents=True, exist_ok=True)
    
        repo_matches = scan_root(args.scan_root, indicators)
        write_matches(args.out_dir / "repository-indicator-matches.txt", repo_matches)
    
        summary = {
            "scan_root": str(args.scan_root),
            "log_root": str(args.log_root) if args.log_root else None,
            "indicator_count": len(indicators),
            "repository_match_count": len(repo_matches),
            "repository_matches": repo_matches,
        }
    
        if args.log_root is not None:
            log_matches = scan_root(args.log_root, indicators)
            write_matches(args.out_dir / "exported-telemetry-indicator-matches.txt", log_matches)
            summary["log_match_count"] = len(log_matches)
            summary["log_matches"] = log_matches
    
        (args.out_dir / "scan-summary.json").write_text(
            json.dumps(summary, indent=2, sort_keys=True) + "\n",
            encoding="utf-8",
        )
    
        print(f"[+] Loaded {len(indicators)} indicators from {args.iocs}")
        print(f"[+] Repository matches: {len(repo_matches)}")
        if args.log_root is not None:
            print(f"[+] Log matches: {summary['log_match_count']}")
        print(f"[+] Wrote outputs to {args.out_dir}")
        return 0
    
    
    if __name__ == "__main__":
        raise SystemExit(main())

    Downstream Abuse Audits

    Because this vulnerability requires valid credentials with at least write access, the immediate downstream abuse question is whether management-plane credentials were used after the suspicious file-write activity. Review:

    • SD-WAN administrator accounts and recent privilege changes
    • API tokens or automation accounts that can write files through the web UI
    • configuration diffs on controller, manager, and validator components
    • any follow-on edge-device pushes that changed routing or security policy

    The audit should stay tightly scoped to the SD-WAN control plane; this is not a generic enterprise rotation checklist. The goal is to find which write-capable management identity performed the file-write action and whether it was followed by an unauthorized configuration change.

    Remediation and Closure

    1. Preserve admin-tech bundles and the affected management-plane logs before remediation.
    2. Restrict or disable write-capable SD-WAN management access that cannot be justified.
    3. Upgrade each affected control component to a fixed Cisco release.
    4. Review the management-plane logs and filesystem for suspicious writes, overwrites, and unexpected configuration changes.
    5. Treat unexplained file writes as compromise until the controller and connected edge state are reconciled.
    6. Close only after fixed-release proof, negative suspicious-write review, and a clean configuration diff are available.

    Sources

    1. CISA Known Exploited Vulnerabilities catalog JSON
    2. Cisco Security Advisory: Cisco Catalyst SD-WAN Manager path traversal
    3. NVD CVE-2026-20262

    IOC Clipboard

    6 IOCs
    Defang IOCs
    ip 20.9.9.2 20[.]9[.]9[.]2
    ip 20.12.7.2 20[.]12[.]7[.]2
    ip 20.15.4.5 20[.]15[.]4[.]5
    ip 20.15.5.3 20[.]15[.]5[.]3
    ip 20.18.3.1 20[.]18[.]3[.]1
    ip 26.1.1.2 26[.]1[.]1[.]2