# Referrer-Policy: Stop Leaking Sensitive URLs

> Source: <https://dev.to/muhammadalimughal/referrer-policy-stop-leaking-sensitive-urls-5b24>
> Published: 2026-11-10 05:37:25+00:00

Every time a user clicks from your app to a third-party link, the browser may send a `Referer` header with the full URL they came from—including path segments, query strings and sometimes one-time tokens. Password-reset links, signed download URLs, invite codes and internal admin paths have all leaked this way into analytics vendors, CDNs and support widgets. `Referrer-Policy` is the response header that decides how much of that URL other origins are allowed to see. Set it wrong (or leave the browser default) and you quietly ship secrets to whoever sits at the other end of the click.

I build [PixelValut](https://pixelvalut.com/tools/?utm_source=devto&utm_medium=article&utm_campaign=referrer-policy-stop-leaking-urls), a set of browser-side developer and security tools, and I wanted a practical checklist for teams that already ship HTTPS but never audited what their pages put in `Referer`. I wrote this with help from AI tools and checked every command and claim myself. This piece covers the policy values that matter, real leak scenarios, how to set and verify the header with curl and DevTools, and a safe default for most SaaS apps.

**Direct answer:** `Referrer-Policy` tells browsers how much of the current page URL to put in the `Referer` header (and in `document.referrer`) when the user navigates or loads a subresource. Policies range from sending nothing (`no-referrer`) to sending the full URL even on HTTPS→HTTP downgrades. Pick a value that keeps path and query off cross-origin requests unless you truly need them for analytics.

| Policy | Same-origin request | Cross-origin HTTPS→HTTPS | HTTPS→HTTP downgrade | Typical use | 
|---|---|---|---|---|
| `no-referrer` | No `Referer` | No `Referer` | No `Referer` | Highest privacy; breaks referrer-based analytics | 
| `no-referrer-when-downgrade` | Full URL | Full URL | No `Referer` | Old browser default; still leaks path/query cross-origin | 
| `origin` | Origin only | Origin only | Origin only | Soft analytics without paths | 
| `origin-when-cross-origin` | Full URL | Origin only | Origin only | Good balance for many apps | 
| `same-origin` | Full URL | No `Referer` | No `Referer` | Strict; third parties see nothing | 
| `strict-origin` | Origin only | Origin only | No `Referer` | Origin for peers; strip on downgrade | 
| `strict-origin-when-cross-origin` | Full URL | Origin only | No `Referer` | Current browser default on modern engines; solid SaaS default | 
| `unsafe-url` | Full URL | Full URL | Full URL | Almost never justified | 

Modern Chrome, Firefox and Safari effectively default to `strict-origin-when-cross-origin` when the site sends no policy. That is better than the old `no-referrer-when-downgrade` default, but it still sends your full path and query to other pages on the same origin, and your origin (scheme + host + port) to other HTTPS sites. If a reset link lives at `https://app.example.com/reset?token=…` and the user clicks a cross-origin help article, the token stays off the wire—only `https://app.example.com/` is sent. If that help widget is same-site or you used `unsafe-url`, the token can leave the browser.

Treat these as design cases, not one-off bugs:

`Referer` unless the policy strips them.`/admin/users/123/impersonate`). Even without tokens, path leakage tells an external script who you were looking at.`unsafe-url` and older defaults are how full URLs end up on cleartext hops.
This sits next to transport controls like [MTA-STS for inbound email](https://dev.to/muhammadalimughal/mta-sts-and-tls-rpt-enforce-tls-for-inbound-email-3c2g) and certificate issuance limits via [CAA records and CT logs](https://dev.to/muhammadalimughal/caa-records-and-ct-logs-control-who-issues-your-certs-29db): each closes a different disclosure channel. Referrer policy closes the browser-navigation channel.

| Weak | Hardened | Why | 
|---|---|---|
| No `Referrer-Policy` header | `Referrer-Policy: strict-origin-when-cross-origin` | Explicit beats relying on each browser's default | 
| `unsafe-url` "so analytics works" | `origin` or`strict-origin-when-cross-origin` plus server-side UTM on outbound links you control | You do not need full paths in third-party logs | 
| Token in query on a marketing page that loads many third-party scripts | Move secrets to POST body, fragment, or one-time server session; keep `same-origin` or`no-referrer` on that route | Headers cannot fix a secret that must never leave | 
| Only a `<meta name="referrer">` on some templates | Send the HTTP header globally from the reverse proxy or app middleware | Meta tags are easy to forget on error pages and APIs | 
| Different policies per environment, undocumented | One documented default in nginx/Cloudflare/Laravel, with per-route exceptions listed | Drift is how `unsafe-url` survives in staging clones | 

Nginx (inside the `server` block):

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

Cloudflare Transform Rule or Response Header modification:

```
Set Referrer-Policy = strict-origin-when-cross-origin
```

Laravel middleware (global):

``` php
public function handle($request, Closure $next)
{
    $response = $next($request);
    $response->headers->set(
        'Referrer-Policy',
        'strict-origin-when-cross-origin'
    );
    return $response;
}
```

You can also set a document-wide default with HTML, useful on static sites:

```
<meta name="referrer" content="strict-origin-when-cross-origin">
```

Prefer the HTTP header for APIs and redirects. For a single sensitive view (reset confirm, billing portal), tighten further:

```
Referrer-Policy: no-referrer
```

HTML links can override per navigation with the `referrerpolicy` attribute or `rel="noreferrer"`:

```
<a href="https://partner.example/docs" referrerpolicy="no-referrer">Docs</a>
<a href="https://partner.example/docs" rel="noreferrer">Docs</a>
```

`rel="noreferrer"` also implies `noopener` behavior for browsing context, which pairs well with the reverse-proxy hardening patterns in [zero-trust nginx setups](https://dev.to/muhammadalimughal/zero-trust-reverse-proxy-hardening-in-nginx-rate-limiting-request-smuggling-guards-mtls-e71).

Check that the response advertises the policy:

```
curl -sI https://pixelvalut.com/tools/ | grep -i referrer-policy
```

You want a line like:

```
referrer-policy: strict-origin-when-cross-origin
```

In Chrome DevTools:

`referrer-policy`.` referer`.`?token=` or `/reset/`.
For a quick browser-side pass on any URL, use the [PixelValut HTTP Status Checker](https://pixelvalut.com/tools/http-status-checker?utm_source=devto&utm_medium=article&utm_campaign=referrer-policy-stop-leaking-urls) to inspect response headers without installing anything. Then repeat the navigation test in DevTools—header presence alone does not prove outbound requests are stripped; you still need to watch a real cross-origin click.

| Problem | Why policy is not enough | Better control | 
|---|---|---|
| Secret in the URL bar copied by the user | No browser header involved | Prefer body/fragment/session; short TTL tokens | 
| Server-side logs of your own full URLs | Same-origin full referrers still apply under several policies | Redact query strings in access logs | 
| Third-party script reading `document.referrer` same-origin | Policy allows full URL same-origin by design under the recommended default | `no-referrer` /`same-origin` on sensitive pages; CSP script allowlists | 
| Email clients prefetching links | Different client stack | Single-use tokens; do not put long-lived secrets in query strings | 

`strict-origin-when-cross-origin`
`no-referrer` or `same-origin`
`curl -sI` and a DevTools cross-origin click
For most product apps, yes as a default. It keeps path and query off cross-origin requests and strips referrers on HTTPS→HTTP downgrades. Sensitive flows (password reset, impersonation, billing) still deserve `no-referrer` or `same-origin`.

It can reduce the path-level detail third parties receive. Origin-only or missing referrers are common under modern defaults. If you need campaign attribution, put UTM parameters on links you control and accept that full-path referrers to arbitrary third parties are not worth the leak.

The header (or meta tag) sets a document default. `rel="noreferrer"` and the `referrerpolicy` attribute override per link. Use the header globally, then override on specific outbound anchors.

Yes. `fetch`, XHR and subresources send `Referer` according to the policy (and the request's `referrerPolicy` option). A global header covers navigations and most subresources; explicit `referrerPolicy: "no-referrer"` in `fetch` helps for sensitive XHRs.

You can, if you do not rely on inbound referrers for security or analytics. Many teams prefer `strict-origin-when-cross-origin` site-wide and `no-referrer` only on secret-bearing pages so first-party analytics still see full same-origin paths.

Open a staging page whose URL contains a dummy `?token=test`, click a cross-origin link or load a cross-origin image, and inspect the outbound `Referer` in DevTools. Repeat after setting the header until the token disappears from cross-origin requests.
