Skip to main content
CVE Vulnerability Database
Vulnerability Database/CVE-2026-62947

CVE-2026-62947: OpenWrt Path Traversal Vulnerability

CVE-2026-62947 is a path traversal flaw in OpenWrt that allows attackers to read sensitive files like /etc/shadow through cgi-io handler exploitation. This article covers technical details, affected versions, and mitigation.

Published:

CVE-2026-62947 Overview

CVE-2026-62947 is a path traversal vulnerability [CWE-22] in OpenWrt, a Linux operating system for embedded devices. The flaw resides in the cgi-download handler in cgi-io, which authorizes the requested path against the caller's ubus session file ACL before canonicalization. Because rpcdsession.c calls fnmatch() without the FNM_PATHNAME flag, an attacker can append ../ traversal segments to an allowed wildcard prefix and reach files outside the permitted scope. Authenticated attackers can read root-readable files such as /etc/shadow. OpenWrt fixed the issue in version 25.12.5.

Critical Impact

Authenticated users with limited ACL permissions can traverse outside their allowed path prefix and read sensitive root-owned files, including credential material in /etc/shadow.

Affected Products

  • OpenWrt versions prior to 25.12.5
  • cgi-io component used by OpenWrt LuCI and RPC interfaces
  • rpcd session ACL matcher

Discovery Timeline

  • 2026-07-15 - CVE-2026-62947 published to NVD
  • 2026-07-15 - GitHub Security Advisory GHSA-jw5r-xhf5-2xcq published
  • 2026-07-15 - Fix released in OpenWrt v25.12.5
  • 2026-07-15 - Last updated in NVD database

Technical Details for CVE-2026-62947

Vulnerability Analysis

The vulnerability arises from an ordering flaw between authorization and path canonicalization in the cgi-io download handler. When a client requests a file through cgi-download, the handler calls session_access() with the raw path supplied by the caller. The ACL check succeeds if the path matches an allowed glob defined in the caller's ubus session. The handler then passes the same unresolved path to stat() and open(), which resolve ../ segments at the filesystem level and traverse outside the intended directory.

The second half of the flaw sits in rpcdsession.c. The ACL matcher uses fnmatch() without the FNM_PATHNAME flag. Without this flag, the * wildcard matches across / separators, allowing a crafted path such as /allowed/prefix/*/../../etc/shadow to satisfy an ACL glob while the kernel resolves it to a completely different file.

Root Cause

The root cause is a Time-of-Check Time-of-Use (TOCTOU) style mismatch. Authorization runs against a lexical path string, while file access runs against a canonicalized path. Combined with an overly permissive fnmatch() configuration, the two views of the path diverge and permit traversal.

Attack Vector

An authenticated attacker with at least one allowed download ACL entry can craft a URL that appends ../ sequences after a permitted prefix. The handler authorizes the request based on the lexical match, then opens the traversed path with the privileges of the cgi-io process. This exposes any root-readable file on the device.

c
 	if (!fields[1] || !session_access(fields[1], "cgi-io", "download", "read"))
 		return failure(403, 0, "Download permission denied");
 
-	if (!fields[3] || !session_access(fields[1], "file", fields[3], "read"))
+	/*
+	 * Canonicalize the requested path before checking it against the session
+	 * ACL and opening it. The rpcd ACL matcher uses fnmatch() without
+	 * FNM_PATHNAME, so a "../" suffix would otherwise match an allowed glob
+	 * prefix during the ACL check while open() resolves the embedded ".."
+	 * and reaches a file outside of that prefix.
+	 */
+	autochar *path = fields[3] ? canonicalize_path(fields[3], strlen(fields[3])) : NULL;
+
+	if (!path || !session_access(fields[1], "file", path, "read"))
 		return failure(403, 0, "Access to path denied by ACL");
 
-	if (stat(fields[3], &s))
+	if (stat(path, &s))
 		return failure(404, errno, "Failed to stat requested path");

Source: OpenWrt cgi-io commit 72990b7. The patch introduces canonicalize_path() before the ACL check, ensuring session_access() and stat() operate on the same resolved path.

Detection Methods for CVE-2026-62947

Indicators of Compromise

  • HTTP requests to /cgi-bin/cgi-download containing ../ sequences or URL-encoded %2e%2e%2f variants in the path parameter
  • Successful download responses referencing sensitive files such as /etc/shadow, /etc/config/*, or private key material
  • cgi-io process activity opening files outside declared ACL prefixes for a given session token

Detection Strategies

  • Inspect web server and reverse proxy logs for cgi-download requests where the resolved path differs from the requested prefix
  • Correlate ubus session ACL grants with subsequent file access patterns to identify boundary violations
  • Alert on any read access to /etc/shadow, /etc/dropbear/, or /etc/config/ originating from the cgi-io process

Monitoring Recommendations

  • Enable verbose logging in rpcd and cgi-io to capture requested path arguments prior to filesystem resolution
  • Forward OpenWrt syslog to a centralized SIEM and build detections for path traversal patterns against embedded device fleets
  • Track OpenWrt firmware versions across managed devices and flag any router still running a release older than 25.12.5

How to Mitigate CVE-2026-62947

Immediate Actions Required

  • Upgrade all OpenWrt devices to version 25.12.5 or later, which includes the canonicalization fix in cgi-io
  • Audit ubus session ACLs and remove wildcard file read grants that are not strictly required
  • Rotate credentials stored on affected devices, including local user password hashes and any keys reachable by the cgi-io process

Patch Information

The fix ships in OpenWrt release v25.12.5. The upstream commit 72990b7489872112df31c94032637c907760bae4 in the cgi-io repository canonicalizes the download path with canonicalize_path() before invoking session_access() and stat(). See the OpenWrt Security Advisory GHSA-jw5r-xhf5-2xcq, the cgi-io Pull Request #4, and the OpenWrt v25.12.5 Release for complete details.

Workarounds

  • Restrict access to the LuCI web interface and rpcd endpoints to trusted management networks using firewall rules
  • Tighten ubus ACL definitions to use precise path values rather than wildcard globs that could be extended with ../
  • Disable the cgi-io download handler on devices that do not require file download functionality until patching is complete
bash
# Verify installed OpenWrt version and upgrade path
cat /etc/openwrt_release | grep DISTRIB_RELEASE
opkg update
opkg list-upgradable | grep -E 'cgi-io|rpcd'

# Restrict LuCI/rpcd exposure to LAN interface only
uci set uhttpd.main.listen_http='192.168.1.1:80'
uci set uhttpd.main.listen_https='192.168.1.1:443'
uci commit uhttpd
/etc/init.d/uhttpd restart

Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

Default Legacy - Prefooter | Experience the World’s Most Advanced Cybersecurity Platform

Experience the Most Advanced Cybersecurity Platform

See how the world’s most intelligent, autonomous cybersecurity platform can protect your organization today and into the future.