Skip to main content

CSRF Without Tokens: Cross-Origin Protection in Fiber v3.6

ยท 21 min read
Fiber Team
Maintainers

Most CSRF bugs I have seen in Fiber apps were not attacks. They were users who left a form open over lunch, came back, clicked Save and got a 403 because the token in the page had expired. Or an HTMX page where one fragment was rendered without the hx-headers attribute that carries the token. Or a SPA that read the token cookie on startup and kept sending a stale value after the session rotated. The token itself was never the hard part. The plumbing was: every template, every fetch wrapper and every cached page has to carry a value from the server back to the server, and a single gap turns into a support ticket.

Browsers can tell a server where a request comes from. Every major browser engine now sends the Sec-Fetch-Site header, and Go 1.25 used it to add http.CrossOriginProtection to the standard library, a CSRF defense without any token. Fiber v3.6.0 brings the same check to Fiber as csrf.NewCrossOriginProtection (#4596). It sets no cookie, needs no storage and puts nothing in your templates.

This post protects a small notes service that has three kinds of clients: its own pages, a dashboard on a sibling subdomain, and an identity provider that posts back after login. We will exempt the one route that has to accept cross-site posts, roll the check out in report-only mode next to the existing tokens, pin the policy down in a test, and look at the cases where a token remains the better tool. Everything was built and tested against Fiber v3.6.1. The middleware needs v3.6.0 or later, which in turn requires Go 1.26.

Your Gateway Broke on v3.5.0: The Proxy Middleware's New SSRF Policy

ยท 22 min read
Fiber Team
Maintainers

You bump Fiber from v3.4.0 to v3.5.0, the tests pass, the deploy goes out, and every request to /api/users comes back as a 500. The body of that response tells anyone who asks exactly what went wrong:

proxy: upstream host resolves to a blocked address: localhost -> 127.0.0.1

In a Docker Compose or Kubernetes setup the hostname is users or users.default.svc and the IP starts with 10. or 172., but the message is the same. If the upstream in your proxy.Balancer config is an IP literal, you do not even get that far: the process panics at startup with proxy: upstream host resolves to a blocked address: 127.0.0.1.

This is not a regression. Fiber v3.5.0 hardened the proxy middleware (#4405), and its new default policy rejects upstreams on loopback, private, link-local and similar addresses. That default is right for code that forwards requests to URLs it did not choose, and inconvenient for the most common use of the middleware, an API gateway in front of internal services. This post shows how to give each kind of proxying the policy it needs, with one gateway that does both, built and tested against Fiber v3.5.0.

Nobody Cancels Your Handler: Timeouts and Client Disconnects in Fiber v3

ยท 17 min read
Fiber Team
Maintainers

Picture a bug report that is really a cost problem. A summary endpoint calls a slow upstream, an LLM API in our case, and users who get bored close the tab after a second or two. The frontend is fine with that. The invoice is not: the upstream bill shows complete generations for requests whose clients were long gone. The handler passed its context to the upstream client, so everybody assumed that a closed connection would cancel the call. It never did.

If you came to Fiber from net/http, Gin, Echo or Chi, that assumption is reasonable. In those frameworks, the request context is canceled when the client disconnects. Fiber runs on fasthttp, and fasthttp does not watch the connection while your handler runs. The fiber.Ctx you get satisfies context.Context, so the code compiles, but it is a context that can never be canceled. It is one of the most frequently reported surprises in the issue tracker (see #4335 or #4263), and the method docs in v3.5.0 now state it in plain words.

This post shows what you can rely on instead, with one service that we build and test against Fiber v3.5.0: a deadline for request/response handlers, disconnect detection for streams, and a clean way to end long streams when the server shuts down.