Bug 112530 - [Shadow] offsetParent should never return nodes in user agent Shadow DOM to script
Summary: [Shadow] offsetParent should never return nodes in user agent Shadow DOM to s...
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: DOM (show other bugs)
Version: 528+ (Nightly build)
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: Dominic Cooney
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2013-03-17 21:01 PDT by Dominic Cooney
Modified: 2013-03-18 08:55 PDT (History)
8 users (show)

See Also:


Attachments
Patch (6.50 KB, patch)
2013-03-17 21:03 PDT, Dominic Cooney
no flags Details | Formatted Diff | Diff
Patch (6.55 KB, patch)
2013-03-18 00:13 PDT, Dominic Cooney
no flags Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Dominic Cooney 2013-03-17 21:01:00 PDT
There is a theoretical attack against user agent Shadow DOM where an attacker script uses offsetParent to grab a reference to a node in user agent Shadow DOM. This could be an information disclosure risk or could be used to induce a bad cast. The attack is theoretical, however to defend against this kind of attack, the offsetParent attribute should never return nodes in user agent Shadow DOM.

In future this handling point could be generalized to checking that offsetParent is in the same tree scope as the element being queried, which will be useful for 'non traversable' shadows.
Comment 1 Dominic Cooney 2013-03-17 21:03:26 PDT
Created attachment 193484 [details]
Patch
Comment 2 Elliott Sprehn 2013-03-17 21:16:46 PDT
Comment on attachment 193484 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=193484&action=review

> Source/WebCore/dom/Element.cpp:539
> +Element* Element::bindingsOffsetParent()

Could we just add an argument to offsetParent with enums like AllowUserAgentShadows and DisallowUserAgentShadows ? It's somewhat suspicious that platform code even uses offsetParent, I do see Blackberry and SpatialNavigation use it, but we have better methods for getting the absolute rect locations in the render tree. We should add a FIXME to eliminate all usage of offsetParent from C++ land.

> Source/WebCore/dom/Element.cpp:542
> +    if (!element)

This might be nicer with the bitfield check like:

if (!element || !element->isInShadowTree())
  return element;

return element->containingShadowRoot()->type() == ShadowRoot::UserAgentShadowRoot ? 0 : element;
Comment 3 Dominic Cooney 2013-03-18 00:13:25 PDT
Created attachment 193494 [details]
Patch
Comment 4 Dominic Cooney 2013-03-18 00:17:27 PDT
Comment on attachment 193494 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=193494&action=review

> Source/WebCore/dom/Element.cpp:542
> +    if (!element || !element->isInShadowTree())

Updated with different conditional structure suggested by esprehn.

Although this code is vertically shorter, I think this is less readable.

In particular, when non-traversable shadows are implemented, the original if-early return structure will have a neat diff. This will require the egg to first be unscrambled before it can be poached.

> Source/WebCore/dom/Element.h:307
> +    // FIXME: Replace uses of offsetParent in the platform with calls

I think a separate method is easier to understand than an enum parameter with a default value which flips the behavior of the method.

I agree that ultimately there should be simply one set of offset* methods used by the bindings. Reading RenderObject.h it isn't immediately clear what the equivalent method there is--absoluteBoundingBoxRectIgnoringTransforms?
Comment 5 Elliott Sprehn 2013-03-18 00:18:28 PDT
Comment on attachment 193494 [details]
Patch

LGTM.
Comment 6 WebKit Review Bot 2013-03-18 00:57:50 PDT
Comment on attachment 193494 [details]
Patch

Clearing flags on attachment: 193494

Committed r146037: <http://trac.webkit.org/changeset/146037>
Comment 7 WebKit Review Bot 2013-03-18 00:57:53 PDT
All reviewed patches have been landed.  Closing bug.
Comment 8 Elliott Sprehn 2013-03-18 08:55:18 PDT
(In reply to comment #4)
> (From update of attachment 193494 [details])
> View in context: https://bugs.webkit.org/attachment.cgi?id=193494&action=review
> 
> > Source/WebCore/dom/Element.cpp:542
> > +    if (!element || !element->isInShadowTree())
> 
> Updated with different conditional structure suggested by esprehn.
> 
> Although this code is vertically shorter, I think this is less readable.
> 
> In particular, when non-traversable shadows are implemented, the original if-early return structure will have a neat diff. This will require the egg to first be unscrambled before it can be poached.

You can go back to an if (element->containingShadowRoot()->type() == UserAgent) return 0; if you want. I meant it makes more sense to check isInShadowTree() in the first if and get rid of the extra null checks and locals. That's only one extra line as well.

> 
> > Source/WebCore/dom/Element.h:307
> > +    // FIXME: Replace uses of offsetParent in the platform with calls
> 
> I think a separate method is easier to understand than an enum parameter with a default value which flips the behavior of the method.
> 
> I agree that ultimately there should be simply one set of offset* methods used by the bindings. Reading RenderObject.h it isn't immediately clear what the equivalent method there is--absoluteBoundingBoxRectIgnoringTransforms?

Probably something like Element::getBoundingClientRect. I don't know why you'd want to ignore transforms.