Feb 26, 2026·5 min read·85 visits
Coraza WAF used the wrong Go URL parser (`url.Parse` instead of `url.ParseRequestURI`). Sending a request like `//admin/` causes Coraza to treat `admin` as a hostname and strip it from the path it inspects. The WAF sees `/`, but the backend sees `/admin/`, completely bypassing path-based access controls.
A subtle but effective parser confusion vulnerability in the OWASP Coraza WAF allows attackers to bypass path-based security rules using double slashes in the URI. By misinterpreting the request path as a scheme-relative URL, Coraza accidentally truncates the first path segment, blinding the WAF to the attacker's true destination.
Imagine a nightclub bouncer who has been told strictly: "Do not let anyone named 'Admin' into the VIP room." A man walks up. His ID card says "Admin". The bouncer looks at it, squints, and somehow decides the name is actually empty, just a blank space. He waves the man through. The bartender inside, however, has better eyes. He sees "Admin" clearly and serves him the premium champagne (or the admin panel, in this analogy).
This is exactly what happened with CVE-2025-29914 in the OWASP Coraza WAF. Coraza is a popular, open-source Web Application Firewall written in Go. It is supposed to be the bouncer that inspects HTTP traffic before it hits your application.
However, due to a subtle misuse of Go's standard library, Coraza developed a blind spot. It turns out that simply adding an extra slash (/) to the beginning of your URL was enough to confuse the parser, effectively slicing off the most critical part of the path—the directory you were trying to protect. It's a classic case of Parser Confusion, where the security device and the backend application disagree on what the request actually is.
To understand this bug, we have to look at how URLs are defined in RFC 3986. In the web world, a string starting with // is often a "scheme-relative" or "network-path" reference. For example, if you see <script src="//evil.com/x.js"> in HTML, the browser knows to fetch that resource using the current protocol (HTTP or HTTPS) from the host evil.com.
Coraza is written in Go. Go's standard library has a powerful URL parser: net/url. However, it has two different functions that sound similar but behave very differently:
url.Parse(): Designed for general URL references. It respects the // rule. If you feed it //admin/users, it thinks admin is the Host and /users is the Path.url.ParseRequestURI(): Designed specifically for the Request-Line in an HTTP request. It assumes the input is a path (unless it's an absolute proxy request). If you feed it //admin/users, it treats the whole thing as the Path.The developers of Coraza inadvertently used url.Parse(). So, when an attacker sends GET //admin/setup.php, Coraza's internal logic splits it:
admin (Wait, what?)/setup.phpCoraza then populates the WAF variable REQUEST_FILENAME with /setup.php. The critical segment admin has vanished into the void of the "Host" field, which isn't checked by path-based rules.
Let's look at the diff. The fix is a one-liner, but it changes the entire behavior of the application's perception of reality. The vulnerability existed in internal/corazawaf/transaction.go.
The Vulnerable Code:
// internal/corazawaf/transaction.go
func (tx *Transaction) ProcessURI(uri string, method string, httpVersion string) {
// ...
// WRONG: Interprets //foo as host 'foo'
parsedURL, err := url.Parse(uri)
// ...
}Because parsedURL.Path was used to populate the REQUEST_FILENAME variable, the WAF was inspecting a truncated version of the attack string.
The Fix (Commit 4722c9ad0d502abd56b8d6733c6b47eb4111742d):
// internal/corazawaf/transaction.go
func (tx *Transaction) ProcessURI(uri string, method string, httpVersion string) {
// ...
// RIGHT: Interprets //foo as path '//foo'
parsedURL, err := url.ParseRequestURI(uri)
// ...
}By switching to ParseRequestURI, Coraza now correctly understands that in the context of an HTTP Request Line (e.g., GET //admin HTTP/1.1), the double slash is just a part of the path, not a signal to switch hosts.
Let's construct a scenario. You are running a legacy PHP application behind Coraza. You have a rule to block external access to the /private/ directory.
WAF Rule:
SecRule REQUEST_FILENAME "@beginsWith /private/" "id:1001,phase:1,deny,status:403"The Attack Chain:
Attacker Request:
GET //private/db_dump.sql HTTP/1.1
Host: target.com
Coraza Processing (Vulnerable):
//private/db_dump.sqlurl.Parse behavior: Host = private, Path = /db_dump.sqlREQUEST_FILENAME = /db_dump.sqlWAF Logic:
/db_dump.sql begin with /private/?Backend Processing (e.g., Nginx/Apache):
//private/db_dump.sql.// becomes /./private/db_dump.sql.This diagram illustrates the divergence in perception:
This is effectively a "Get Out of Jail Free" card for any rule relying on REQUEST_FILENAME to restrict access to specific directories.
This vulnerability affects all versions of Coraza prior to 3.3.3. If you are using Coraza as a library in your Go application, or as part of the Coraza Caddy plugin (depending on the version bundled), you are likely vulnerable.
Immediate Actions:
go.mod to require github.com/corazawaf/coraza/v3 v3.3.3.The patch ensures that // paths are preserved in REQUEST_FILENAME, allowing your regex rules to match them correctly. If you have rules like @beginsWith /admin, they will now correctly see //admin (assuming you handle the extra slash in your regex or the WAF normalizes it correctly after parsing).
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:L/I:L/A:N| Product | Affected Versions | Fixed Version |
|---|---|---|
Coraza OWASP | < 3.3.3 | 3.3.3 |
| Attribute | Detail |
|---|---|
| CWE | CWE-706 (Incorrect Resolution of Path) |
| CVSS | 5.4 (Medium) |
| Vector | CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:L/I:L/A:N |
| Attack Vector | Network (HTTP) |
| Impact | Security Rule Bypass |
| Status | Patched in v3.3.3 |
The product uses a name or reference to resolve a resource, but the name/reference resolves to a different resource than intended.
An uncontrolled resource consumption vulnerability exists in the Scala-based http4s-blaze-server package of the http4s/blaze library. The vulnerability allows remote, unauthenticated attackers to cause an Out of Memory Error (OOM) and JVM crash by streaming a continuous sequence of small or empty WebSocket continuation frames with the FIN bit set to 0. This bypasses typical payload size checks because of the JVM's per-object allocation overhead, leading to rapid heap exhaustion with minimal network bandwidth.
A critical path traversal vulnerability has been identified in the OpenList Go-based backend package. The vulnerability exists within the batch rename handler because the application does not validate the source filename parameter before constructing filesystems paths. This omission allows authenticated users to escape their designated directory and rename files in sibling paths.
OpenList version 4.2.3 and prior is vulnerable to an authorization bypass and metadata leakage. When configured with the Bleve search engine backend, OpenList fails to perform separator-aware path matching when validating tenant containment. This allows authenticated users to access sibling directories sharing similar name prefixes. Furthermore, the search backend returns unfiltered global result counts, leaking existence verification data of unauthorized files via side-channel analysis.
An authorization bypass vulnerability in OpenList version 4.2.3 and below allows authenticated users to read arbitrary files outside of their designated base directories due to an insecure path prefix check using Go's standard strings.HasPrefix function.
A security policy bypass vulnerability exists in the AWS API MCP Server (awslabs-aws-api-mcp-server) from version 0.2.13 through 1.3.46. When the server fails to load the read-only operations index during startup (due to transient network failures, file permission issues, or other exceptions), it logs a warning but continues running in an insecure, degraded state. Under this condition, the security policy engine fails open, silently skipping all subsequent security checks and consent prompts for the lifetime of the process. This permits unauthorized mutating AWS CLI commands to execute via indirect prompt injection attacks.
An incomplete escaping vulnerability in the npm package 'shescape' allows unauthenticated users to trigger dynamic shell expansions, absolute path disclosure, and command block break-outs on Unix and Windows systems.