Skip to main content

Module csrf

Module csrf 

Available on crate feature http only.
Expand description

Modern protection against cross-site request forgery (CSRF) attacks.

This middleware implements the stateless CSRF protection scheme introduced in Go 1.25 and described in Filippo Valsorda’s blog post. It relies on the Sec-Fetch-Site and Origin request headers and requires no per-request token state.

Unlike the Go reference, rama compares origins structurally using rama_net::uri::Uri: hosts are matched case-insensitively and a default port (80 for http, 443 for https) compares equal whether it is written out explicitly or omitted.

Requests are allowed if any of the following hold:

  1. The method is GET, HEAD, or OPTIONS.
  2. Sec-Fetch-Site is same-origin or none.
  3. The request’s Origin matches an allow-listed trusted origin.
  4. Neither a usable Sec-Fetch-Site nor a non-empty Origin is present.
  5. The Origin’s authority (host + port) matches the request’s effective host — the request-target authority if present (RFC 7230 §5.3), else the Host header.

Rejected requests receive a 403 Forbidden response. The originating ProtectionError is attached to the response’s extensions — on every rejection, including those from a custom builder — so surrounding layers can distinguish explicit cross-origin rejections from conservative fallback rejections (e.g. requests from old browsers without Sec-Fetch-Site). Use CsrfLayer::with_rejection_response to replace the rejection response.

§Example

use std::convert::Infallible;

use rama_core::{Layer, service::service_fn};
use rama_http::layer::csrf::CsrfLayer;
use rama_http::{Body, Request, Response};

async fn handle(_: Request) -> Result<Response, Infallible> {
    Ok(Response::new(Body::empty()))
}

// Same-origin (and `https://app.example.com`) requests pass through; cross-origin
// state-changing requests are rejected with `403 Forbidden`.
let layer = CsrfLayer::new()
    .add_trusted_origin("https://app.example.com")
    .expect("valid trusted origin");
let service = layer.into_layer(service_fn(handle));

§Deployment caveat

The middleware trusts whatever Origin and Host reach it. Reverse proxies and load balancers that rewrite Host (e.g. to an internal hostname) or strip Origin silently degrade the protection: the Origin/Host fallback can no longer match and Sec-Fetch-Site becomes the only remaining line of defense. Configure intermediaries to forward both headers unchanged.

Structs§

Csrf
Middleware that enforces cross-origin request forgery (CSRF) protection.
CsrfLayer
Layer that applies the Csrf middleware.
DefaultResponseForProtectionError
Default ResponseForProtectionError used by CsrfLayer::new.
ProtectionError
Reason a request was rejected by Csrf.

Enums§

ConfigError
Errors that can occur while configuring CsrfLayer.
ProtectionErrorKind
The category of a ProtectionError.

Traits§

ResponseForProtectionError
Builds the response returned by Csrf when a request fails CSRF protection.