You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[css-paint-api] CSS Paint API leaks browsing history #791
The Privacy considerations should be updated in my option to reflect the dangers of leaking browser history (at high rates). We have a paper that will be published next week at WOOT discussing this (my copy here). Chromium addressed this by disabling the API on link elements and their children.
Beyond the privacy impact warning, are you making any recommendations for changes to this API? It looks like your advice is instead focused on the underlying :visited styles which expose browsing history to the current page in the first place.
It definitely is! I think we should try to cover visited links under the SOP umbrella so that specs like this don't need to special case links or worry about history sniffing. This is a larger conversation that we need to have, though, and I'm guessing that may take a while.
Until this is done, I think recommending Chrome's approach is pretty reasonable. (Unfortunately, the Paint API exposes a higher bandwidth channel than the other things we looked at.) Alternatively, plugging the side channels (registerPaint throwing an exception and paintlet-width leak [pg 5]) to address the amplified attack may be reasonable (though other side channels may similarly exist so I'm less excited about this to be honest).
Ugh, nice attack. I don't see a reasonable way around this, and disabling the API on all <a> elements or their descendants is not a viable forward tactic.
We really need to finally handle this at the higher level, and censor :visited state entirely (not matching :visitedat all) unless the visited state is already observable to the page via a standard channel. I filed w3c/csswg-drafts#3012 to see if we can solve this in CSS properly.
I would think a reasonable way around this would be something like the following:
when a paint callback is invoked, record what it does (either (preferably) as a sequence of canvas drawing commands, or as a bitmap)
only invoke the paint callback again when it is invoked with a different set of dependent properties (exposing only unvisited styles in this set of properties) or a different size (which can't change as a result of visitedness)
That said, although the paper doesn't explicitly say so, I'm assuming the "Amplified attack" variant is also counting calls to the paint callback and only doing the registerPaint that marks the link as visited on the second call... if that's not the case then I don't actually understand how that attack is working.
That said, although the paper doesn't explicitly say so, I'm assuming the "Amplified attack" variant is also counting calls to the paint callback and only doing the registerPaint that marks the link as visited on the second call... if that's not the case then I don't actually understand how that attack is working.
Yes, that's correct. We use registerPaint to store persistent state across paint callback invocations.
On the first invocation of our paint callback, we do registerPaint('target_foo', P).
On the second invocation, we do registerPaint('target_foo', P) again, but this time it throws an exception since target_foo is already registered. We catch the exception and do registerPaint('target_foo_visited', P) in response.
either (preferably) as a sequence of canvas drawing commands
I worry that I could chain up a long series of canvas drawing commands from my paintlet, then use a timing attack to detect when the browser replays them.
Yeah, the timing channel revealing when repaints occur is always going to be there; we can't prevent expensive repaints in general. The "good" attack with Paint API just makes it more reliable, but anything that can cause painting to be computationally expensive will work.
Hi @deian, it's a small world. (I'm the implementor of the paint API in Servo.) FWIW I agree with the approach in the paper, of keeping a separate visited store per security domain. If we did it per-eTLD+1 then this would line up nicely with content processes.
Reacted by Deian Stefan, Craig Disselkoen and cybai
All right, I've added an entry to the Privacy Considerations summarizing the problem and linking here. @deian, can you confirm this resolves the issue for you?
(The larger issue of how to fix this is, of course, still unresolved.)
@tabatkins thanks! I think this is a completely reasonable take. I agree with your take on trying to solve this for real by getting at the root of the problem.
Activity
AmeliaBR commentedon Aug 10, 2018
@deian
Beyond the privacy impact warning, are you making any recommendations for changes to this API? It looks like your advice is instead focused on the underlying
:visitedstyles which expose browsing history to the current page in the first place.deian commentedon Aug 11, 2018
It definitely is! I think we should try to cover visited links under the SOP umbrella so that specs like this don't need to special case links or worry about history sniffing. This is a larger conversation that we need to have, though, and I'm guessing that may take a while.
Until this is done, I think recommending Chrome's approach is pretty reasonable. (Unfortunately, the Paint API exposes a higher bandwidth channel than the other things we looked at.) Alternatively, plugging the side channels (registerPaint throwing an exception and paintlet-width leak [pg 5]) to address the amplified attack may be reasonable (though other side channels may similarly exist so I'm less excited about this to be honest).
tabatkins commentedon Aug 12, 2018
Ugh, nice attack. I don't see a reasonable way around this, and disabling the API on all
<a>elements or their descendants is not a viable forward tactic.We really need to finally handle this at the higher level, and censor :visited state entirely (not matching
:visitedat all) unless the visited state is already observable to the page via a standard channel. I filed w3c/csswg-drafts#3012 to see if we can solve this in CSS properly.dbaron commentedon Aug 13, 2018
I would think a reasonable way around this would be something like the following:
That said, although the paper doesn't explicitly say so, I'm assuming the "Amplified attack" variant is also counting calls to the paint callback and only doing the
registerPaintthat marks the link as visited on the second call... if that's not the case then I don't actually understand how that attack is working.spinda commentedon Aug 13, 2018
@dbaron
Yes, that's correct. We use
registerPaintto store persistent state acrosspaintcallback invocations.On the first invocation of our
paintcallback, we doregisterPaint('target_foo', P).On the second invocation, we do
registerPaint('target_foo', P)again, but this time it throws an exception sincetarget_foois already registered. We catch the exception and doregisterPaint('target_foo_visited', P)in response.spinda commentedon Aug 13, 2018
With regard to
I worry that I could chain up a long series of canvas drawing commands from my paintlet, then use a timing attack to detect when the browser replays them.
tabatkins commentedon Aug 13, 2018
Yeah, the timing channel revealing when repaints occur is always going to be there; we can't prevent expensive repaints in general. The "good" attack with Paint API just makes it more reliable, but anything that can cause painting to be computationally expensive will work.
asajeffrey commentedon Aug 13, 2018
Hi @deian, it's a small world. (I'm the implementor of the paint API in Servo.) FWIW I agree with the approach in the paper, of keeping a separate visited store per security domain. If we did it per-eTLD+1 then this would line up nicely with content processes.
tabatkins commentedon Oct 25, 2019
All right, I've added an entry to the Privacy Considerations summarizing the problem and linking here. @deian, can you confirm this resolves the issue for you?
(The larger issue of how to fix this is, of course, still unresolved.)
deian commentedon Oct 25, 2019
@tabatkins thanks! I think this is a completely reasonable take. I agree with your take on trying to solve this for real by getting at the root of the problem.
[css-paint-api] Add a Privacy Consideration about Paint API being a h…