CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



CVE-2026-25891
7.7

Fiber's Windows Hangover: The Double-Decode Path Traversal

Alon Barad
Alon Barad
Software Engineer

Feb 25, 2026·6 min read·5 visits

PoC Available

Executive Summary (TL;DR)

Fiber v3 on Windows fails to properly sanitize paths containing double-encoded backslashes. The middleware checks for malicious characters *before* decoding the URL, allowing attackers to sneak directory traversal sequences past the filter. Once decoded, the Windows kernel happily interprets the backslashes, granting read access to the entire filesystem.

A high-severity Path Traversal vulnerability in the Fiber Go framework (v3) allows remote attackers to read arbitrary files on Windows servers. By exploiting a logic flaw in the static middleware's sanitization routine, attackers can bypass security checks using double-encoded backslashes, escaping the web root and accessing sensitive system files.

The Hook: When Abstractions Leak

Fiber bills itself as the "Express of Go," promising speed, ease of use, and a familiar developer experience. It’s a fantastic framework—until you deploy it on Windows and try to serve static files. You see, the problem with cross-platform abstractions is that they eventually leak, and when they do, they usually leak file contents.

This specific vulnerability, CVE-2026-25891, is a textbook example of "It works on my machine (which is a MacBook)." The developers relied on Go's standard path package to clean URLs. This is standard practice in the Go community. The path package is strictly POSIX-compliant; it treats forward slashes (/) as separators and everything else as just another character.

But Windows? Windows is the chaotic evil of file systems. It accepts both forward slashes and backslashes (\) as separators. When Fiber's middleware blindly trusts a POSIX cleaning function to sanitize inputs for a Windows file system, it creates a massive logic gap. It's like locking your front door (checking for /../) but leaving the back door ( \..\ ) wide open because your security guard doesn't believe back doors exist.

The Flaw: A Tale of Two Packages

The root cause here is a beautiful disaster involving three distinct failures: an Order-of-Operations error, a Package Mismatch, and a Recursive Decoding Loop.

First, the Order-of-Operations: The vulnerable code in sanitizePath attempted to filter out dangerous characters—specifically the backslash \—before it finished decoding the URL. It checks the raw input, says "looks clean," and then unescapes the characters. This is the security equivalent of checking a passenger's luggage before they've finished packing it.

Second, the Recursive Decoding Loop: Fiber implements a loop that repeatedly calls url.PathUnescape until no more changes occur. This is intended to handle weirdly encoded URLs, but it serves as a weapon for attackers. If I send %255C, the first pass turns it into %5C. The second pass turns it into \. Since the security check happened before this loop, the lethal backslash appears only after the guard has left the room.

Third, the Package Mismatch: After decoding, the code calls path.Clean(). Remember, this is the POSIX version. If you feed ..\..\Windows to path.Clean(), it shrugs and says, "That's a valid filename with some weird backslashes in it." It doesn't collapse the path. It doesn't remove the ... It just passes it along to the OS. When that string hits the Windows syscalls, the OS treats those backslashes as valid directory separators, and suddenly you're traversing directories.

The Code: Anatomy of the Bypass

Let's look at the "smoking gun" in middleware/static/static.go. The vulnerability stems from where the checks are placed relative to the decoding logic.

The Vulnerable Logic (Simplified):

// 1. Check for backslashes prematurely
if strings.Contains(path, "\\") {
    return nil, ErrInvalidPath
}
 
// 2. Decode the path in a loop (The attacker's playground)
for {
    decoded, err := url.PathUnescape(path)
    if decoded == path {
        break
    }
    path = decoded
}
 
// 3. Clean using POSIX rules (Ineffective against Windows paths)
path = pathpkg.Clean("/" + path)

Do you see the issue? If I send %255C, step 1 sees safe ASCII characters. Step 2 decodes it down to \. Step 3 ignores it. The variable path now contains a backslash traversal.

The Fix (Commit 5913370):

The maintainers fixed this by moving the validation after the decoding loop and, crucially, normalizing the path using filepath (which is OS-aware) instead of just path.

// 1. Decode FIRST
for {
    decoded, err := url.PathUnescape(path)
    if decoded == path {
        break
    }
    path = decoded
}
 
// 2. NOW check for malicious characters
if strings.Contains(path, "\\") || strings.Contains(path, "\x00") {
    return nil, ErrInvalidPath
}
 
// 3. Normalize for the specific OS
normalized := filepath.ToSlash(path)
 
// 4. Clean and Check again
path = pathpkg.Clean("/" + normalized)

