Skip to content

Frontline hop-counter loop prevention is stripped before use #6249

Description

@chronark

Summary

Frontline cross-region forwarding uses X-Unkey-Frontline-Hops to enforce MaxHops, but the public proxy route runs WithReservedHeaderStrip() before routing and strips all X-Unkey-* headers. Peer frontline requests appear to use the same handler path, so the receiving frontline never sees the hop count from the previous hop and reinitializes it on the next forward.

Why this matters

The documented loop prevention in svc/frontline/internal/proxy/doc.go does not hold across peer frontlines. In stale-cache / split-brain routing scenarios, requests can bounce between frontlines until external timeouts or connection limits stop them, creating an availability/amplification risk.

This does not appear to be a cross-tenant data access issue; it is primarily operational resilience / DoS protection.

Relevant code

  • svc/frontline/internal/proxy/service.go: forwardToRegion reads HeaderFrontlineHops and rejects at MaxHops.
  • svc/frontline/internal/proxy/director.go: makeRegionDirector increments/writes HeaderFrontlineHops.
  • svc/frontline/routes/register.go: proxy route includes WithReservedHeaderStrip().
  • svc/frontline/middleware/sanitize_headers.go: strips every X-Unkey-* request header.

Possible fix

Minimal: allow X-Unkey-Frontline-Hops through sanitization. Forging that header only lets a client make its own request fail earlier; it does not grant privilege. Keep stripping sensitive headers such as X-Unkey-Principal.

More robust: authenticate peer-frontline metadata with mTLS/HMAC or move hop tracking out of unauthenticated headers.

Suggested verification

Add a focused test proving an inbound request with X-Unkey-Frontline-Hops at/above MaxHops reaches forwardToRegion and is rejected, while sensitive reserved headers continue to be stripped.

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions