-
Notifications
You must be signed in to change notification settings - Fork 301
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Trusted Types integration #789
Comments
I've found another approach to integrate the content attribute checks into the lower-level algorithms - namely into these attribute algorithms:
Similar to attribute change steps, define attribute validate steps in Element In append add optional parameter valueToValidate. In change, append and replace (optionally, also in remove, but that's not needed for TT strictly),
The attribute validate steps would be defined in other specs (e.g. HTML or CSP), and would define the behavior for sensitive attributes+element pairs. The behavior would be a thin wrapper around Get Trusted Types compliant string. The result would be that as long as we're dealing with values (e.g. Update: This needs some carve out for parser's create an element for token, which calls append. This approach solves the bypass via attribute nodes, and also fixes w3c/trusted-types#229. |
A proof-of concept integration for guarding attribute nodes is in w3c/trusted-types#233. Preview (Firefox only): |
Referring to the proposal of having a slot for URLs and text in a script element (to avoid patching DOM mutation algos), that we discussed offline, I took a look at this, and there's a small set of remaining attribute sinks (inline event handlers + svg scripts + object/embed attrs + srcdoc). These would likely need to get the same treatment, but at least the number of them is manageable. I'll look into it. |
…#3052 As proposed by @annevk, add slots for script URL / text, populate them when calling sink functions, and verify them when a script is prepared, optionally running a default policy on a value read from the DOM if it's different than the slot value. It avoids integration points with DOM mutation algorithms, but we still need to support script.setAttribute('src').
Alternate take on this, using the slot values for scripts. w3c/trusted-types#236 With this approach, Integration points with DOM disappeared (while the HTML integration gets a bit more involved). One issue remains in that I think it makes sense for |
It makes more sense to me if types always go through IDL attributes and content attributes remain strings forever. |
I'm concerned mostly about the migration path for existing codebases that
are based on writing content attributes. It's not just a simple replacement
from using element attributes to its properties.
The attrs do not need to store custom type values, we might only make
setAttribute not stringify the 2nd argument (+its namespaced version),
which could be picked up by change steps defined in HTML / csp.
I already noticed that attribute change steps in HTML return early in https://html.spec.whatwg.org/#event-handler-attributes, before
attr value is set in https://dom.spec.whatwg.org/#concept-element-attributes-change) when CSP blocks event handlers. Perhaps this logic
could be used in the same way. The only new part would then be just the
signature of `setAttribute` function.
Edit: Fix typos, added links.
|
Those steps returning early does not imply that the calling algorithm returns early too. Or is that not what you meant? |
I see. Yes, you're right. The value is actually set, it's just that the event object is not created, but the actual content attribute value is set in DOM spec later. This behavior is a bit similar to what we'd want for TT (fill the right slots based on the value type). So we could define the slots for trusted values in the appropriate elements in HTML (set directly from IDL attributes). I would argue that we should support |
I realize this might be hard to answer in the abstract, but in what cases is replacing a |
For example: one only creates the value once, and may use it in various sinks; so TT might only require to change the code that produces the value (say, a function that generates the URLs for dynamic script loads), and not all the places where this data ends up in the DOM. I can also imagine some situations where there is a difference in behavior between |
The migration would be simpler, but making |
To clarify: are you worried about the call to We are proposing the way to query the DOM to see what type is expected for the attribute, to reduce the surprise effect. |
Throwing is weird (but probably okay for non-strings). It's more the conceptual change from a string->string map to something else. It's not as invasive as the abandoned tree mutation changes though and if we keep it to |
It would most likely throw for strings (expected a type, got a string, default policy doesn't exist or rejects). +1 for more opinions on the thread. Intitially was thinking roughly that where you're providing the value as a string, than it would make sense to accept a type too (so |
I was hoping to weigh in with the desired "more opinions", but I've ended up pretty confused. Would someone be able to summarize what the current question at hand is? In the meantime, here is my general position: I believe that I also appreciate the simplicity of the model of attributes being a string -> string map, and think that would be nice to keep. Although we have to recognize that in reality it's a list of If you combine these it seems like the simplest way to make it work is to normalize the trusted type object to a string as part of the setAttribute() call, which is part of the "TT-at-sinks" program. This could throw. That sounds like a good path to me. It's also reasonable to add a "trusted" or "came from a trusted type" boolean to the |
Roughly summarizing - when we move the trusted values to slots in elements, and use them instead of content attributes when JS code execution might happen, we need to decide what to do if the values were set using DOM APIs that set content attributes - i.e. how and if to use TT in Javascript APIs from the following list:
FWIW, Chrome's implementation that added TT support for const s = document.createElement('script');
s.attributes.setNamedItem(someSrcAttr); succeded, but did not set a slot value, such that TT check would be done in prepare a script later, calling a default policy and likely bailing out. |
…#3052 As proposed by @annevk, add slots for script URL / text, populate them when calling sink functions, and verify them when a script is prepared, optionally running a default policy on a value read from the DOM if it's different than the slot value. It avoids integration points with DOM mutation algorithms, but we still need to support script.setAttribute('src').
* Alternate take for script enforcement. whatwg/dom#789 and whatwg/html#3052 As proposed by @annevk, add slots for script URL / text, populate them when calling sink functions, and verify them when a script is prepared, optionally running a default policy on a value read from the DOM if it's different than the slot value. It avoids integration points with DOM mutation algorithms, but we still need to support script.setAttribute('src'). * Fix reviewer's comments. * Adding a note to DOM issue.
@domenic I think to some extent you also need to consider |
We discussed the |
Yeah, #805 will make this even easier. |
Allows for integrating with Trusted Types - see whatwg#789.
Allows for integrating with Trusted Types - see whatwg#789. Contains whatwg#805.
Draft integration in #809. |
Allows for integrating with Trusted Types - see whatwg#789. Contains whatwg#805.
call from DOM. whatwg/dom#789 Closes w3c#401.
call from DOM. whatwg/dom#789 Closes w3c#401.
call from DOM. whatwg/dom#789 Closes w3c#401.
call from DOM. whatwg/dom#789 Closes w3c#401.
See w3c/trusted-types#418 and whatwg#789. Supercedes PR whatwg#809.
call from DOM. whatwg/dom#789 Closes w3c#401.
Rewrote DOM integration, adding an expliting entry point algorithm to call from DOM. whatwg/dom#789 Closes #401. Co-authored-by: Luke Warlow <[email protected]>
See w3c/trusted-types#418 and whatwg#789. Supercedes PR whatwg#809.
See w3c/trusted-types#418 and whatwg#789. Supercedes PR whatwg#809.
See w3c/trusted-types#418 and whatwg#789. Supercedes PR whatwg#809.
See w3c/trusted-types#418 and whatwg#789. Supercedes PR whatwg#809.
See w3c/trusted-types#418 and whatwg#789. Supercedes PR whatwg#809.
We've outlined what we think would be the HTML integration points needed for Trusted Types. This accompanies HTML#3052 describing the integration with HTML.
Approaches
The current draft spec implements the TT checks at the DOM sinks (JS functions) layer, and then discards the type information, such that TT become invisible to most other Web APIs and algorithms. The upside is that TT are simpler to spec & implement, the downside is that the future sinks might be introduced that skip the TT logic, and re-introduce DOM XSS-proneness. Or that we might have missed some existing algorithms that would bypass TT already. There's also a few of bypasses that require some additional custom protections (e.g. this). Let's call that tt-at-sinks approach.
@annevk proposed an alternative approach - to keep the type information intact such that it can be verified by the algorithms running later on (e.g. when script is to be prepared, check that its URL was a
TrustedScriptURL
. Let's call that tt-at-primitives approach.TT-at-sinks
Add text node validation steps to the insert algorithm.
Note: Perhaps this needs to be changed - the checks might be problematic in step 7 of node insert as they can partially fail, and then step 8 doesn't run. Perhaps hook after insertion but pre execution.
Changes to
Element.setAttribute*
. That's to add TT checks for IDL attributes that reflect content attributes with those checks. Currently only explained as a note. This needs some work, but in general the approach is to perform the checks (via relevant global object) that ascertain that TT type checks are performedbased, determining the right type for (context object, qualified name) pair. These callouts may be added to set an attribute value algorithm.Changes to set an attribute. Callout to TT when the (element, attr qualified name) needs types (e.g. for
iframe.srcdoc
). The TT checks will attempt to call the default policy on the attribute value, and might abort the algorithm, or change the attr value.Changes to
Attr
value setter; do the TT checks when setting a value of the attribute on an element, if (element + attr name) pair requires TT checks. Callout to TT checks can be implemented either in set an existing attribute value, or in change an attribute from an element algorithm. The latter might make the changes to set an attribute above unneccessary.TT-at-primitives
The changes required in DOM for this approach would be:
Add type metadata to Attr and Text nodes. (e.g. allow them to store string or TrustedType).
Change the signatures of
Element.setAttribute*
and other affected DOM APIs to also accept a typed value.Change Attr value getter to stringify the output; also in https://dom.spec.whatwg.org/#concept-element-attributes-get-value (or perhaps introduce a don't stringify argument?)
Changes to attribute-related algorithms, similar to ones outlined in TT-at-sinks section. Instead of callouts to TT checks, these would likely assert that a value is of an expected type.
The text was updated successfully, but these errors were encountered: