Open zenhack opened 4 years ago
If there was an easy way to just diff the CSP headers an app sends and apply whichever is more restrictive that'd probably be the easiest to explain to developers and the most flexible. I also have a few routes I want to be more restrictive than others (serving untrusted content and setting sandbox
attributes) and it would be nice to differentiate. But I could get by with an app-wide package definition.
I guess we could add the information to the response types in web-session.capnp, and then have the bridge handle it.
Isn't the bridge inside the app though? Couldn't one then implement a bridge with a less restrictive CSP?
Maybe I wasn't super clear. The idea would be, we'd first add fields to the Response
struct:
...for each of the csp sources we want apps to be able to use. So we might do something like:
enum CspSrc {
self @0;
dataUrl @2;
blobUrl @3;
eval @4;
# ...
}
struct Response {
# ...
defaultSrc :CspSrc;
scriptSrc :CpsSrc;
# ...
}
Importantly, this type would not include variants for anything that we don't want apps to be able to allow. This is the same thing we do with everything else in the HTTP protocol; you'll note many statuses, headers & such do not have representations in web-session, which means that the grain does not even have a way of telling sandstorm it would like to set them, since the web-session protocol can't even represent them.
The bridge would only be responsible for translating between raw http (spoken by the app), and the web-session protocol, per usual. If the app sets script-src: https://evilcorp.example.com
, the bridge has no way of honoring this, since there's no CspSrc
value that maps to an https:
directive.
Ah, okay. Thanks for explaining.
Apparently you can set multiple CSP headers, and the browser will do the work of figuring out the intersection: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy#multiple_content_security_policies
3409 adds a content-security-policy for grains running in a ui session, which (except for some holes that we'll plug in the future) prevents grains from leaking info to the outside world from the client via any mechanism csp can control.
However, the policy does allow some things that csp can block, and that might be useful to block as an app-bug mitigation measure: things like inline scripts and use of
eval()
.We can't just hard-block these unconditionally, because many apps actually use them, but it would be nice if apps that don't could opt in to the extra protection offered by a CSP that blocks these things.
My notion of what this would look like is that we'd add some fields to the package definition indicating whether to enable these extra protections. The default in the schema file would be off, so that it doesn't change the behavior for existing apps, but
spk init
should generate package definitions that explicitly turn these on, so they're the default for "new" apps, unless the packager opts out of them.