-
Notifications
You must be signed in to change notification settings - Fork 27
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
Expand storage-access-preserving navigations to include same-origin-initiated navigations, not just self-initiated. #197
Comments
@arturjanc: you had security concerns on the origin boundary w.r.t. navigations initiated by documents with storage access. Does this maintain the security invariants you wanted? I don't recall why the navigation was required to be self-initiated. |
This change makes sense to me and I don't think it will undermine the security properties we care about here. The motivation behind the self-initiated restriction was to prevent a cross-origin embedder from navigating an iframe that received storage access to an arbitrary endpoint on the iframe's site chosen by the embedder (and e.g. clickjack it or leak data). But allowing same-origin-initiated navigations to maintain storage access is fine because it still protects the iframe from these kinds of navigations, so I think we can safely allow it. |
I think @johannhof was also interested in allowing this for the same site, no? |
Dumb question: can you even initiate a navigation in a same-site-but-cross-origin iframe if you're not the embedder? You generally shouldn't be able to navigate cross-origin frames except in a few cases, e.g. you have an embedder/embeddee relationship - I think we tightened this a few years ago, but don't remember exactly where we landed on that. Basically, I'm not sure in which scenarios allowing same-site navigation would be useful here. |
That's not something that's currently well-defined unfortunately. whatwg/html#313 goes into some of it. |
Hi 👋 I'm the reporter of the Firefox bug that @bvandersloot-mozilla mentions. And the question whether storage access should be propagated to a nested same-site or same-origin iframe is alse very relevant to us. Our setup looks like this:
Reading the discussion in this issue, it seems that propagating the storage access automatically to nested same-site iframes could be possible to standardize and implement? That would solve all our problems. After all, if
But when this tree of same-site iframes is embedded in a cross-origin document, and the top-level iframe of this tree is granted storage access, it's a similar situation, but the nested iframes don't get access. |
My concern with a change like this is that it makes it hard to "drop" unpartitioned cookie access once you've gotten it, even if you want to. Today, an iframe can drop cookie access just by opening a new iframe and not requesting access there. With this change, that's no longer possible. It seems like a step backward to the unsafe default of having unpartitioned cookie access without having asked for it, IMO. Instead, I think a better solution for this is to use the Storage Access Headers proposal, specifically the @jsnajdr, I think there might be a misunderstanding on your third point - although storage access is not automatically propagated to the nested iframe, the nested iframe can call |
I like that approach, if we can get a 3-engine consensus on the storage access headers :) |
Oh yes, this has been the missing piece and it works! And it works around the Firefox "bug" I reported. Initially, the frame load request is sent without unpartitioned cookies and the frame doesn't have storage access. But I can do this: if (!await document.hasStorageAccess()) {
await document.requestStorageAccess();
window.location.reload();
} After the access was granted, I reload the frame. This time the request is sent with unpartitioned cookies, and after the load the frame has storage access automatically, without having to ask for it. With Storage Access Headers, the above script can be replaced with a response header
I see, the design principle is that no embedded frame should automatically get storage access until it asks for it explicitly. The default is "no access". But that means that Firefox does it right (not sending unpartitioned cookies on the initial load) and it's Chrome that has a bug. If the embedded frame doesn't have storage access by default, then the load request shouldn't have unpartitioned cookies. If it has them, it means that the frame effectively does have unpartitioned access, because the server response can contain data derived from the unpartitioned cookies. |
Yeah, there's a tradeoff between security and performance here. We're exploring that tradeoff space in privacycg/storage-access-headers#6; feel free to take a look and contribute if you have more ideas.
Maybe I'm misunderstanding, but from your initial description I understood that the embedded iframe does request storage access: |
This is the core question that Firefox and Chrome are answering differently. Which iframe really does the fetch? Is it the parent iframe (and its Chrome thinks that the parent iframe does the fetch, doing it for the child iframe. Firefox thinks that the child frame does it, doing it for itself. Is there a place in the HTML or Fetch standard that would state clearly which I noticed another difference between how Firefox and Chrome treat the iframe fetch differently. When there is a
Here, both browsers agree that the fetch is not
But in Firefox it's still |
As to "who does the fetch", I would defer to @annevk for authoritative knowledge of the current specification. In any case, I don't think we should be dogmatic about what the current spec says but consider what the best developer experience would be instead. I agree that it's very confusing to have a credentialed document load and then no subsequent storage access in the document, since developers are likely to already make a decision about what content to render based on the server-side presence of cookies or not. It could also lead to subtle issues where most of the pre-rendered page works well but then subsequent credentialed subresource requests fail. So, either we completely exclude nested same-site iframes from receiving storage access without rSA (or headers) or we always propagate the storage access bit to same-site children. I'm leaning towards the latter. I haven't really seen clear evidence of a practical attack that would be possible against those nested iframes, especially one that isn't also applicable to any other same-site resource loaded by the original iframe. Without this kind of reasoning for restricting it, I think we should prefer developer utility and simplicity here. |
I was testing this with Safari (17.2.1) today and found that it already propagates the access to a nested same-site iframe:
However, there is a weird bug when
doesn't work in Safari when a top-level frame (which never asked for access, because why would it when it's the top-level document) embeds a same-site iframe. This is already reported in WebKit since 4 years ago, and @johnwilander responded "I made a review comment about this in the ongoing Storage Access API spec work." But there are no details about the location and the content of the review comment, and the bug is still there today. |
Conceptually, I see this similarly to what @cfredric outlined above, i.e. it seems a bit cleaner for each document to require explicit calls to OTOH, looking at this purely from a security perspective I think @johannhof is right that we don't have a compelling reason to disallow automatic propagation of storage access:
One concern that @ddworken came up with is whether a cross-site ancestor, e.g. the top-level page, is permitted to navigate the nested frame (which, as @annevk points out above, is not well-defined) -- my hope is that it shouldn't. But if it was, then it could navigate that nested frame to a different endpoint same-site with the frame that requested storage access; so we would need to prevent this from happening, similarly to the self-initiated restriction we discussed above. Overall, to me this boils down to the ergonomic benefit of automatically propagating storage access. Ideally, if this affects only a small number of widgets, we could forego this and require nested frames to call rSA. But if this introduces a burden on many developers building widget that request storage access, I think automatically propagating access to same-site frames would be okay. |
Following up on the discussion about whether an iframe load request should initially have storage access or not. There is a surprising relation to CHIPS and partitioned cookies, as pointed out in privacycg/CHIPS#88. Depending on whether the request has storage access or not, a different set of cookies will be sent with it, and the server will send different That means that the |
@jsnajdr the question of how CHIPS partition keys should be defined seems like it's best discussed in privacycg/CHIPS#88; let's discuss there, since that question seems somewhat unrelated to this issue. (With that said, I agree with what @aselya said there. IMO it would be very confusing if an iframe's partition key could change over time; and the isolation that you're trying to achieve is still possible by simply not using partitioned storage.) |
We got this bug filed on Firefox: Bug 1876504 - With storage access granted, nested iframe is loaded without cookies
The user has an iframe with storage access and loads a same-origin iframe nested inside the first iframe. The subdocument fetch behaves differently among browsers. In the spec, I believe it is ambiguous whether or not this request should get unpartitioned cookies, pending the result of the cookie-layering work. However it is clear that the resulting window should not have storage access initially.
Chrome now sends unpartitioned cookies on the subdocument fetch, then does not give access to the subdocument's unpartitioned cookies initially. This is weird, and I think we should make these two align. Firefox gives neither unpartitioned cookies. This is consistent, but increases developer friction.
To solve this, I propose we generalize our propogation of the has storage access state to not be self-initiated but instead be same-origin-initiated. This does not meaningfully change the security properties of which documents may get storage access in my view, maintaining origin-granularity over which subdocuments can ever access their unpartitioned cookies.
The text was updated successfully, but these errors were encountered: