What's the vulnerability?

The default KeyGenerator of Fiber v3's cache middleware returns only c.Path(). The cache key therefore ignores the query string and any other request component that distinguishes one user's request from another's.

Two requests to the same path with different query strings collide on the cache key: the second request returns the first user's cached response, leaking that response across users (cache confusion / information disclosure).

Root Cause Analysis

# RCA Report: CVE-2026-30246 — Fiber v3 Cache Middleware Key Collision

## Summary

In `github.com/gofiber/fiber/v3` versions `<= 3.1.0`, the default `KeyGenerator` of the `cache` middleware returns only `c.Path()`, ignoring the query string and all other request dimensions. This causes cache key collisions for requests to the same path with different query parameters (e.g., `/?id=1` vs `/?id=2`). The second request receives the first request's cached response, leading to cross-user information disclosure and cache confusion (CWE-200 / CWE-524).

## Impact

- **Package**: `github.com/gofiber/fiber/v3` (Go module)
- **Affected versions**: `<= 3.1.0`
- **Fixed version**: `3.2.0`
- **Severity**: Medium (CVSS 3.1 base 6.5)
- **Consequences**: Any application using the default cache middleware without a custom `KeyGenerator` is vulnerable to cache confusion. Responses tailored to one user's query parameters may be leaked to another user requesting the same path with different parameters.

## Root Cause

The vulnerable code in `middleware/cache/config.go` at v3.1.0 defines the default `KeyGenerator` as:

```go
KeyGenerator: func(c fiber.Ctx) string {
    return utils.CopyString(c.Path())
},
```

In `middleware/cache/cache.go`, the cache lookup key is built as:

```go
baseKey := cfg.KeyGenerator(c) + "_" + requestMethod
```

Because `c.Path()` returns only the URL path without the query string, requests to `/?id=1` and `/?id=2` both resolve to the same cache key (`/_GET`). The second request therefore hits the cached entry from the first request and receives the wrong response body.

The fix in v3.2.0 (commits `9a0d12c07ed895b84c72987f9288b04137afe5de` and `050ff1ff18511c1475b8ec627460216aaec627460216aaecddd4e`) completely rewrites the default key generator (`defaultKeyGenerator`) to include:
- HTTP method
- Escaped path (preventing delimiter injection)
- Canonical query string (sorted, with bounds to prevent DoS)
- Selected representation headers (`Accept`, `Accept-Encoding`, `Accept-Language`)
- Optional cookie dimensions

This ensures requests with different query parameters produce distinct cache keys, eliminating the collision.

## Reproduction Steps

1. Run `repro/reproduction_steps.sh`.
2. The script creates a scratch Go module, installs Fiber v3.1.0 (vulnerable) and v3.2.0 (fixed) separately, and for each version:
   - Builds a small Fiber server with the default `cache.New()` middleware.
   - Registers a handler on `/` that returns the `id` query parameter.
   - Issues `GET /?id=1` followed by `GET /?id=2`.
   - Captures the two response bodies to `logs/vulnerable_output.txt` and `logs/fixed_output.txt`.
3. **Expected evidence**:
   - **Vulnerable (v3.1.0)**: both responses are `1` (the second request hits the cache entry from the first because the query string is ignored in the key).
   - **Fixed (v3.2.0)**: responses are `1` then `2` (each request gets its own cache key because the query string is included).

## Evidence

- `logs/vulnerable_output.txt`:
  ```
  1
  1
  ```
- `logs/fixed_output.txt`:
  ```
  1
  2
  ```
- `logs/summary.txt`: contains the full run output with confirmation messages.
- `repro/runtime_manifest.json`: structured evidence with request/response pairs and verdict.

## Recommendations / Next Steps

1. **Upgrade immediately** to `github.com/gofiber/fiber/v3@v3.2.0` or later.
2. **If a custom `KeyGenerator` is in use**, audit it to ensure query strings, headers, or other user-specific dimensions are incorporated into the key.
3. **Regression test**: add an integration test that issues two requests to the same path with different query parameters and asserts distinct response bodies when caching is enabled.

## Additional Notes

- **Idempotency**: `repro/reproduction_steps.sh` was executed twice consecutively with identical results, confirming idempotency.
- **Edge cases**: The vulnerability is present regardless of the number or names of query parameters, as long as the path component remains identical. The default cache middleware only caches `GET` and `HEAD` requests, so other HTTP methods are not affected by this specific key collision.
One Command

Verify with pruva-verify

Run the Pruva CLI to automatically fetch and execute the reproduction script.

pruva-verify REPRO-2026-00157
or pruva-verify GHSA-35hp-hqmv-8qg8
or pruva-verify CVE-2026-30246
Install: curl -fsSL https://pruva.dev/install.sh | sh

Or Run Manually

1

Download the script

curl -O https://pruva.dev/api/v1/reproductions/REPRO-2026-00157/artifacts/reproduction_steps.sh
2

Make executable

chmod +x reproduction_steps.sh
3

Run the script

./reproduction_steps.sh
Run in a VM, container, or disposable environment. This exploits a real vulnerability.

How Pruva Reproduced This

Watch the AI agent's step-by-step process.

Loading session...

Artifacts

No artifacts available