HIGH cache poisoningchigo

Cache Poisoning in Chi (Go)

Cache Poisoning in Chi with Go — how this specific combination creates or exposes the vulnerability

Cache poisoning occurs when an attacker tricks a cache (or cache-like behavior) into storing a malicious response, causing subsequent users to receive attacker-controlled data. In a Go HTTP router like Chi, this can arise when route parameters or query values are used to construct cache keys without proper normalization and validation. If a handler reflects user input directly into the response and that response is cached based on the raw request, an attacker can inject crafted inputs that alter cached entries for other users.

Chi does not provide built-in caching; developers typically add caching at the handler or middleware layer. When using Chi’s context.URLParam or context.QueryParam to vary cache keys, failing to validate, sanitize, or scope these values can lead to cache poisoning. For example, a handler that uses a user-supplied Accept-Language header or a path parameter to decide response content might inadvertently cache a poisoned response. Attackers can exploit this to serve malicious content, bypass language or regional restrictions, or manipulate business logic that depends on cache state.

Real-world patterns that increase risk include dynamic route definitions where parameters influence backend selection or response formatting, and handlers that embed parameters in cache keys without canonicalization. If the application uses shared caches (e.g., in-memory caches keyed by request attributes), a poisoned key can overwrite legitimate entries. Because Chi routes are matched in order, a malicious route parameter that matches a broader pattern can intercept requests and alter cached outcomes. Such issues are not inherent to Chi but stem from how developers design caching strategies and handle input within Chi handlers.

Go-Specific Remediation in Chi — concrete code fixes

To mitigate cache poisoning in Chi, treat all user-controlled data as untrusted when building cache keys. Validate and sanitize inputs, avoid using raw parameters or headers directly in cache logic, and scope cache entries with explicit context such as authenticated user identifiers. Below are concrete Go examples demonstrating secure patterns.

Validate and canonicalize route parameters

Use strict parameter validation and canonicalization before using values in cache keys. For a numeric ID, ensure it is parsed and bounded:

import (
	"net/http"
	"strconv"

	"github.com/go-chi/chi/v5"
)

func safeHandler(rw http.ResponseWriter, r *http.Request) {
	idStr := chi.URLParam(r, "id")
	id, err := strconv.Atoi(idStr)
	if err != nil || id <= 0 {
		http.Error(r, "invalid id", http.StatusBadRequest)
		return
	}
	// Use the validated integer ID for cache key construction
	cacheKey := "resource:v1:id:" + strconv.Itoa(id)
	// proceed with cache lookup/handling
	http.Fprintln(rw, "safe response")
}

Avoid using raw headers in cache keys

Do not directly incorporate headers like Accept-Language into cache keys without normalization and allowlisting:

import (
	"strings"

	"github.com/go-chi/chi/v5"
)

func languageAwareHandler(rw http.ResponseWriter, r *http.Request) {
	lang := chi.URLParam(r, "lang")
	// Canonicalize: restrict to supported languages
	supported := map[string]bool{"en": true, "fr": true, "es": true}
	if !supported[lang] {
		lang = "en" // default
	}
	cacheKey := "page:lang=" + lang
	// use cacheKey safely
	http.Fprintln(rw, "response for "+lang)
}

Scope cache entries with request context

Include user or tenant identifiers when available to avoid cross-user contamination:

import (
	"github.com/go-chi/chi/v5"
)

func scopedCacheMiddleware(next http.Handler) http.Handler {
	return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
		userID := "anonymous"
		if authenticatedID := r.Header.Get("X-User-ID"); authenticatedID != "" {
			userID = authenticatedID
		}
		// Example: store userID in context for downstream cache logic
		ctx := context.WithValue(r.Context(), "cacheContext", userID)
		next.ServeHTTP(rw, r.WithContext(ctx))
	})
}

Use middleware to sanitize inputs globally

Register Chi middleware to validate or strip unexpected query parameters that could poison cache keys:

import (
	"net/http"

	"github.com/go-chi/chi/v5"
	"github.com/go-chi/chi/v5/middleware"
)

func main() {
	r := chi.NewRouter()
	r.Use(middleware.RequestID)
	r.Use(func(next http.Handler) http.Handler {
		return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
			// Remove or normalize query parameters that should not affect cache behavior
			r.URL.RawQuery = "safe=true" // example: enforce safe query state
			next.ServeHTTP(rw, r)
		})
	})
	r.Get("/items/{id}", safeHandler)
}

Frequently Asked Questions

Can cache poisoning affect unauthenticated endpoints in Chi?
Yes. If unauthenticated Chi handlers use raw user input in cache keys or responses, attackers can poison cached content for subsequent unauthenticated requests.
Does middleBrick detect cache poisoning vectors in API specifications?
middleBrick scans unauthenticated attack surfaces and maps findings to frameworks like OWASP API Top 10; it reports potential cache poisoning indicators when inputs influence cache behavior without validation.