[referrer] Providing safer policy states

The Referrer Policy spec as it stands addresses very well the problem of
lost Referrers interfering with HTTPS adoption. If we're going to enable
developers to opt into a "less safe" behavior to avoid blocking their
move to HTTPS, we'd like to also enable them to use this feature to opt
into a safer behavior.

Currently, the spec only includes a single policy state that is strictly
safer than the default: no-referrer. Other policy states that could be
used to tighten the referrer further (i.e. "origin" or
"origin-when-cross-origin") unfortunately fail to maintain the
"no-referrer-when-downgrade" property, as the spec correctly warns in
the notes that accompany these.


TL;DR

We’re proposing 3 new policy states to fill that gap:

- "same-origin" (https://github.com/w3c/webappsec-referrer-policy/pull/19)
- "origin" without downgrades
- "origin-when-cross-origin" without downgrades

We would also be willing to consider having a separate policy for
downgrades, but we think specifying a few new policies is cleaner.


DETAILS

Fundamentally, what we want to address is that of all of the logically
useful policies, only half are currently specified:


                               Same origin  Cross-origin  Downgrade
                               loads        loads         loads
===================================================================
 "no-referrer"                 none         none          none
-------------------------------------------------------------------
                               origin       none          none
-------------------------------------------------------------------
 (proposed)                    origin       origin        none
-------------------------------------------------------------------
 "origin"                      origin       origin        origin
-------------------------------------------------------------------
 (proposed)                    full         none          none
-------------------------------------------------------------------
 (proposed)                    full         origin        none
-------------------------------------------------------------------
 "origin-when-cross-origin"    full         origin        origin
-------------------------------------------------------------------
 "no-referrer-when-downgrade"  full         full          none
-------------------------------------------------------------------
                               full         full          origin
-------------------------------------------------------------------
 "unsafe-url"                  full         full          full
-------------------------------------------------------------------


(Of the 27 combinatorial possibilities here, we’re only considering ones
where same-origin >= cross-origin >= downgrade, which seems like a
sensible invariant to enforce.)

There are two basic approaches to providing the missing functionality:

 1. Adding more policy states (to label more of the boxes), or
 2. Adding a separate attribute/flag (to handle downgrades separately).


Adding policy states
--------------------

Taking "origin" as an example, we would add extra policy states by:

- Renaming "origin" to "unsafe-origin", and
- Creating a new "origin" which sends no-referrer in case of downgrades.

If we’re not willing to break backwards compatibility with the working
draft (a "safe by default" approach), we could instead introduce a
"safe-origin" state and leave "origin" as it is (an "opt into safety"
approach).

Similarly, we would need a non-downgrading version of the
"origin-when-cross-origin" state. Also, we have proposed a separate
"same-origin" state.


Adding a new flag to enable/disable downgrades
----------------------------------------------

Instead of a new policy attribute, we could introduce a new
"referrerOnDowngrade" attribute which would use "no-referrer" for
downgrades but otherwise honor the "referrerPolicy" attribute.

e.g. <a href="..." referrerPolicy="origin-when-cross-origin"
referrerOnDowngrade="yes"></a>

These attributes would take the following values:

- "referrerPolicy" = { "full", "origin-when-cross-origin", "origin",
"no-referrer" }
- referrerOnDowngrade = { "yes", "no" }

And their defaults would be:

- "referrerPolicy": "full"
- "referrerOnDowngrade": "no"


Adding a separate policy attribute
----------------------------------

Alternatively, we could introduce a new attribute by:

- Renaming the existing "referrerPolicy" attribute to
"unsafeReferrerPolicy" which would apply to all loads including
downgrades, and
- Adding a new "refererPolicy" attribute which would apply to
non-downgrade loads and use no-referrer for downgrades.

e.g. <a href="..." referrerPolicy="full" unsafeReferrerPolicy="origin"></a>

These attributes would take the following values: "full",
"origin-when-cross-origin", "origin", "no-referrer".

And their defaults would be:

- "referrerPolicy": "full"
- "unsafeReferrerPolicy": "no-referrer"

Of course, we’d need to change the header and meta element in the same way.


Francois (with lots of input from Dan, Franziskus, Richard and Tanvi)

Received on Wednesday, 30 March 2016 21:56:07 UTC