How to Set Referrer-Policy: strict-origin-when-cross-origin

This page covers deploying one specific value of the Referrer-Policy header and is part of the Referrer-Policy and Permissions-Policy reference. strict-origin-when-cross-origin is the correct default for nearly every production site: it sends the full URL on same-origin requests, only the bare origin on cross-origin requests, and nothing at all when the destination downgrades from HTTPS to HTTP. That combination keeps internal navigation attribution intact while preventing paths, query strings, tokens, and PII from leaking to third parties.

Configuration Syntax & Exact Values

The complete header value is a single token:

Referrer-Policy: strict-origin-when-cross-origin

Annotated behaviour of that one token:

There are no parameters, no quotes inside the value, and no list. A misspelled token (e.g. strict-origin-when-crossorigin) is not an error — the browser silently falls back to its own default, so the exact string matters.

Server-Side Configuration

Nginx

add_header Referrer-Policy "strict-origin-when-cross-origin" always;

always emits the header on error responses (4xx/5xx) too. Any add_header inside a location block discards inherited ones, so repeat this line in every block that sets its own headers.

Apache

Header always set Referrer-Policy "strict-origin-when-cross-origin"

always covers internally generated error responses; set overrides any value emitted by an upstream module. Requires mod_headers.

Cloudflare

Rules → Transform Rules → Modify Response Header → Set header Referrer-Policy to strict-origin-when-cross-origin, matching All incoming requests. A Transform Rule overwrites rather than appends, so it will not produce a duplicate alongside an origin value.

Node/Helmet

const helmet = require("helmet");

app.use(
  helmet({
    referrerPolicy: { policy: "strict-origin-when-cross-origin" },
  })
);

Helmet normalises header casing and prevents a duplicate Referrer-Policy. Register it before your route handlers so it applies to every response.

Referer sent under strict-origin-when-cross-origin Three navigations from an HTTPS origin showing the Referer value sent for same-origin, cross-origin HTTPS, and HTTPS to HTTP downgrade. Origin https://app.example/p?t=1 same-origin nav Referer: full URL https://app.example/p?t=1 cross-origin HTTPS Referer: origin only https://app.example/ HTTPS→HTTP downgrade Referer: (empty) nothing sent
The same origin URL leaks its full path internally, only its origin to a cross-origin HTTPS target, and nothing on an insecure downgrade.

Diagnostic & Verification Steps

  1. Confirm the header value:

    curl -sI https://app.example | grep -i referrer-policy

    Expected output:

    referrer-policy: strict-origin-when-cross-origin
    
  2. Open DevTools → Network → enable Preserve log. Click an internal link and inspect the new request’s Request Headers. Expected Referer:

    Referer: https://app.example/dashboard?tab=billing
    
  3. Click an external HTTPS link and inspect its Request Headers. Expected truncated Referer:

    Referer: https://app.example/
    

    The path /dashboard and query ?tab=billing are gone — this is the cross-origin truncation that proves the policy is live.

  4. Read document.referrer in a third-party page’s console after navigating from your site. Expect https://app.example/, never a path.

Edge Cases, Security Implications & Safe Rollback

Safe rollback (non-destructive). This header has no client-side lock-in, so reverting is immediate:

  1. Replace the value with the broadest compatible fallback:
    Header always set Referrer-Policy "no-referrer-when-downgrade"
  2. Purge CDN/edge cache.
  3. Re-verify: curl -sI https://app.example | grep -i referrer-policy.
  4. Confirm the dependent flow (analytics or OAuth) recovers, then plan a server-side fix so you can return to strict-origin-when-cross-origin.

Frequently Asked Questions

Is strict-origin-when-cross-origin already the browser default? Modern Chromium, Firefox, and Safari default to it, but defaults are not contractual and privacy-hardened or legacy agents differ. Set the header explicitly for deterministic, auditable behaviour.

Does this value send anything cross-origin at all? Yes — the bare origin (https://app.example/) on same-security cross-origin requests, and nothing on an HTTPS→HTTP downgrade. Only the path and query are stripped cross-origin.

Will it break OAuth logins? No, provided the flow validates origin (which still arrives in Referer) and carries state in the state/redirect parameters rather than depending on the full referring path. Relying on the full Referer path for OAuth is itself insecure.

Conclusion

Roll this out incrementally: set strict-origin-when-cross-origin in staging, confirm the cross-origin Referer truncation in DevTools and that analytics and any redirect flows still behave, then promote to production at a single enforcement layer (edge or origin, not both). Because the header carries no client-side persistence, rollback is just a value change plus a cache purge.