Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CSP: Provide a way to restrict domain of document.cookie #432

Open
kentonv opened this issue Jul 21, 2015 · 15 comments
Open

CSP: Provide a way to restrict domain of document.cookie #432

kentonv opened this issue Jul 21, 2015 · 15 comments
Assignees
Labels
Milestone

Comments

@kentonv
Copy link

kentonv commented Jul 21, 2015

Sandstorm.io could benefit from being able to use Content-Security-Policy to restrict the set of origins for which cookies can be assigned via document.cookie (in our case, we want to restrict it to only the current origin).

It would also be nice -- though less important -- to be able to restrict the set of cookies readable through document.cookie to only those which were originally set on some set of origins (in our case, only the current origin).

The goal is effectively to self-impose something like what the Public Suffix List does, except on a dynamic basis controlled via HTTP headers.

Background: Sandstorm servers assign sub-domains to individual apps with the intent that those apps be prevented from communicating with each other. Currently, we believe we are able to use Content-Security-Policy or other measures to prohibit all forms of communication between apps except for cookies: an app can assign a cookie on the parent domain and all other apps can then read that cookie.

The problem cannot be solved using the Public Suffix List because Sandstorm is designed to be decentralized -- every user potentially runs their own server, on their own domain. (Additionally, there are other technical reasons why the PSL is a bad fit even for large multi-tenant Sandstorm servers.)

Note that Sandstorm already acts as an HTTP proxy in front of app servers. Therefore, we are already able to control HTTP-level cookies. Only document.cookie is problematic.

@annevk
Copy link
Member

annevk commented Jul 21, 2015

Additionally, there are other technical reasons why the PSL is a bad fit even for large multi-tenant Sandstorm servers.

Off-topic, but I would love to hear these.

Would disabling document.cookie altogether be fine? Also, restricting document.cookie, but not document.domain, seems risky.

@hillbrad
Copy link
Contributor

I wonder if this is a job for Suborigin Namespaces?

https://www.chromium.org/developers/design-documents/per-page-suborigins

The current proposal simply says that cookie access is not allowed and they
must be explicitly communicated from an un-namespaced page, but perhaps a
filter syntax could be specified?

@annevk
Copy link
Member

annevk commented Jul 21, 2015

Suborigins doesn't help with restricting things to origins, I think.

@hillbrad
Copy link
Contributor

I'm thinking about the more general problem of isolating apps that share
some part of the same origin hierarchy that motivated the question. Maybe
that proposal obviates the need for this one?

@annevk
Copy link
Member

annevk commented Jul 21, 2015

Maybe, though restricting document.cookie / document.domain through CSP seems like an obvious easy win (and might even allow some JavaScript engine perf optimizations), whereas suborigins are way complex.

@mikewest
Copy link
Member

@metromoxie will have opinions about suborigins and cookies, I suppose. It's possible that that proposal will meet the entire need expressed here.

That said, for CSP, I agree with @annevk that restricting the JavaScript API is pretty much in line with other things that CSP does. If we need to restrict domains, then a -src-style directive seems appropriate (cookie-domain sub.example.com might disallow example.com for instance, and `cookie-domain 'none' might disable the API completely?). That seems like it might have legs.

@mikewest mikewest added this to the CSP 3 milestone Jul 21, 2015
@mikewest mikewest added the CSP label Jul 21, 2015
@kentonv
Copy link
Author

kentonv commented Jul 21, 2015

Additionally, there are other technical reasons why the PSL is a bad fit even for large multi-tenant Sandstorm servers.

Off-topic, but I would love to hear these.

Mainly, we'd prefer for apps to be at subdomains of the Sandstorm server's main interface. If we were using the PSL to prevent apps from setting cookies on parent domains, that would mean the main interface would itself be in the PSL. It's unclear to us whether this would actually work in our case (it might, since we use localStorage rather than cookies for authentication), but it seems like it's not the intended use of the PSL. E.g. the effects on local storage quota might be all wrong.

In any case, since we can't very well tell every user to add themselves to the PSL, it's a moot point.

Would disabling document.cookie altogether be fine?

No. Many of our apps are ports not originally designed to work inside Sandstorm, and many of them use cookies. Forcing changes to avoid cookies would be too disruptive.

Also, restricting document.cookie, but not document.domain, seems risky.

We also want to restrict document.domain. I was under the impression that CSP could already do this, but maybe I'm thinking of the case where sandbox origin is applied (which is too restrictive for us).

I think a single rule that restricts both makes a lot of sense, but separate rules is also fine.

@paulproteus
Copy link

I agree with @kentonv above, and just want to clarify one thing Kenton said:

In any case, since we can't very well tell every user to add themselves to the PSL, it's a moot point.

Sandstorm.io is open source software that many people run on servers they control. Therefore, we (the Sandstorm team, the software providers) don't know what domains people will run Sandstorm on, so we can't ask for all those domains to be added to the public suffix list.

We want Sandstorm self-hosters to have solid security for the apps they run, and since the Sandstorm software does place a proxy between (mutually untrusted) apps and the browser, one convenient way to achieve cookie confinement could be a new Content-Security-Policy rule to constrain document.cookie.

(Just hoping to clarify the possible confusion between "Sandstorm a hosted service" and "Sandstorm the software people can run on their own servers.)

@mikewest mikewest self-assigned this Jul 23, 2015
@enygren
Copy link

enygren commented Aug 27, 2015

I also believe this functionality would be valuable. For example, as a:

 Content-Security-Policy: cookie-scope=origin

or:

 Content-Security-Policy: cookie-scope=host

that would constrain document.cookie to only be able to set cookies on the same origin or host.
Some previous discussion from CSP 2 (which missed the boat at that point in time):
https://lists.w3.org/Archives/Public/public-webappsec/2013Sep/0046.html

@Haravikk
Copy link

Haravikk commented Dec 9, 2015

I'm another person that came looking for a cookie restriction in the CSP header; I was kind of surprised it isn't there already actually, though I suppose CSP wasn't really designed with sub-origins in mind.

A fetch type directive that falls back to default-src would be ideal IMO, though it may make sense as others have suggested to name it something like cookie-domain to emphasise that it is a restriction for both reading and creating cookies.

With HTML5 now so capable, and many plugin platforms on the way out it's going to start making sense for sites that currently support uploading of Flash files and similar content to also support content created in HTML5/Javascript, but doing so is currently very challenging from a security point of view. CSP is great for preventing uploaded files from referencing each other (or elements from the parent site), but cookies are still a problem.

Of course in an ideal scenario I would just use per-user domains, but unfortunately my preferred certificate authority doesn't currently issue wildcard certificates, and my reverse proxy (CloudFlare) only caches wildcard domains on their $5,000/month enterprise plan, which is a little steep for my free website! I'm isolating uploaded content under its own sub-domain to simplify things a bit, but it'd be great if I could do more to restrict content to sub-directories so long as sub-domains remain out of my reach.

Also I wanted to ask, but does anyone know if such restrictions on cookies can be applied to SWF (Flash) files as well? I know that Flash shared objects can be cleared by browsers now, but do browsers get any other control over them?

@mikewest
Copy link
Member

@Haravikk: Sorry, I don't really understand the suggestion you're making. Can you give me an example of what kind of header you'd send, and what the effect would be?

@Haravikk
Copy link

Well, I was thinking that using nginx capture groups I could do something like the following:

location ~ /([^/]+)/([^/]+) {
    add_header Content-Security-Policy "default-src $scheme://$server_name/$1/$2; cookie-domain $scheme://$server_name/$1;";
}

Assuming the first directory is a user name, and the second is the name of something they've uploaded (in its own directory). So for my own files I might end up with a header like:

default-src http://mydomain.com/haravikk/something; cookie-domain http://mydomain.com/haravikk;

i.e- fetch requests would be restricted to the same directory as the uploaded file(s) themselves, but cookies could be declared for all uploads by the same author, but not for the root domain itself. Essentially, I could allow a user to upload web-page or app named something without having it interfere with others uploaded by other users.

Ideally this could be applied for SWF shared objects too (since they're basically the same thing as cookies), but I have no idea if that is possible, even with the extra capabilities of the NPAPI plugin (which allows shared objects to be cleared just like regular cookies).

I realise this may have some crossover with Google's sub-origins (which they seem to hope might be implemented as a CSP directive, making the issue even muddier), but with URLs and cookies I think use cases like this would be pretty well covered.

@sindastra
Copy link

What happened to cookie-scope? https://www.w3.org/TR/csp-cookies/

cookie-scope: http

Would restrict the use of document.cookie altogether but the specification is not being worked on anymore. 🤔

I think cookie-scope is a good idea to be worked on and perhaps even expanded for fine-tuning?

@sindastra
Copy link

sindastra commented Dec 22, 2019

Suggestion: Create two cookie scopes, one that controls HTTP cookies and one that controls JavaScript cookies and use the same syntax as resource loading. An example could be:

cookie-scope-js: 'none'
cookie-scope-http: 'self' https://*.example.com

Or even add cookie-scope-active to control any form of active content that could set cookies (i.e. JS and other non-HTTP cookies), if applicable.

An example could be:

cookie-scope-active: 'none'
cookie-scope-js: 'self'
cookie-scope-http: 'self' https://*.example.com

Which would allow for precise control which domains/protocols may set which kind of cookies.

[EDIT]: Turned my suggestion into an issue: #561

@simonw
Copy link

simonw commented Dec 5, 2021

I found this thread while researching whether or not CSP could be used to prevent untrusted code on a subdomain from setting or reading cookies from other sub domains. My use-case is exactly the same as the one described by Sandstorm in the first post in this issue: I want the equivalent of being listed on the public suffix list by without first waiting to get listed (and for all of the browsers to update from it).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

9 participants