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

Storage Access Headers #45

Open
cfredric opened this issue Nov 28, 2023 · 8 comments
Open

Storage Access Headers #45

cfredric opened this issue Nov 28, 2023 · 8 comments
Labels
interest: blink Implementer interest from Blink (e.g. Brave, Google/Chrome, Microsoft/Edge)

Comments

@cfredric
Copy link

In the current Storage Access API specification, sites must explicitly opt into accessing their unpartitioned cookies. This explicit requirement is an intentional protection against CSRF, so that embedded iframes can choose whether they want to access unpartitioned cookies or not. However, there's currently only one way to opt into accessing unpartitioned cookies: by calling a JavaScript API. This effectively means that only embedded iframes can opt in, and they have to execute some JavaScript before being allowed to access cookies - even if the user has already granted the relevant permission. This causes unnecessary network traffic and resource loads/reloads.

At TPAC, I presented some slides (see slides 7-12) on ideas for new ways to "opt in" or "activate" an existing permission through the Storage Access API. In particular, the use of an HTTP response header instead of requiring a invocation of the JavaScript API. This generally got positive feedback (IMO) and other browser vendors seemed interested in exploring the ideas, in particular suggesting a complementary request header.

Explainer: https://github.com/cfredric/storage-access-headers

I'd appreciate any additional feedback, comments, concerns, etc. Thank you!

@johannhof johannhof added the agenda+ Request to add this issue to the agenda of our next telcon or F2F label Nov 28, 2023
@johannhof
Copy link
Member

@johnwilander
Copy link

Following up on the PrivacyCG call we just had. I was asked to flesh out the scenario I tried to sketch.

I think browsers who want to enforce 1) per-page access to unpartitioned cookies, 2) with user activation will be under pressure to relax that if developers do this:

  1. The user is on news.example/startPage.
  2. An iframe from thirdParty.example on news.example/startPage gets a tap and requests storage access.
  3. Storage access is granted, either promptless because the user has opted in previously or with a prompt.
  4. The iframe from thirdParty.example signals to the top frame that it now has storage access.
  5. The top frame navigates to news.example/nextPage presenting the news or whatnot.
  6. Subresources from thirdParty.example on news.example/nextPage send the storage access HTTP response header because they "know" that news.example will only ever navigate the user to news.example/nextPage after storage access has been granted to thirdParty.example.

Per-page storage access with user activation will not work in the above case. Browser who prefer that as their privacy boundary will be pressured to either quirk all such websites or relax their storage access policy.

@bvandersloot-mozilla
Copy link

@johnwilander: We talked a bit about the privacy benefits of per-page access to unpartitioned cookies in the meeting- I wanted to follow up. You said that we shouldn't presume collaboration between first and third parties when setting our threat model, and I still agree.

However I don't think a third party requires collaboration to link their partitioned and unpartitioned storages permanently after a single grant. Here is the attack I'm thinking of:

  1. The user is on news.example/startPage.
  2. An iframe from thirdParty.example on news.example/startPage is loaded.
  3. The iframe Fetches a cross-site resource from an origin under their control thirdPartyOther.example/cookie-sync-1. This sets the partitioned cookie for thirdPartyOther.example, and renders it accessible to the frame's Javascript.
  4. The iframe gets a tap and requests storage access.
  5. Storage access is granted with a user prompt.
  6. The iframe on thirdParty.example POSTs their unpartitioned cookie string and partitioned cookie set in step 3 to a cross-site resource under their control thirdPartyOther.example/cookie-sync-2.
  7. On a subsequent page load on news.example, an iframe from thirdParty.example is loaded partitioned but fetches thirdPartyOther.example/cookie-sync-3, which can now respond with the unpartitioned cookie string that was POSTed with the same partitioned cookie from step 6.

I came up with this using partitioned cookies, but you can substitute Fetch request/response bodies and Storage where needed.

@johnwilander
Copy link

@johnwilander: We talked a bit about the privacy benefits of per-page access to unpartitioned cookies in the meeting- I wanted to follow up. You said that we shouldn't presume collaboration between first and third parties when setting our threat model, and I still agree.

However I don't think a third party requires collaboration to link their partitioned and unpartitioned storages permanently after a single grant. Here is the attack I'm thinking of:

  1. The user is on news.example/startPage.
  2. An iframe from thirdParty.example on news.example/startPage is loaded.
  3. The iframe Fetches a cross-site resource from an origin under their control thirdPartyOther.example/cookie-sync-1. This sets the partitioned cookie for thirdPartyOther.example, and renders it accessible to the frame's Javascript.
  4. The iframe gets a tap and requests storage access.
  5. Storage access is granted with a user prompt.
  6. The iframe on thirdParty.example POSTs their unpartitioned cookie string and partitioned cookie set in step 3 to a cross-site resource under their control thirdPartyOther.example/cookie-sync-2.
  7. On a subsequent page load on news.example, an iframe from thirdParty.example is loaded partitioned but fetches thirdPartyOther.example/cookie-sync-3, which can now respond with the unpartitioned cookie string that was POSTed with the same partitioned cookie from step 6.

I came up with this using partitioned cookies, but you can substitute Fetch request/response bodies and Storage where needed.

Yup, syncing partitioned storage with unpartitioned storage is a threat indeed. That’s in part why WebKit makes all partitioned storage ephemeral which at least limits it to per-session. But I agree it points towards this response header opt-in not worsening things. I’ll have to think about it some more.

@cfredric
Copy link
Author

Thanks Ben, that's a good illustration that the header doesn't regress any existing privacy properties.

IMO browsers should assume that the embedded site knows its unpartitioned state once permission has been granted, whether document.requestStorageAccess() is called again (with or without user activation) or not.

@martinthomson martinthomson removed the agenda+ Request to add this issue to the agenda of our next telcon or F2F label Jan 4, 2024
@martinthomson
Copy link

@cfredric, I just untagged this, but I don't know if we reached a satisfactory conclusion when it was last discussed. Do you want to talk about this again at our upcoming call?

@cfredric
Copy link
Author

cfredric commented Jan 8, 2024

Thanks Martin, we'd love for chairs to consider accepting this proposal as a Privacy CG work item. Would you suggest another discussion on a call for that or do you think the multi-stakeholder interest and discussion in this thread is sufficient?

@johannhof johannhof added the interest: blink Implementer interest from Blink (e.g. Brave, Google/Chrome, Microsoft/Edge) label Jun 24, 2024
@johannhof
Copy link
Member

@martinthomson @bvandersloot-mozilla friendly ping on this question. We're implementing this and would like to start requesting feedback / positions, so we'll need a group to incubate in. Would be good to understand if that's PCG, which would be our preference, or whether it needs to be another group.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
interest: blink Implementer interest from Blink (e.g. Brave, Google/Chrome, Microsoft/Edge)
5 participants