WebKit Bugzilla
New
Browse
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
RESOLVED WONTFIX
110880
Cross-origin XSLT requests with CORS should be allowed
https://bugs.webkit.org/show_bug.cgi?id=110880
Summary
Cross-origin XSLT requests with CORS should be allowed
Raphael Kubo da Costa (:rakuco)
Reported
2013-02-26 07:31:19 PST
These days, if one attempts to load an XSLT resource from a different origin (as described in <
http://www.w3.org/wiki/CORS#xml-stylesheet_processing_instruction_.28XMLSS.29
>), the request fails because the origins do not match. Revisions
r34719
and
r38065
seem to implement the current behavior, but they reference bugs I do not have permission to view.
r34719
's commit message said it made WebKit match Firefox, IE and Opera at the time. These days, loading cross-origin XSLT resources works fine on IE and Firefox (and Opera simply ignored the request). Before spending some time trying to "fix" the issue, I'd like to know if there's an issue to be fixed at all or if we're happy with the current behavior. FWIW, there's a Chromium bug which references this same issue, <
https://code.google.com/p/chromium/issues/detail?id=101152
>.
Attachments
First attempt
(30.24 KB, patch)
2013-03-05 08:56 PST
,
Raphael Kubo da Costa (:rakuco)
no flags
Details
Formatted Diff
Diff
First attempt, fix test
(30.96 KB, patch)
2013-03-06 09:30 PST
,
Raphael Kubo da Costa (:rakuco)
no flags
Details
Formatted Diff
Diff
Remove some leftover
(30.29 KB, patch)
2013-03-06 09:38 PST
,
Raphael Kubo da Costa (:rakuco)
no flags
Details
Formatted Diff
Diff
Do not touch SubresourceLoader
(30.84 KB, patch)
2013-03-14 14:43 PDT
,
Raphael Kubo da Costa (:rakuco)
no flags
Details
Formatted Diff
Diff
Show Obsolete
(3)
View All
Add attachment
proposed patch, testcase, etc.
Adam Barth
Comment 1
2013-02-26 10:05:21 PST
I've added you to the bugs in question. They're old enough that we can probably make them public. The short answer is that cross-origin XSLT can lead to XSS vulnerabilities.
Raphael Kubo da Costa (:rakuco)
Comment 2
2013-02-27 05:03:40 PST
Thanks. Only now have I noticed that I didn't explicitly mention I had CORS in mind, sorry about that. My actual question is what to do when
http://bar.baz/something.xml
sends a request to
http://foo.bar/resource.xsl
, which send back a proper Access-Control-Allow-Origin header; in this case, Gecko and IE load it, whereas we don't.
Adam Barth
Comment 3
2013-02-27 07:58:10 PST
Does the fetch happen with credentials? Typically we prefer that people use CORS in "anonymous" mode so they don't accidentally share cookie-authenticated data. For example, that's the default for the crossorigin attribute on <img>.
Adam Barth
Comment 4
2013-02-27 07:59:20 PST
The short answer is yes, though. We can use CORS to let web sites open into allowing this behavior. I'd have to look at the security issue again to remember exactly which resources need to supply CORS headers.
Raphael Kubo da Costa (:rakuco)
Comment 5
2013-02-27 09:22:28 PST
(In reply to
comment #3
)
> Does the fetch happen with credentials? Typically we prefer that people use CORS in "anonymous" mode so they don't accidentally share cookie-authenticated data. For example, that's the default for the crossorigin attribute on <img>.
Given that there's no equivalent to the crossorigin attribute for <?xml-stylesheet>, I think both Gecko and IE perform the request without credentials, but I can check that.
Raphael Kubo da Costa (:rakuco)
Comment 6
2013-02-28 07:39:55 PST
Firefox always seems to send its requests in anonymous mode. IE10, on the other hand, does not really seem to apply CORS' rules in the request: if Protected Mode is disabled (or if only port numbers differ from what I could verify) cross-resource XSLT requests are performed and cookies are sent; the request fails and a warning is written on the console otherwise.
Raphael Kubo da Costa (:rakuco)
Comment 7
2013-02-28 07:59:45 PST
Actually, testing a bit more, Protected Mode does not alter IE10's behavior: in this case, whether it performs the cross-origin request or not depends on the "Access data sources across domains" setting. It does not take the CORS headers into account in any case, though.
Adam Barth
Comment 8
2013-02-28 11:43:09 PST
Doing anonymous requests is probably better so that folks can use Access-Control-Allow-Origin: *
Raphael Kubo da Costa (:rakuco)
Comment 9
2013-03-04 15:40:43 PST
(In reply to
comment #8
)
> Doing anonymous requests is probably better so that folks can use Access-Control-Allow-Origin: *
I'm currently having some trouble with redirects; namely, the ResourceRequest used when requesting a CachedXSLResource is not the one used when the network backend reports a redirect to the loader. This means that even if I, say, write some code in SubresourceLoader::willSendRequest to call updateRequestForAccessControl() the ResourceRequest that I eventually use in ProcessingInstruction::setXSLStyleSheet() has not been changed, and calling something like passesAccessControlCheck() may fail. Is this really intentional and I'm missing something obvious? Is one really supposed to change both CachedResourceLoader and something like SubresourceLoader to treat both original requests and redirects (I had thought both went through a similar code path)?
Raphael Kubo da Costa (:rakuco)
Comment 10
2013-03-05 08:56:55 PST
Created
attachment 191504
[details]
First attempt
Raphael Kubo da Costa (:rakuco)
Comment 11
2013-03-05 08:59:07 PST
Comment on
attachment 191504
[details]
First attempt There are a few things I don't like in this patch very much: for one, passing a ResourceResponse in setXSLStyleSheet feels weird. Also, performing almost the same origin checks in 3 different places makes me feel I'm doing something wrong.
WebKit Review Bot
Comment 12
2013-03-05 09:54:32 PST
Comment on
attachment 191504
[details]
First attempt
Attachment 191504
[details]
did not pass chromium-ews (chromium-xvfb): Output:
http://webkit-commit-queue.appspot.com/results/17015011
New failing tests: http/tests/security/cross-origin-xsl-BLOCKED.html
Build Bot
Comment 13
2013-03-05 15:53:34 PST
Comment on
attachment 191504
[details]
First attempt
Attachment 191504
[details]
did not pass mac-wk2-ews (mac-wk2): Output:
http://webkit-commit-queue.appspot.com/results/17044024
New failing tests: http/tests/security/cross-origin-xsl-BLOCKED.html
Raphael Kubo da Costa (:rakuco)
Comment 14
2013-03-06 09:30:18 PST
Created
attachment 191768
[details]
First attempt, fix test
Raphael Kubo da Costa (:rakuco)
Comment 15
2013-03-06 09:38:59 PST
Created
attachment 191771
[details]
Remove some leftover
Alexey Proskuryakov
Comment 16
2013-03-06 10:15:14 PST
Comment on
attachment 191771
[details]
Remove some leftover View in context:
https://bugs.webkit.org/attachment.cgi?id=191771&action=review
> Source/WebCore/loader/SubresourceLoader.cpp:147 > + if (m_resource->type() == CachedResource::XSLStyleSheet && !m_documentLoader->document()->securityOrigin()->canRequest(newRequest.url())) > + updateRequestForAccessControl(newRequest, m_documentLoader->document()->securityOrigin(), DoNotAllowStoredCredentials); > m_resource->willSendRequest(newRequest, redirectResponse);
Is this the right place to make this check? It seems like the line below should get us inside CachedXSLStyleSheet, which would be better for XSLStyleSheet specific code than SubresourceLoader. Additionally, this handling of redirects seems unique - I don't see any similar updateRequestForAccessControl calls elsewhere.
Raphael Kubo da Costa (:rakuco)
Comment 17
2013-03-06 11:41:46 PST
Comment on
attachment 191771
[details]
Remove some leftover View in context:
https://bugs.webkit.org/attachment.cgi?id=191771&action=review
>> Source/WebCore/loader/SubresourceLoader.cpp:147 >> m_resource->willSendRequest(newRequest, redirectResponse); > > Is this the right place to make this check? It seems like the line below should get us inside CachedXSLStyleSheet, which would be better for XSLStyleSheet specific code than SubresourceLoader. > > Additionally, this handling of redirects seems unique - I don't see any similar updateRequestForAccessControl calls elsewhere.
I thought about putting it in CachedXSLStyleSheet too. This would probably mean adding some empty method to CachedResource that's only implemented by CachedXSLStyleSheet. Is that OK? WRT this looking unique: other places, such as <img> + <canvas>, or XHR, provide means for users to specify the behavior their want. XSL was a special case before by simply discarding cross-origin requests. Were you thinking of something in specific?
Alexey Proskuryakov
Comment 18
2013-03-06 11:57:31 PST
> This would probably mean adding some empty method to CachedResource that's only implemented by CachedXSLStyleSheet.
Wouldn't CachedXSLStyleSheet::willSendRequest() work?
> other places, such as <img> + <canvas>, or XHR, provide means for users to specify the behavior their want
What is the place where other loaders do the equivalent of updateRequestForAccessControl() on redirect? Or do they not need to?
Raphael Kubo da Costa (:rakuco)
Comment 19
2013-03-06 12:10:20 PST
(In reply to
comment #18
)
> > This would probably mean adding some empty method to CachedResource that's only implemented by CachedXSLStyleSheet. > > Wouldn't CachedXSLStyleSheet::willSendRequest() work?
This would mean either passing m_documentLoader->securityOrigin() to willSendRequest() or calling loader()->documentLoader()->securityOrigin() there. I was a bit afraid of this chain not always being non-NULL, but can give it a try.
> > other places, such as <img> + <canvas>, or XHR, provide means for users to specify the behavior their want > > What is the place where other loaders do the equivalent of updateRequestForAccessControl() on redirect? Or do they not need to?
From what I understood from the behavior of <img>+<canvas> and XHR, at creation time (respectively, by setting the crossorigin attribute in <img> and using XHR.withCredentials) one defines whether all requests should be made without any credentials (which means the original request and any occasional ones created by redirects) are sent without credentials or all of them are sent with credentials.
Adam Barth
Comment 20
2013-03-06 14:53:48 PST
Comment on
attachment 191771
[details]
Remove some leftover View in context:
https://bugs.webkit.org/attachment.cgi?id=191771&action=review
This looks like a good start. My main question is why XSLT needs special handling in subresource loader.
>>> Source/WebCore/loader/SubresourceLoader.cpp:147 >>> + if (m_resource->type() == CachedResource::XSLStyleSheet && !m_documentLoader->document()->securityOrigin()->canRequest(newRequest.url())) >>> + updateRequestForAccessControl(newRequest, m_documentLoader->document()->securityOrigin(), DoNotAllowStoredCredentials); >>> m_resource->willSendRequest(newRequest, redirectResponse); >> >> Is this the right place to make this check? It seems like the line below should get us inside CachedXSLStyleSheet, which would be better for XSLStyleSheet specific code than SubresourceLoader. >> >> Additionally, this handling of redirects seems unique - I don't see any similar updateRequestForAccessControl calls elsewhere. > > I thought about putting it in CachedXSLStyleSheet too. This would probably mean adding some empty method to CachedResource that's only implemented by CachedXSLStyleSheet. Is that OK? > > WRT this looking unique: other places, such as <img> + <canvas>, or XHR, provide means for users to specify the behavior their want. XSL was a special case before by simply discarding cross-origin requests. Were you thinking of something in specific?
Why is this check needed for XSLStyleSheet but not for CORS-enabled image fetches?
> Source/WebCore/loader/cache/CachedResourceLoader.cpp:238 > + KURL requestURL = request.resourceRequest().url(); > + bool sameOriginRequest = m_document->securityOrigin()->canRequest(requestURL); > + > + if (!sameOriginRequest) > + updateRequestForAccessControl(request.mutableResourceRequest(), m_document->securityOrigin(), DoNotAllowStoredCredentials);
So, we're only doing an anonymous fetch if the initial URL is cross-origin. We need to be sure to test the case where a same-origin request gets redirected to a cross-origin URL
> LayoutTests/http/tests/security/cross-origin-xsl-BLOCKED-expected.txt:1 > -CONSOLE MESSAGE: line 2: Unsafe attempt to load URL
http://localhost:8000/security/resources/forbidden-stylesheet.xsl
from frame with URL
http://127.0.0.1:8000/security/resources/cross-origin-xsl.xml
. Domains, protocols and ports must match. > +CONSOLE MESSAGE: Unsafe attempt to load URL
http://localhost:8000/security/resources/forbidden-stylesheet.xsl
from frame with URL
http://127.0.0.1:8000/security/resources/cross-origin-xsl-BLOCKED.xml
. Domains, protocols and ports must match.
Why are we losing the line number?
Raphael Kubo da Costa (:rakuco)
Comment 21
2013-03-11 13:39:11 PDT
Sorry for the delay, I was flying across continents. (In reply to
comment #20
)
> This looks like a good start. My main question is why XSLT needs special handling in subresource loader.
As I see it XSL fetches behave differently than the rest because we're sort of adapting the behavior of something that does not really know about CORS, that is, in this case there's no "crossorigin" tag as there is for the <img> tag.
> > Source/WebCore/loader/cache/CachedResourceLoader.cpp:238 > > + KURL requestURL = request.resourceRequest().url(); > > + bool sameOriginRequest = m_document->securityOrigin()->canRequest(requestURL); > > + > > + if (!sameOriginRequest) > > + updateRequestForAccessControl(request.mutableResourceRequest(), m_document->securityOrigin(), DoNotAllowStoredCredentials);
>
> So, we're only doing an anonymous fetch if the initial URL is cross-origin. We need to be sure to test the case where a same-origin request gets redirected to a cross-origin URL
This is what http/tests/security/cross-origin-xsl-redirect.html is testing, and why I had to add code to SubresourceLoader: when the original request is a same-origin one, updateRequestForAccessControl() is not called. The platform-specific networking code then processes the redirect, creates a ResourceRequest based on the existing one and calls SubresourceLoader. The test I added there checks if this is happening and strips the request accordingly.
> >>> Source/WebCore/loader/SubresourceLoader.cpp:147 > >>> + if (m_resource->type() == CachedResource::XSLStyleSheet && !m_documentLoader->document()->securityOrigin()->canRequest(newRequest.url())) > >>> + updateRequestForAccessControl(newRequest, m_documentLoader->document()->securityOrigin(), DoNotAllowStoredCredentials); > >>> m_resource->willSendRequest(newRequest, redirectResponse);
>
> [...]
>
> Why is this check needed for XSLStyleSheet but not for CORS-enabled image fetches?
The CORS policy for image fetches is defined by the "crossorigin" attribute in <img>. Specifically, if crossorigin is "anonymous" the original request is already stripped so the RequestResource created after the redirect does not allow cookies either. Analogously, if crossorigin is set to "use-credentials" none of the requests have the omit credentials flag set.
> > LayoutTests/http/tests/security/cross-origin-xsl-BLOCKED-expected.txt:1 > > -CONSOLE MESSAGE: line 2: Unsafe attempt to load URL
http://localhost:8000/security/resources/forbidden-stylesheet.xsl
from frame with URL
http://127.0.0.1:8000/security/resources/cross-origin-xsl.xml
. Domains, protocols and ports must match. > > +CONSOLE MESSAGE: Unsafe attempt to load URL
http://localhost:8000/security/resources/forbidden-stylesheet.xsl
from frame with URL
http://127.0.0.1:8000/security/resources/cross-origin-xsl-BLOCKED.xml
. Domains, protocols and ports must match.
>
> Why are we losing the line number?
The line was shown because the document was still being parsed when the loading stopped and the message was logged. As the code in CachedResourceLoader::canRequest() has been removed, the message is added after parsing finishes.
Raphael Kubo da Costa (:rakuco)
Comment 22
2013-03-14 14:43:11 PDT
Created
attachment 193186
[details]
Do not touch SubresourceLoader
Raphael Kubo da Costa (:rakuco)
Comment 23
2013-04-02 14:07:11 PDT
Ping?
Alexey Proskuryakov
Comment 24
2013-04-15 15:57:54 PDT
Comment on
attachment 193186
[details]
Do not touch SubresourceLoader View in context:
https://bugs.webkit.org/attachment.cgi?id=193186&action=review
> Source/WebCore/dom/ProcessingInstruction.cpp:244 > + if (!document()->securityOrigin()->canRequest(response.url()) > + && !passesAccessControlCheck(response, DoNotAllowStoredCredentials, document()->securityOrigin(), errorDescription)) {
It feels strange to see an access check here, this is not loading code. I think that this may be too late.
> Source/WebCore/loader/cache/CachedResourceLoader.cpp:238 > + if (!sameOriginRequest) > + updateRequestForAccessControl(request.mutableResourceRequest(), m_document->securityOrigin(), DoNotAllowStoredCredentials);
I think that this is insufficient to make the request anonymous. ResourceHandleClient should return false from shouldUseCredentialStorage() to prevent ResourceHandle from using credentials stored in Keychain.
Andreas Kling
Comment 25
2014-02-05 11:20:23 PST
Comment on
attachment 193186
[details]
Do not touch SubresourceLoader Clearing review flag on patches from before 2014. If this patch is still relevant, please reset the r? flag.
alexbuzzbee
Comment 26
2019-12-17 14:52:49 PST
This bug still appears to be unfixed, at least in current iOS WebKit.
Anne van Kesteren
Comment 27
2023-05-12 23:50:30 PDT
I don't think we should add support for this unless it's properly standardized. Only Gecko supports this at the moment after all.
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