Introduction
A single crafted cookie is all it takes to gain full administrative control over AdGuard Home instances running on GL.iNet routers, and with it the power to manipulate DNS resolution for every device on the network. CVE-2026-41448, scored at CVSS v3 9.4 and CVSS v4 9.2, is a path traversal authentication bypass in AdGuard Home's authglinet middleware, caused by an unsanitized file path.
AdGuard Home is an open-source, network-wide DNS filtering server that blocks ads and tracking at the DNS level for every device on a network, with no client-side software. It has a substantial user base, much of it through GL.iNet routers (models like the Flint 3, Beryl 7, and Slate 7), where it ships as the built-in DNS filtering layer. That makes it core network infrastructure for home and small-business networks worldwide.
Technical Information
Root Cause: Unsanitized Path Construction from Cookie Input
CVE-2026-41448 is classified under CWE-22: Improper Limitation of a Pathname to a Restricted Directory. The vulnerability exists only when AdGuard Home is launched with the --glinet command-line flag, which activates the authglinet middleware, a separate authentication module built for GL.iNet router integration.
The bug is simple. The middleware builds a filesystem path by concatenating a static prefix with the value of the Admin-Token cookie, then opens that path to read and validate the authentication token. Before the patch, the prefix was a mutable package-level variable:
// BEFORE (internal/home/authglinet.go) var glFilePrefix = "/tmp/gl_token_"
When a request arrived, the middleware appended the cookie value directly to this prefix to form the full file path, with no sanitization, no validation, and no directory confinement. A cookie value containing ../ sequences would push the resulting path out of the intended /tmp/ directory entirely.
Attack Flow
Exploitation takes six steps:
- The attacker identifies an AdGuard Home instance running with the
--glinetflag (the default on GL.iNet routers). - The attacker sends an HTTP request to the AdGuard Home web interface with a crafted
Admin-Tokencookie containing path traversal sequences (e.g.,../../followed by a known file path). - The
authglinetmiddleware concatenates this unsanitized cookie value with the/tmp/gl_token_prefix, producing a path like/tmp/gl_token_/../../etc/some_file. - The middleware opens this traversed path using
os.Openand reads its contents. - If the file read succeeds and the returned content satisfies the token validation logic, the middleware grants full administrative access.
- The attacker now has complete control over the AdGuard Home instance: DNS filtering rules, upstream DNS servers, DHCP settings, and the DNS resolution of every connected device.
CVSS Scoring
The CVSS v4 vector assigned by VulnCheck is CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:H/VA:L/SC:N/SI:N/SA:N. The AT:P (Attack Requirements: Present) reflects the requirement that the target must be running with the --glinet flag. On GL.iNet routers that flag is the default configuration, so there the requirement is met out of the box.
| Metric | Value |
|---|---|
| Attack Vector | Network |
| Attack Complexity | Low |
| Privileges Required | None |
| User Interaction | None |
| Confidentiality Impact | High |
| Integrity Impact | High |
| Availability Impact | Low |
Impact
Full administrative access to AdGuard Home in a GL.iNet router deployment means control over the network's primary DNS resolver. An attacker can redirect DNS queries to malicious servers, modify blocklists to allow malicious domains, alter DHCP configurations, and silently surveil all DNS traffic. DNS-level manipulation is insidious because it is hard to detect without dedicated monitoring infrastructure, and the home and small-office networks where GL.iNet routers are deployed rarely have it.
Discovery
Security researcher djnn (GitHub: @djnnvx) discovered the vulnerability. Disclosure was coordinated through VulnCheck, which acted as the CVE Numbering Authority.
Patch Information
AdGuard Home v0.107.77, released June 2, 2026, fixes CVE-2026-41448 with a well-structured change that closes the path traversal vector at the filesystem API level instead of relying on input sanitization. The diff between v0.107.76 and v0.107.77 shows the changes.
Eliminating the Mutable Path Prefix
The first change converts the token file prefix from a mutable variable holding a full filesystem path to a constant holding only the filename prefix:
// BEFORE (internal/home/authglinet.go) var glFilePrefix = "/tmp/gl_token_" // AFTER (internal/home/authglinet.go) const glFilePrefix = "gl_token_"
The directory component is gone, the prefix itself can no longer be manipulated, and the filename portion is a compile-time constant.
Introducing os.Root for Directory Confinement
The patch replaces the tokenFilePrefix string configuration field with a tokenFileRoot *os.Root field. This uses Go 1.24's os.OpenRoot facility, which creates a handle to a directory that path traversal cannot escape. AdGuard Home opens the root at startup:
if opts.glinetMode { glTokenFileRoot, err = os.OpenRoot("/tmp/") fatalOnError(err) }
This *os.Root value is threaded through the configuration structs (authConfig, authMiddlewareGLiNetConfig) into the middleware.
Replacing os.Open with Sandboxed Open
The critical change is in the tokenDate method, where the token file is opened:
// BEFORE f, err := os.Open(tokenFile) // AFTER f, err := mw.tokenFileRoot.Open(tokenFile)
os.Root.Open() resolves paths relative to the root directory and rejects any traversal sequences. A cookie value like /../../etc/passwd will no longer escape the /tmp/ sandbox.
Test Coverage
The patch adds explicit test cases that attempt path traversal and verify it fails:
reqPathTraversalToken := httptest.NewRequest(http.MethodGet, "/", nil) reqPathTraversalToken.AddCookie(&http.Cookie{ Name: glCookieName, Value: "/../../path_traversal_token", })
The test asserts that this request gets an HTTP 302 redirect to the login page, which confirms the traversal is blocked.
Instead of trying to sanitize the input, which is error-prone, the fix confines the filesystem operation to one directory at the OS level, so traversal is structurally impossible. It is a textbook example of defense in depth.
Affected Systems and Versions
All versions of AdGuard Home prior to v0.107.77 are affected when running with the --glinet command-line flag. Specifically:
- Affected: AdGuard Home versions before 0.107.77 launched with
--glinet - Not affected: AdGuard Home instances running without the
--glinetflag (standard deployments) - Fixed in: AdGuard Home v0.107.77 (released June 2, 2026)
The --glinet flag is the default integration mode on all GL.iNet router models that bundle AdGuard Home, including:
- GL.iNet Flint 3 (GL-BE9300)
- GL.iNet Beryl 7 (GL-MT3600BE)
- GL.iNet Slate 7 (GL-BE3600)
GL.iNet router firmware updates lag behind upstream AdGuard Home releases. Even after the release of AdGuard Home v0.107.77, GL.iNet users may remain exposed until GL.iNet issues a firmware update with the patched version. The GL.iNet forum has an active thread about this lag, with users asking when the patches will reach firmware.
Vendor Security History
CVE-2026-41448 is the second critical authentication bypass in AdGuard Home in 2026. The first, CVE-2026-32136 (CVSS 9.8), was disclosed in March 2026 and fixed in v0.107.73. That vulnerability exploited the HTTP/2 Cleartext (h2c) upgrade mechanism. The authentication wrapper only applied to the initial HTTP/1.1 upgrade request, so h2c connections went unauthenticated and could reach admin endpoints. GL.iNet forum staff published a proof of concept for that flaw.
| Attribute | CVE-2026-32136 | CVE-2026-41448 |
|---|---|---|
| CVSS Score | 9.8 | 9.4 / 9.2 (v4) |
| CWE | Auth bypass via protocol | CWE-22 (Path Traversal) |
| Attack Vector | HTTP/2 h2c upgrade | Path traversal in Admin-Token cookie |
| Affected Mode | All deployments | --glinet flag only |
| Fixed Version | v0.107.73 | v0.107.77 |
According to OpenCVE, AdGuard Home has at least 8 documented CVEs. Earlier vulnerabilities CVE-2022-30580 and CVE-2022-29804 were fixed in a release that also introduced enforced password protection. A security bulletin covering five vulnerabilities was issued in March 2024.
The two critical authentication bypasses, three months apart, follow the same pattern. The authentication middleware has multiple independent logic paths, and a flaw in any one of them results in a complete bypass. CVE-2026-32136 exploited a protocol-level weakness, and CVE-2026-41448 exploits a classic input validation failure. Two unrelated mechanisms reaching the same outcome show that the authentication layer has multiple independent failure modes, which suggests it needs a comprehensive architecture review rather than more point fixes.
References
- NVD: CVE-2026-41448
- VulnCheck Advisory: AdGuard Home Authentication Bypass via Path Traversal in Admin-Token Cookie
- AdGuard Home v0.107.77 Release Notes
- GitHub Diff: v0.107.76 to v0.107.77
- CVE-2026-41448 on Vulners
- Cloudron Forum: AdGuard Home Package Updates
- CWE-22: Improper Limitation of a Pathname to a Restricted Directory
- NVD: CVE-2026-32136
- GHSA-5fg6-wrq4-w5gh: HTTP/2 Cleartext (h2c) Upgrade Authentication Bypass
- GL.iNet Forum: AdGuard Home Security Update
- OpenCVE: AdGuard Vulnerabilities
- GL.iNet Router Docs: AdGuard Home
- GitHub Issue #1853: GL.iNet Integration
- BeyondMachines: AdGuard Home Patches Critical Authentication Bypass
- SecurityOnline: Critical 9.8 CVSS Flaw in AdGuard Home



