Open shhnjk opened 2 years ago
I've used Jun's example to show how a developer might update their XMLHttpRequest to stop using .innerHTML
(correctly rejected by TrustedTypes), and then naively update it to use responseType = "document"
, and .appendChild()
.
Even without responseType
set to document
, you can still bypass Trusted Types with XHR, by abusing responseXML
:
<!DOCTYPE html>
<meta charset="UTF-8">
<meta http-equiv="Content-Security-Policy" content="require-trusted-types-for 'script'; trusted-types 'none';">
<script>
const xhr = new XMLHttpRequest();
xhr.open("get", "data:text/xml,<x xmlns='http://www.w3.org/1999/xhtml'><img src='' onerror='alert(1)' /></x>")
xhr.send();
xhr.onload = ev => {
document.body.append(xhr.responseXML.firstChild);
}
</script>
Both these vectors require fetching new (same-origin, local scheme) documents and inserting nodes from there. I suspect they would be less probable to legitimately (authors are not malicious in TT threat model) exist in code than navigation-based vectors (e.g. create a same-origin iframe, clone nodes off that).
We already explicitly call out https://w3c.github.io/trusted-types/dist/spec/#cross-document-vectors as remaining security considerations, and the complimentary security controls mentioned there (e.g. script-src
CSP) would also work for these cases. I wonder whether the best course of action would not be to recognize such vectors in security considerations.
The alternative that follows the TT approach would be to require TrustedDocumentURL
or equivalent in fetch-related functions, which seems quite unergonomic for the authors for no good enough benefit. Fetch is probably as popular as navigations, and we made the error in the past of trying to control navigation sinks via TT, and had to backtrack with TrustedURL
deprecation.
For authors that pass dynamic values to XHMLHttpRequest.open
and then copy the resulting nodes to the main document CSP (either connect-src
or script-src
) seems like a much more practical advice than pure TT and rewriting all their fetch API usage.
Aren't we also considering blocking XSLT? That's also cross-document, no? We should at least be consistent.
And blocking XHR doesn't seem like the end of the world. fetch()
doesn't have a bulit-in parser for HTML/XML and won't get one.
Aren't we also considering blocking XSLT? That's also cross-document, no? We should at least be consistent.
Vectors from https://github.com/w3c/trusted-types/issues/359 would also be subject to CSP (it's unsafe-inline
, essentially), so there's always a trivial way of consistently saying "it's a cross-document vector" and not changing the sinks. I don't think we should just default to that without considering alternatives.
What might be the source of inconsistency is the way we handle the sinks for different known bypass vectors that deal with document objects.
From the ones we know about:
XSLTProcessor.importStylesheet
allows for bypassing parser entry points, We definitely cannot address 3. with TT being realm-scoped. I think we might explore blocking of XSLT functionality to stop https://github.com/w3c/trusted-types/issues/359 and https://github.com/w3c/trusted-types/issues/358, the challenge is to find the best entry point, and whether we need a "Level 2 TT" for that, since there are websites enforcing TT we should avoid breaking by enforcing on new sinks or blocking functionality.
blocking XHR doesn't seem like the end of the world.
I worry it might be quite taxing, at least for the current codebases. There probably is some telemetry, but quickly grepping GitHub gives 6.7M instances of innerHTML assignment and 2.4M of XHR usage. Needing to refactor such a common sink for little visible benefit is a a huge tax on developers adopting a security feature.
What might be more practical is blocking document responseType
and responseXML
, but given one can also take nodes off data:
iframe, I question the actual utility we'd be making with that.
After publishing the XHR vector, there was feedback asking to enforce Trusted Types on XHR document response.
Is it possible to change XMLHttpRequest (i.e. XHR) to the following?
XHR.open
to acceptstring
orTrustedScriptURL
in theurl
parameterXHR.responseType
is set todocument
, Trusted Types will check if theXHR.open
'surl
parameter wasstring
orTrustedScriptURL
. If it wasstring
, this will throw TT violation.WDYT?