SECURE_REFERRER_POLICY recommendations

For 3.0 SECURE_REFERRER_POLICY was added and also included on the python manage.py check --deploy command. My question is: what default do people typically use and why given the developer should set one?

I understand there are 8 different options and the docs recommend same-origin referrers so CSRF protection occurs.

So…default to same-origin? What are some examples where strict-origin or strict-origin-when-cross-origin make more sense?

Thanks for insight y’all!

-Will

I just had to use strict-origin-when-cross-origin to make my Django project read media files from Amazon S3.

I’m a newbie, though! Please let me know if I can make it same-origin (and how) for this scenario!

same-origin passes the referrer only when the origin remains the same, but not when you move origin or when you downgrade the protocol (I think). It also includes the full referrer (path and query string are included).

strict-origin exposes the origin to other sites, but never passes path or query string. It also doesn’t expose the referrer on protocol downgrades.

strict-origin-when-cross-origin protects the referrer on downgrades, sends the origin as a referrer to other sites, and uses the fill referrer on your own domain.

The latter two are required for user tracking, when you want to allow other pages to see where your their users were coming from.

TL;DR: I’d go with strict-origin if you can.

I updated Django 3.1 to default it to same-origin: https://docs.djangoproject.com/en/3.1/releases/3.1/#security . I say stick with it til it breaks.

@MrCordeiro that sounds to me like you’ve explicitly configured S3 to only allow serving images when the referer header is set to your domain, in your s3 bucket policy? It’s not a default behaviour. That’s a very rudimental hotlink protection and should not be relied on for any kind of security. I found this Stack Overflow post on the subject, with some alternatives: https://stackoverflow.com/questions/46010789/restricting-access-to-aws-s3-bucket-based-on-referer .

1 Like

@adamchainz, do have a solution that does not involve having to set up Cloudflare or a lambda function on Node.js like that stack overflow post does? This was supposed to be a very simple app hosted on heroku and static files on S3. What would be a simpler way to have a secure setup in this scenario?

I think what you’re looking for are “Pre-Signed URLs” in the S3 world. To use them, my recommendation would be to use django-storages. That provides integrations for static and media files to be placed in S3 buckets. Setting the ACL on the bucket and in django-storaged to the canned ACL authenticated-read would then generate signed URL, if I’m not mistaken.

1 Like

Yes Markus’ recommendation is right. It seems django-storages defaults to presigned URL’s with its setting AWS_QUERYSTRING_AUTH.

1 Like

Thanks @adamchainz and @MarkusH!

I’m having some problem setting it up. The django-storages/aws docs are not helping much, maybe I need some sort of tutorial (I’ve asked over stackoverflow so I don’t derail the thread any further). So my settings are now:

  • AWS_DEFAULT_ACL = 'authenticated-read'
  • SECURE_REFERRER_POLICY = 'same-origin'

And on AWS, I had a programmatic user with accesses (from what I understood I need to add it on the bucket’s ACL but it asks for a canonical ID I cannot find), a policy allowing for the root user to do everything and, as @adamchainz correctly surmised, a policy that checks if the referrer header is set to the domain (which I think I can delete by now, right?).

I believe you can delete the bucket policy for the referer header.

And yes, S3 permissions are a mess. I’ve used Scaleway object store with great success recently - https://www.scaleway.com/en/object-storage/ - S3 compatible, fewer permissions, free up to 75GB.

1 Like

What are your views for each referrer policy use case, @wsvincent?