WebKit Bugzilla
New
Browse
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
RESOLVED FIXED
180301
A canvas should not be tainted if it draws a data URL SVGImage with a <foreignObject>
https://bugs.webkit.org/show_bug.cgi?id=180301
Summary
A canvas should not be tainted if it draws a data URL SVGImage with a <foreig...
Said Abou-Hallawa
Reported
2017-12-01 17:52:51 PST
After <
http://trac.webkit.org/changeset/195614
>, the canvas will tainted if it draws any SVGImage with a <foreignObject>. The reason for this is we do not want to SVGImages to leak cross-origin data (e.g., visited links, spellcheck). But if the sourceURL of the SVGImage is a data URL, then there should not be a cross-origin data leak. So we should not taint the canvas in this case. We need to relax the tainting check for data URL SVGImage.
Attachments
Patch
(4.71 KB, patch)
2017-12-01 17:54 PST
,
Said Abou-Hallawa
no flags
Details
Formatted Diff
Diff
Archive of layout-test-results from ews102 for mac-elcapitan
(2.46 MB, application/zip)
2017-12-01 18:44 PST
,
EWS Watchlist
no flags
Details
Patch
(4.72 KB, patch)
2017-12-01 18:46 PST
,
Said Abou-Hallawa
no flags
Details
Formatted Diff
Diff
Patch
(11.66 KB, patch)
2017-12-04 12:38 PST
,
Said Abou-Hallawa
no flags
Details
Formatted Diff
Diff
Patch
(11.91 KB, patch)
2017-12-04 12:47 PST
,
Said Abou-Hallawa
no flags
Details
Formatted Diff
Diff
Patch
(11.54 KB, patch)
2018-01-08 15:58 PST
,
Said Abou-Hallawa
no flags
Details
Formatted Diff
Diff
Show Obsolete
(5)
View All
Add attachment
proposed patch, testcase, etc.
Said Abou-Hallawa
Comment 1
2017-12-01 17:54:42 PST
Created
attachment 328199
[details]
Patch
Said Abou-Hallawa
Comment 2
2017-12-01 17:55:25 PST
<
rdar://problem/35319543
>
EWS Watchlist
Comment 3
2017-12-01 18:44:08 PST
Comment on
attachment 328199
[details]
Patch
Attachment 328199
[details]
did not pass mac-ews (mac): Output:
http://webkit-queues.webkit.org/results/5461862
New failing tests: svg/as-image/svg-canvas-data-url-svg-with-foreign-object-not-tainted.html
EWS Watchlist
Comment 4
2017-12-01 18:44:10 PST
Created
attachment 328204
[details]
Archive of layout-test-results from ews102 for mac-elcapitan The attached test failures were seen while running run-webkit-tests on the mac-ews. Bot: ews102 Port: mac-elcapitan Platform: Mac OS X 10.11.6
Said Abou-Hallawa
Comment 5
2017-12-01 18:46:02 PST
Created
attachment 328205
[details]
Patch
Darin Adler
Comment 6
2017-12-02 10:00:41 PST
Comment on
attachment 328205
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=328205&action=review
> Source/WebCore/html/canvas/CanvasRenderingContext.cpp:85 > + const URL url = image->sourceURL(); > + if (url.protocolIsData()) > + return false;
It seems strange to modify this function. Why wouldn't we want hasSingleSecurityOrigin to return true for an SVG image from a data URL? Are there other clients of that function that need to get false for that case? The const here is peculiar and not needed, nor is a local variable needed. If this check is correct, then I would write: if (image->sourceURL().protocolIsData()) return false;
Dean Jackson
Comment 7
2017-12-03 18:30:57 PST
What if the foreign object references cross origin content?
Said Abou-Hallawa
Comment 8
2017-12-04 12:38:15 PST
Created
attachment 328375
[details]
Patch
Said Abou-Hallawa
Comment 9
2017-12-04 12:47:20 PST
Created
attachment 328378
[details]
Patch
Said Abou-Hallawa
Comment 10
2017-12-04 13:19:47 PST
Comment on
attachment 328205
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=328205&action=review
>> Source/WebCore/html/canvas/CanvasRenderingContext.cpp:85 >> + return false; > > It seems strange to modify this function. Why wouldn't we want hasSingleSecurityOrigin to return true for an SVG image from a data URL? Are there other clients of that function that need to get false for that case? > > The const here is peculiar and not needed, nor is a local variable needed. If this check is correct, then I would write: > > if (image->sourceURL().protocolIsData()) > return false;
I think we can't modify SVGImage::hasSingleSecurityOrigin() to check for the data url source because SVGFEImageElement::hasSingleSecurityOrigin() calls Image::hasSingleSecurityOrigin(). Suppose we have the following HTML page: var svg = new Image(); svg.src = "url-to-an-svg-with-an-feimage-which-has-forigen-object.svg"; svg.onload = function() { ctx.drawImage(svg, 0, 0); } And we have the following url-to-an-svg-with-an-feimage-which-has-forigen-object.svg: <svg> <filter id="image"> <feImage xlink:href="data:image/svg+xml;..."/> </filter> <rect width="100" height="100" filter="url(#image)"/> </svg> And suppose we changed SVGImage::hasSingleSecurityOrigin() to look like this: bool SVGImage::hasSingleSecurityOrigin() { + if (sourceURL().protocolIsData()) + return true; ... } Then this svg will not taint the canvas regardless of it is content. In this case, of the following call stack will be executed: CanvasRenderingContext::wouldTaintOrigin() calls SVGImage::hasSingleSecurityOrigin() for the SVGImage "url-to-an-svg-with-an-feimage-which-has-forigen-object.svg". SVGImage::hasSingleSecurityOrigin() calls SVGFEImageElement::hasSingleSecurityOrigin() for the child <feimage>. SVGFEImageElement::hasSingleSecurityOrigin() calls SVGImage::hasSingleSecurityOrigin() for its data url image. SVGImage::hasSingleSecurityOrigin() will return true because if (sourceURL().protocolIsData()) will be true. And this wrong. But you are right about other places that need to do the same check. I searched the source code and I found out that taintsOrigin() in ImageBitmap.cpp needs a similar check and I fixed it the same way.
Said Abou-Hallawa
Comment 11
2017-12-04 13:35:55 PST
(In reply to Dean Jackson from
comment #7
)
> What if the foreign object references cross origin content?
I think that's fine. The data uri image are embedded in the page. The tags inside the SVG <foreignObject> should be treated the same way all other tags in the HTML page are treated. For example the text inside the <a> tag and the text which is drawn on the canvas should be treated the same way. <a href="
http://www.example.com/
">link</a> <canvas></canvas> <script> var data = "data:image/svg+xml;charset=utf-8," + '<svg xmlns="
http://www.w3.org/2000/svg
">' + ' <foreignObject width="100%" height="100%">' + ' <xhtml:a href="
http://www.example.com/
">link</xhtml:a>' + ' </foreignObject>' + '</svg>'; var svg = new Image(); svg.onload = function() { var canvas = document.querySelector('canvas'); var ctx = canvas.getContext('2d'); ctx.drawImage(svg, 0, 0); } svg.src = data; </script>
Dean Jackson
Comment 12
2018-01-08 15:07:08 PST
(In reply to Said Abou-Hallawa from
comment #10
)
> Comment on
attachment 328205
[details]
> > I think we can't modify SVGImage::hasSingleSecurityOrigin() to check for the > data url source because SVGFEImageElement::hasSingleSecurityOrigin() calls > Image::hasSingleSecurityOrigin(). > > Suppose we have the following HTML page: > > var svg = new Image(); > svg.src = "url-to-an-svg-with-an-feimage-which-has-forigen-object.svg"; > svg.onload = function() { > ctx.drawImage(svg, 0, 0); > } > > And we have the following > url-to-an-svg-with-an-feimage-which-has-forigen-object.svg: > > <svg> > <filter id="image"> > <feImage xlink:href="data:image/svg+xml;..."/> > </filter> > <rect width="100" height="100" filter="url(#image)"/> > </svg> > > And suppose we changed SVGImage::hasSingleSecurityOrigin() to look like this: > > bool SVGImage::hasSingleSecurityOrigin() > { > + if (sourceURL().protocolIsData()) > + return true; > ... > } > > Then this svg will not taint the canvas regardless of it is content. In this > case, of the following call stack will be executed: > > CanvasRenderingContext::wouldTaintOrigin() calls > SVGImage::hasSingleSecurityOrigin() for the SVGImage > "url-to-an-svg-with-an-feimage-which-has-forigen-object.svg". > SVGImage::hasSingleSecurityOrigin() calls > SVGFEImageElement::hasSingleSecurityOrigin() for the child <feimage>. > SVGFEImageElement::hasSingleSecurityOrigin() calls > SVGImage::hasSingleSecurityOrigin() for its data url image. > SVGImage::hasSingleSecurityOrigin() will return true because if > (sourceURL().protocolIsData()) will be true. > > And this wrong.
Sorry for being dumb, but what is wrong here? The image in the FEImage is an SVGImage, and it does have a single security origin right? (since it is a data URL) So the uppermost SVG, used to draw into the context, has a single security origin and should not taint the canvas?
Said Abou-Hallawa
Comment 13
2018-01-08 15:41:50 PST
(In reply to Dean Jackson from
comment #12
)
> (In reply to Said Abou-Hallawa from
comment #10
) > > Comment on
attachment 328205
[details]
> > > > I think we can't modify SVGImage::hasSingleSecurityOrigin() to check for the > > data url source because SVGFEImageElement::hasSingleSecurityOrigin() calls > > Image::hasSingleSecurityOrigin(). > > > > Suppose we have the following HTML page: > > > > var svg = new Image(); > > svg.src = "url-to-an-svg-with-an-feimage-which-has-forigen-object.svg"; > > svg.onload = function() { > > ctx.drawImage(svg, 0, 0); > > } > > > > And we have the following > > url-to-an-svg-with-an-feimage-which-has-forigen-object.svg: > > > > <svg> > > <filter id="image"> > > <feImage xlink:href="data:image/svg+xml;..."/> > > </filter> > > <rect width="100" height="100" filter="url(#image)"/> > > </svg> > > > > And suppose we changed SVGImage::hasSingleSecurityOrigin() to look like this: > > > > bool SVGImage::hasSingleSecurityOrigin() > > { > > + if (sourceURL().protocolIsData()) > > + return true; > > ... > > } > > > > Then this svg will not taint the canvas regardless of it is content. In this > > case, of the following call stack will be executed: > > > > CanvasRenderingContext::wouldTaintOrigin() calls > > SVGImage::hasSingleSecurityOrigin() for the SVGImage > > "url-to-an-svg-with-an-feimage-which-has-forigen-object.svg". > > SVGImage::hasSingleSecurityOrigin() calls > > SVGFEImageElement::hasSingleSecurityOrigin() for the child <feimage>. > > SVGFEImageElement::hasSingleSecurityOrigin() calls > > SVGImage::hasSingleSecurityOrigin() for its data url image. > > SVGImage::hasSingleSecurityOrigin() will return true because if > > (sourceURL().protocolIsData()) will be true. > > > > And this wrong. > > Sorry for being dumb, but what is wrong here? The image in the FEImage is an > SVGImage, and it does have a single security origin right? (since it is a > data URL) So the uppermost SVG, used to draw into the context, has a single > security origin and should not taint the canvas?
You are not "dumb" Dean :). It took me awhile to remember why I wrote this comment and I realized this area is very confusing. The html and the svg do not have the same security origin "if the svg includes foreign objects." See the for-loop in SVGImage::hasSingleSecurityOrigin() and <
http://trac.webkit.org/changeset/195614
>. See also the layout test LayoutTests/svg/as-image/svg-canvas-svg-with-feimage-with-link-tainted.html which looks very similar to what I described above. In fact this test case will fail if I implement Darin's suggestion. I think the fix is to check whether the uppermost SVG is a data uri or not. If it is then, we should not taint the canvas. Putting the check of protocolIsData() at the beginning of SVGImage::hasSingleSecurityOrigin() will bypass the check of the <foreignObject> even if the uppermost SVG is not a data uri.
Said Abou-Hallawa
Comment 14
2018-01-08 15:58:48 PST
Created
attachment 330750
[details]
Patch
Said Abou-Hallawa
Comment 15
2018-01-08 16:00:04 PST
(In reply to Said Abou-Hallawa from
comment #14
)
> Created
attachment 330750
[details]
> Patch
I re-uploaded the same patch to make sure it can still be applied to the trunk.
WebKit Commit Bot
Comment 16
2018-01-08 16:35:39 PST
Comment on
attachment 330750
[details]
Patch Clearing flags on attachment: 330750 Committed
r226599
: <
https://trac.webkit.org/changeset/226599
>
WebKit Commit Bot
Comment 17
2018-01-08 16:35:41 PST
All reviewed patches have been landed. Closing bug.
Note
You need to
log in
before you can comment on or make changes to this bug.
Top of Page
Format For Printing
XML
Clone This Bug