By ensuring the validation happens on the final representation of the string, the bypass is closed.

The Exploit: Crafting the Payload

Exploiting this is trivially easy once you understand the decoding logic. We don't need fancy tools; a standard web browser or curl is enough. We are targeting a Windows server running Fiber v3.0.0.

The Objective: Read C:\Windows\win.ini.

The Obstacle: The application is serving files from ./public, and we need to go up three levels to reach the drive root.

The Technique: Double URL Encoding.

  1. Standard Traversal: ..\..\..\Windows\win.ini
  2. Single Encoding: %2E%2E%5C%2E%2E%5C%2E%2E%5CWindows%5Cwin.ini (Blocked by basic filters often, or decoded to \ too early).
  3. Double Encoding the Backslash: %255C.

When we send %255C, the server receives it. The initial check scans for \ (0x5C). It finds nothing. The loop runs:

  • Pass 1: %25 becomes %. Result: %5C.
  • Pass 2: %5C becomes \. Result: \.

The Final Payload:

curl "http://target-server.com/static/%255C..%255C..%255C..%255CWindows%255Cwin.ini"

The server resolves this to .\public\..\..\..\Windows\win.ini. The Windows I/O manager canonicalizes this to C:\Windows\win.ini and serves the file content. Congratulations, you have just compromised the server's confidentiality.

The Impact: Why You Should Care

This isn't just about reading win.ini. If an attacker can read arbitrary files on a web server, they own the data.

  1. Source Code Disclosure: Attackers can read your application's source code (e.g., main.go, config.go), revealing logic flaws and hardcoded secrets.
  2. Configuration Leakage: Most modern apps use .env files or config.json. These files often contain database credentials, API keys, and signing secrets. With a single request: GET /static/%255C..%255C.env.
  3. RCE Potential: While this is a "File Read" vulnerability, it is often a precursor to Remote Code Execution. If an attacker can read the configuration of other services on the box, or find an administrative interface, the pivot to RCE is often short.

The CVSS score is 7.7 (High), but in the context of a cloud environment where a single credential leak can compromise an entire AWS/Azure account, the real-world impact is critical.

The Fix: Mitigation & Remediation

If you are running Fiber v3 on Windows, you are currently exposed. The remediation is straightforward, but urgency is required.

Immediate Action: Update to Fiber v3.1.0 immediately. The patch introduces strict validation that normalizes paths specifically for the underlying OS before attempting to serve files.

Defense in Depth:

  1. Least Privilege: Why does your web server process have permission to read C:\Windows? Run your application as a low-privilege user that only has read access to the specific ./public directory.
  2. Containerization: Stop running Go binaries directly on bare-metal Windows if you can avoid it. Docker containers (even Windows containers) provide filesystem isolation that mitigates the impact of traversal attacks.
  3. WAF Rules: Configure your WAF to block URLs containing %255C (double-encoded backslash) or %5C (backslash). While you're at it, block .. in URL paths entirely if your application structure permits it.

Official Patches

GoFiberOfficial Patch Commit
GoFiberGitHub Security Advisory

Fix Analysis (1)

Technical Appendix

CVSS Score
7.7/ 10
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N/E:P

Affected Systems

Fiber v3.0.0 (Go Framework)Windows Server 2019/2022Windows 10/11 Hosts

Affected Versions Detail

Product
Affected Versions
Fixed Version
fiber
gofiber
>= 3.0.0, < 3.1.03.1.0
AttributeDetail
CWE IDCWE-22 (Improper Limitation of a Pathname to a Restricted Directory)
Attack VectorNetwork (Remote)
CVSS v4.07.7 (High)
Exploit StatusProof-of-Concept Available
PlatformWindows
ComponentStatic Middleware

MITRE ATT&CK Mapping

T1083File and Directory Discovery
Discovery
T1005Data from Local System
Collection
CWE-22
Path Traversal

The software uses external input to construct a pathname that is intended to identify a file or directory that is located underneath a restricted parent directory, but the software does not properly neutralize special elements within the pathname that can cause the pathname to resolve to a location that is outside of the restricted directory.

Known Exploits & Detection

Internal Test SuiteThe patch commit includes regression tests demonstrating the attack vectors.
NucleiDetection Template Available

Vulnerability Timeline

Fix commit merged
2026-02-08
GHSA Advisory Published
2026-02-24
CVE Published
2026-02-24

References & Sources

  • [1]NVD Entry
  • [2]Fiber Repository

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.