Move CSP from nsIPrincipal into the Client
Categories
(Core :: DOM: Security, task, P2)
Tracking
()
Tracking | Status | |
---|---|---|
firefox69 | --- | fixed |
People
(Reporter: grobinson, Assigned: ckerschb)
References
(Depends on 3 open bugs, Blocks 13 open bugs, Regressed 1 open bug)
Details
(Whiteboard: [domsecurity-active][wptsync upstream])
Attachments
(4 files, 19 obsolete files)
Reporter | ||
Updated•11 years ago
|
Reporter | ||
Updated•11 years ago
|
Comment 1•11 years ago
|
||
Updated•10 years ago
|
Assignee | ||
Comment 2•10 years ago
|
||
Assignee | ||
Comment 3•10 years ago
|
||
Comment 4•10 years ago
|
||
Comment 5•10 years ago
|
||
Comment 6•9 years ago
|
||
Assignee | ||
Updated•9 years ago
|
Assignee | ||
Updated•8 years ago
|
Assignee | ||
Updated•8 years ago
|
Comment 7•8 years ago
|
||
Comment 8•8 years ago
|
||
Comment 9•8 years ago
|
||
Comment 10•7 years ago
|
||
Comment 11•7 years ago
|
||
Assignee | ||
Updated•7 years ago
|
Assignee | ||
Comment 12•7 years ago
|
||
Comment 13•7 years ago
|
||
Assignee | ||
Comment 14•7 years ago
|
||
Comment 15•7 years ago
|
||
Comment 16•7 years ago
|
||
Comment 17•7 years ago
|
||
Comment 18•7 years ago
|
||
Assignee | ||
Comment 19•7 years ago
|
||
Comment 20•7 years ago
|
||
Assignee | ||
Comment 21•7 years ago
|
||
Comment 22•7 years ago
|
||
Assignee | ||
Comment 23•7 years ago
|
||
Comment 24•7 years ago
|
||
Comment 25•7 years ago
|
||
Assignee | ||
Comment 26•7 years ago
|
||
Comment 27•7 years ago
|
||
Assignee | ||
Comment 28•7 years ago
|
||
Assignee | ||
Comment 29•7 years ago
|
||
Assignee | ||
Comment 30•7 years ago
|
||
Comment 31•7 years ago
|
||
Assignee | ||
Comment 32•7 years ago
|
||
Comment 34•7 years ago
|
||
Comment 35•7 years ago
|
||
Comment 36•7 years ago
|
||
Assignee | ||
Comment 37•7 years ago
|
||
Assignee | ||
Comment 38•7 years ago
|
||
Assignee | ||
Updated•7 years ago
|
Comment 39•7 years ago
|
||
Assignee | ||
Comment 40•7 years ago
|
||
Assignee | ||
Comment 41•7 years ago
|
||
Assignee | ||
Comment 42•7 years ago
|
||
Comment 43•7 years ago
|
||
Assignee | ||
Comment 44•6 years ago
|
||
Assignee | ||
Comment 45•6 years ago
|
||
Assignee | ||
Comment 46•6 years ago
|
||
Comment 47•6 years ago
|
||
Assignee | ||
Comment 48•6 years ago
|
||
Assignee | ||
Comment 49•6 years ago
|
||
Assignee | ||
Comment 50•6 years ago
|
||
Assignee | ||
Updated•6 years ago
|
Comment 51•6 years ago
|
||
Assignee | ||
Comment 52•6 years ago
|
||
Assignee | ||
Comment 53•6 years ago
|
||
Assignee | ||
Comment 54•6 years ago
|
||
Assignee | ||
Comment 55•6 years ago
|
||
Assignee | ||
Comment 56•6 years ago
|
||
Assignee | ||
Comment 57•6 years ago
|
||
Assignee | ||
Comment 58•6 years ago
|
||
Assignee | ||
Comment 59•6 years ago
|
||
Assignee | ||
Comment 60•6 years ago
|
||
Assignee | ||
Comment 61•6 years ago
|
||
Comment 62•6 years ago
|
||
Assignee | ||
Comment 63•6 years ago
|
||
Assignee | ||
Comment 64•6 years ago
|
||
Assignee | ||
Comment 65•6 years ago
|
||
Assignee | ||
Comment 66•6 years ago
|
||
Comment 67•6 years ago
|
||
Assignee | ||
Comment 68•6 years ago
|
||
Updated•6 years ago
|
Assignee | ||
Comment 69•6 years ago
|
||
Assignee | ||
Comment 70•6 years ago
|
||
Assignee | ||
Comment 71•6 years ago
|
||
Assignee | ||
Comment 72•6 years ago
|
||
Assignee | ||
Comment 73•6 years ago
|
||
Assignee | ||
Comment 74•6 years ago
|
||
Assignee | ||
Comment 75•6 years ago
|
||
Assignee | ||
Comment 76•6 years ago
|
||
Assignee | ||
Comment 77•6 years ago
|
||
Assignee | ||
Comment 78•6 years ago
|
||
Assignee | ||
Comment 79•6 years ago
|
||
Assignee | ||
Comment 80•6 years ago
|
||
Comment 81•6 years ago
|
||
Assignee | ||
Comment 82•6 years ago
|
||
Comment 83•6 years ago
|
||
Updated•6 years ago
|
Assignee | ||
Comment 84•6 years ago
|
||
Assignee | ||
Comment 85•6 years ago
|
||
Assignee | ||
Comment 86•6 years ago
|
||
Assignee | ||
Comment 87•6 years ago
|
||
Comment 88•6 years ago
|
||
Assignee | ||
Comment 89•6 years ago
|
||
Assignee | ||
Comment 90•6 years ago
|
||
Comment 91•6 years ago
|
||
Assignee | ||
Comment 92•6 years ago
|
||
Assignee | ||
Comment 93•6 years ago
|
||
Assignee | ||
Comment 94•6 years ago
|
||
Updated•6 years ago
|
Assignee | ||
Comment 95•6 years ago
|
||
Assignee | ||
Comment 96•6 years ago
|
||
Assignee | ||
Comment 97•6 years ago
|
||
Assignee | ||
Comment 98•6 years ago
|
||
Assignee | ||
Comment 99•6 years ago
|
||
Assignee | ||
Comment 100•6 years ago
|
||
Assignee | ||
Comment 101•6 years ago
|
||
Updated•6 years ago
|
Comment 102•6 years ago
|
||
Assignee | ||
Comment 103•6 years ago
|
||
Comment 104•6 years ago
|
||
Comment 105•6 years ago
|
||
Assignee | ||
Comment 106•6 years ago
|
||
Comment 107•6 years ago
|
||
Assignee | ||
Comment 108•6 years ago
|
||
Comment 109•6 years ago
|
||
Assignee | ||
Comment 110•6 years ago
|
||
Assignee | ||
Comment 111•6 years ago
|
||
Assignee | ||
Comment 112•6 years ago
|
||
Updated•6 years ago
|
Assignee | ||
Updated•6 years ago
|
Assignee | ||
Comment 113•6 years ago
|
||
Assignee | ||
Comment 114•6 years ago
|
||
Comment 115•6 years ago
|
||
Assignee | ||
Comment 116•6 years ago
|
||
Assignee | ||
Comment 117•6 years ago
|
||
Assignee | ||
Comment 118•6 years ago
|
||
Assignee | ||
Comment 119•6 years ago
|
||
Comment 120•6 years ago
|
||
Assignee | ||
Comment 121•6 years ago
|
||
Comment 122•6 years ago
|
||
Assignee | ||
Comment 123•6 years ago
|
||
Comment 124•6 years ago
|
||
Assignee | ||
Comment 125•6 years ago
|
||
Comment 126•6 years ago
|
||
Assignee | ||
Comment 127•6 years ago
|
||
Assignee | ||
Comment 128•6 years ago
|
||
OK, so I rebased all those patches, fixed remaining wpt-tests and it seems we have a green TRY run now:
https://treeherder.mozilla.org/#/jobs?repo=try&revision=67d5e574db32e9b4df2bc9229ef7da6f7223c9fd
I still need to do some code cleanups but then this should be ready for review.
Assignee | ||
Comment 129•6 years ago
|
||
This is ready for review (finally:
https://treeherder.mozilla.org/#/jobs?repo=try&revision=6a101f5a030119f49c920f42cd4e3ad996fba61b
I'll remove all splinter patches and upload new phab patches.
Assignee | ||
Updated•6 years ago
|
Assignee | ||
Updated•6 years ago
|
Assignee | ||
Updated•6 years ago
|
Assignee | ||
Updated•6 years ago
|
Assignee | ||
Updated•6 years ago
|
Assignee | ||
Comment 130•6 years ago
|
||
Assignee | ||
Comment 131•6 years ago
|
||
Assignee | ||
Comment 132•6 years ago
|
||
Assignee | ||
Comment 133•6 years ago
|
||
Assignee | ||
Comment 134•6 years ago
|
||
Hey Andrew,
thanks for taking on the work and helping review the backend changes within that bug! Let me provide a quick summary which hopefully makes the changes digestible for you.
Let's start with the major benefits:
- Currently the CSP hangs off the Principal and since the SystemPrincipal is a singleton instance which is shared for all system privileged pages it does not allow us to secure chrome privileged pages with a custom CSP for each of those about pages.
- Moving the CSP away from the Principal is a requirement to make nsIPrincipal objects threadsafe.
- We are expecting a performance boost since we do not need to serialize and deserialize a CSP whenever serializing a Principal through IPC.
- The Client better maps a security context than a Principal (at least in terms of CSP execution context).
Let's move on to the actual changes within this bug:
-
Overall idea
Ultimately we want to move the CSP away from the Principal into the Client (within the LoadInfo). The only exception is the CSP for web extensions which (for now) we are going to keep on ExpandedPrincipals which allows us to keep current semantics of BasePrincipal::OverridesCSP(). I added helper functions within the LoadInfo to query the CSP which returns the CSP for that particular load, either from the Client responsible for the load, or the ExpandedPrincipal in case OverridesCSP returns true. Please note that we keep a cached copy of the CSP on the current document, because the Client itself only holds a serialized version of the CSP. To avoid unnecessary deserialization we simply check if we can query the CSP from the document, if not, then we have to take the slow patch and deserialize the CSP. Since the LoadInfo represents the source of truth in terms of security parameters for every network load, the method LoadInfo::GetCSP() encapsulates all of that functionality. -
Parsing the CSP and putting it into the Client:
When CSP is delivered through an http header then nsDocument::InitCSP() performs the task of getting the CSP off the response header and generating the object representation of CSP. We want to keep that part of generating the CSP object generation there, because e.g. if the CSP includes sandbox flags then we want to set up the document using the right flags. However, at this point the Client has not been created yet, hence we only store the CSP on the document and propagate/sync the CSP with the Client whenever it is generated, which happens within nsGlobalWindowInner::EnsureClientSource. -
Inheriting the CSP
In case the CSP needs to be inherited (e.g. a data: URI iframe) the docshell is the entry point into the new document load. We added a member variable to docshell which only is non null in case the CSP needs to be inherited. Within Document::InitCSP() we then query the CSP that needs to be inherited and move it over to the new document. Not having the CSP on the principal anymore complicates a few corner cases where in the old world the principal inhertiance code basically took care of the CSP inheritance. That is not the case anymore in the new world and hence we have to write a little special code e.g. for about:blank loads where we manually have to propagate the CSP because such loads do not go through ::LoadURI. -
Serializing the CSP:
We have options to stringify CSP by calling the ::toString() methods. For deserialzing the CSP we just feed that string into the CSP Parser again. Further, to replicate the CSP correctly, we also need the requestPrincipal, selfURI, referrer, and innerWindowID - hence I added functionality for that. -
Adding CSP to System Privileged Pages:
As mentioned previously, we want to apply CSP to system privileged pages, which should be doable once the CSP lives on the Client. However, we need some special code, e.g. within OverridesCSP() and some other places within our codebase. This patch is not meant to incorporate that change and I added assertions to make sure the Principal is never SystemPrincipal when parsing a CSP. All of that work which allows to apply a CSP to system privileged loads will happen later in Bug 1496418.
I know it's quite a change and I am happy to provide more insights in our video call next week, but I hope this summary provides a basic overview of what we are trying to accomplish!
Thanks,
Christoph
Comment 135•6 years ago
•
|
||
We added a member variable to docshell
Christoph, why do we need this? Generally speaking, a docshell does not correspond to a single load. Furthermore, in the fission world, the docshell where the load starts may not even be the thing the new document is loaded into.
I was figuring the "CSP to inherit" would come from the loadinfo, which is attached to the channel and therefore is available at the point when we set up the document from the channel. Does that not work for some reason?
Assignee | ||
Comment 136•6 years ago
|
||
(In reply to Boris Zbarsky [:bzbarsky, bz on IRC] from comment #135)
Christoph, why do we need this? Generally speaking, a docshell does not correspond to a single load. Furthermore, in the fusion world, the docshell where the load starts may not even be the thing the new document is loaded into.
Boris, this was more of a semantic choice - let me explain:
a) For iframe loads the member variable cspToInherit on the docshell is in fact not needed at all, because we could simply query the CSP to inherit from the embedding document within document::initCSP().
b) For new window loads we explicitly pass the CSP of the 'triggering' document to ::LoadURI(). If the CSP needs to be inherited then I thought it makes sense to temporarily store the CSP which needs to be inherited on the docshell and then pass it on to the document within document::InitCSP(). It felt semantically right to do that (at least to me). Now that you bring that up we could already store the CSP which needs to be inherited on the "new" document channel/loadinfo we create within docshell so that the channel for the new document already holds the new CSP. I guess we need to add clear and more documentation that there is already a CSP within the loadinfo/client at the time we call document::InitCSP(), but not a big deal in the end.
I assume that is what you are suggesting, right? If that is preferred I am happy to incorporate that change - should be a quick fix.
Comment 137•6 years ago
|
||
because we could simply query the CSP to inherit from the embedding document within document::initCSP()
No, for several reasons:
- With fission the embedding document can be in a different process and hence not reachable.
- This is not right semantically. The CSP to inherit comes from the request's client in https://w3c.github.io/webappsec-csp/#initialize-document-csp. For a load in an iframe the client may NOT be the embedding document. A simple example is if the load in the iframe is done via setting its
location.href
. In that case the client is whatever global the code that did the href set is running in, which may not be the embedding document at all.
Please make sure there are tests for this that would have caught that bug.
I assume that is what you are suggesting, right?
I am suggesting that we should generally do what the spec says. The spec stores the CSP on the load, effectively (though it gets it from the load's client dynamically instead of storing a copy; I thought there was a known spec issue filed on this, but I'm not seeing one; I will get one filed). That's what we should do.
By the way, I strongly suggest testing CSP inheritance across different-process toplevel loads if that's not already tested; you should be able to do that right now with the "noopener" bits for window.open.
Comment 138•6 years ago
|
||
I will get one filed
Assignee | ||
Updated•6 years ago
|
Updated•6 years ago
|
Updated•6 years ago
|
Assignee | ||
Updated•6 years ago
|
Assignee | ||
Comment 139•6 years ago
|
||
Mike,
within this bug we are going to move the CSP from the Principal into the Client. In turn that causes some changes to the current serialization format of: (a) the Principal, and (b) the ContentSecurityPolicy:
Ad (a) ContentPrincipal::Read() and Write() [see part 1 of the changesets attached]
For now we are going to continue to write NS_WriteOptionalCompoundObject() with a 'nullptr' as the CSP, so that the format itself does not change - only the CSP itself is not serialized to disk anymore. On the way back we read that information but do not consume it. FWIW, the actual CSP is serialized separately within nsISHEntry (we started writing and explicit CSP into the history entry within Bug 1518454).
Ad (b) nsCSPContext::Read() and Write() [see part 1 of the changesets attached]
We start serializing a Principal within the CSP.
To make sure we are not missing anything I wanted to check with you the following things:
(1) If someone would update to the latest Firefox version, serialize something to disc and then revert to an older Firefox version we would be in trouble, because for (a) we would not have a CSP to read back in the Principal and (b) the serialized Principal within the CSP would corrupt the deserialization of the CSP.
(2) If we would have to back out that changeset, we would face the same problems. This second problem can be somewhat mitigated by the fact that we are planning to land this changes next week (or at least as early in the new cycle as possible) and rather fix problems than backing changes out.
FWIW, :jkt is working on a better serialization format for Principals within Bug 1508939 which would help to mitigate the problems outlined in (a) but not in (b).
Can we take the risks outlined or is that a no-go?
Updated•6 years ago
|
Assignee | ||
Comment 140•6 years ago
|
||
(In reply to Christoph Kerschbaumer [:ckerschb] from comment #139)
Can we take the risks outlined or is that a no-go?
FWIW, :jkt and I worked out a testing plan that provides some confidence we are not breaking principal serialization for the two cases outlined within comment 139. We added:
- browser/base/content/test/caps/browser_principalSerialization_version1.js
- browser/base/content/test/caps/browser_principalSerialization_csp.js
where the latter uses a hardcoded serialized principal that includes a CSP and ensures that the remaining bits can be read back correctly (even after this bug) so that we have a deserialized principal that is identical to the input modulo the CSP bits. Given that that works and people would just 'loose' the CSP, that seems like a good compromise to me in case people are messing with Firefox versions.
Comment 141•6 years ago
|
||
Hi Chrisptoph, thanks for reaching out!
So if I read comment 140 correctly, this means that current serialized sessions with v1 principals will be deserialized properly when v2 lands, right? So that's the basic thing that should continue to work at the very least.
That first session running v2 will be serialized to disk using v2 principals, thus subsequent restores will work (this is kinda obvious, but still).
The interesting bit, usually, is indeed backward compat. So can sessions serialized using v2 be restored using v1 - a previous Firefox version? If not, that'd be problematic, since we try to be non-destructive in this case at the very least. The way we usually solve that is to introduce a new property name, like triggeringPrincipal_base64v2
, which will be ignored by older clients and thus be treated as there being no principal data available for that tab. I believe that will not break things as badly, right?
But if read comment 140 correctly, we don't even need to worry about the latter scenario, because v2 already takes care of it transparently - which is fantastic :-)
Comment 142•6 years ago
|
||
(In reply to Mike de Boer [:mikedeboer] from comment #141)
The interesting bit, usually, is indeed backward compat. So can sessions serialized using v2 be restored using v1 - a previous Firefox version? If not, that'd be problematic, since we try to be non-destructive in this case at the very least. The way we usually solve that is to introduce a new property name, like
triggeringPrincipal_base64v2
, which will be ignored by older clients and thus be treated as there being no principal data available for that tab. I believe that will not break things as badly, right?
To clarify, are you suggesting if I install Firefox 69 it should be serializing both formats in case I load stable 67? Or simply that the key shouldn't collide?
So are you expecting the history entry to look something like:
entries: [{
url: "https://example.com",
title: "my title",
triggeringPrincipal_base64: Base64Principal,
triggeringPrincipal_base64v2: Base64Encode({"1":{"0":"https://example.com","2":"^privatebrowsing=2"}}),
}
Or like:
entries: [{
url: "https://example.com",
title: "my title",
triggeringPrincipal_base64v2: Base64Encode({"1":{"0":"https://example.com","2":"^privatebrowsing=2"}}),
}
I would prefer if we didn't have to store that duplication.
triggeringPrincipal_base64
currently is used for both as I handle the JSON and downgrade if it's not JSON in the deserialization. The legacy code in older browsers simply won't be able to deserialize either and will effectively not have a principal either.
My current plan in Bug 1508939 was to be able to continue implementing Read
for v1 format such that older profiles can be migrates and then write all new principals with v2.
Comment 143•6 years ago
|
||
Comment 146•6 years ago
|
||
bugherder |
https://hg.mozilla.org/mozilla-central/rev/ddf4012a7652
https://hg.mozilla.org/mozilla-central/rev/3399e7c51942
https://hg.mozilla.org/mozilla-central/rev/63587b402c35
https://hg.mozilla.org/mozilla-central/rev/c5554e93087a
Comment 148•6 years ago
|
||
Christoph can you please take a look at the regressions linked here?
Assignee | ||
Comment 149•6 years ago
|
||
(In reply to Andreea Pavel [:apavel] from comment #148)
Christoph can you please take a look at the regressions linked here?
Yes, me, Jonathan and Basti are on it. Clearing this ni? but keeping others on individual bugs.
Updated•6 years ago
|
Updated•5 years ago
|
Updated•5 years ago
|
Updated•5 years ago
|
Updated•5 years ago
|
Description
•