🌐 AI搜索 & 代理 主页
Skip to content

Conversation

@mgol
Copy link
Member

@mgol mgol commented Sep 9, 2021

Summary

This ensures HTML wrapped in TrustedHTML can be used as an input to jQuery
manipulation methods in a way that doesn't violate the
require-trusted-types-for Content Security Policy directive.
This commit builds on previous work needed for trusted types support, including
gh-4642 and gh-4724.

One restriction is that while any TrustedHTML wrapper should work as input
for jQuery methods like .html() or .append(), for passing directly to the
jQuery factory the string must start with < and end with >; no trailing
or leading whitespaces are allowed. This is necessary as we cannot parse out
a part of the input for further construction; that would violate the CSP rule -
and that's what's done to HTML input not matching these constraints.

No trusted types API is used explicitly in source; the majority of the work is
ensuring we don't pass the input converted to string to APIs that would
eventually assign it to innerHTML. This extra cautiousness is caused by the
API being Blink-only, at least for now.

The ban on passing strings to innerHTML means support tests relying on such
assignments are impossible. We don't currently have such tests on the main
branch but we used to have many of them in the 3.x & older lines. If there's
a need to re-add such a test, we'll need an escape hatch to skip them for apps
needing CSP-enforced TrustedHTML.

See https://web.dev/trusted-types/ for more information about TrustedHTML.

Fixes gh-4409
Ref gh-4642
Ref gh-4724

+30 bytes

Checklist

@mgol mgol added Manipulation Core Discuss in Meeting Reserved for Issues and PRs that anyone would like to discuss in the weekly meeting. labels Sep 9, 2021
@mgol mgol self-assigned this Sep 9, 2021
@mgol
Copy link
Member Author

mgol commented Sep 9, 2021

Travis fails due to #4926 which is unrelated.

}
} ),
inputs = [
[ "<div></div>", "<div class='test'></div>", [ "div" ] ],
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does it make sense to also add a test for TrustedHTMLs that wrap over a non-obvious HTML, e.g. just some text? From what I can tell, different branches are used then.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, good point. That will only apply to the second array items as the first ones are passed directly to jQuery which also supports selectors - and since for TrustedHTML we cannot carve out a part of an input string to later parse, I opted to restrict support for TrustedHTML-wrapped strings to ones that are start with < and end with > - i.e. what was already going through the fast path skipping the regex match.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, I assume that TrustedHTML wrapping something will just get stringified somewhere and be treated as a selector? That's OK, I don't think there would be expectations for jQuery to do anything else. I think it just makes sense to have an explicit test for that behavior.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@koto It would actually just create a jQuery wrapper with a single element being this TrustedHTML instance, i.e. it would treat it like any other non-DOM object. I just didn't handle it in any special way and let it go where it goes naturally in the current flow.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To be clear, this limitation only applies to (pseudo-code) jQuery(TrustedHTML('foo')); jQuery(document.body).append(TrustedHTML('foo')) should append the text foo just as without wrapping in TrustedHTML; I'll add a test for that.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, I forgot about https://api.jquery.com/jQuery/#jQuery-object behavior :) Yeah, that's fine, thanks for clarifying.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added one test case for text content. I haven't added one for the object wrapper as I'm not sure if we want this to be a part of the contract.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good!

@koto
Copy link

koto commented Sep 10, 2021

Looks great!

@mgol
Copy link
Member Author

mgol commented Sep 13, 2021

PR updated, we're down from +38 to +30 bytes.

@mgol mgol added this to the 4.0.0 milestone Sep 13, 2021
@mgol mgol marked this pull request as ready for review September 13, 2021 17:07
@linux-foundation-easycla
Copy link

linux-foundation-easycla bot commented Sep 14, 2021

CLA Signed

The committers are authorized under a signed CLA.

  • ✅ Michał Gołębiowski-Owczarek (57c62b4)

@timmywil timmywil removed the Discuss in Meeting Reserved for Issues and PRs that anyone would like to discuss in the weekly meeting. label Sep 20, 2021
This ensures HTML wrapped in TrustedHTML can be used as an input to jQuery
manipulation methods in a way that doesn't violate the
`require-trusted-types-for` Content Security Policy directive.
This commit builds on previous work needed for trusted types support, including
jquerygh-4642 and jquerygh-4724.

One restriction is that while any TrustedHTML wrapper should work as input
for jQuery methods like `.html()` or `.append()`, for passing directly to the
`jQuery` factory the string must start with `<` and end with `>`; no trailing
or leading whitespaces are allowed. This is necessary as we cannot parse out
a part of the input for further construction; that would violate the CSP rule -
and that's what's done to HTML input not matching these constraints.

No trusted types API is used explicitly in source; the majority of the work is
ensuring we don't pass the input converted to string to APIs that would
eventually assign it to `innerHTML`. This extra cautiousness is caused by the
API being Blink-only, at least for now.

The ban on passing strings to `innerHTML` means support tests relying on such
assignments are impossible. We don't currently have such tests on the `main`
branch but we used to have many of them in the 3.x & older lines. If there's
a need to re-add such a test, we'll need an escape hatch to skip them for apps
needing CSP-enforced TrustedHTML.

See https://web.dev/trusted-types/ for more information about TrustedHTML.

Fixes jquerygh-4409
Ref jquerygh-4642
Ref jquerygh-4724
@mgol
Copy link
Member Author

mgol commented Sep 29, 2021

@timmywil @koto I also added one small change in the tests (in the fixup commit) that makes the tests run even in browsers with no TrustedHTML support - there, it uses a simple object wrapper with a toString function returning the HTML string. It also shows that the changes in this PR are generic and would work with a number of similar APIs as well.

@mgol mgol removed the Needs review label Sep 30, 2021
@mgol mgol merged commit de5398a into jquery:main Sep 30, 2021
@mgol mgol deleted the trusted-html branch September 30, 2021 14:00
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Sep 25, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Development

Successfully merging this pull request may close these issues.

Have Trusted Types API built directly into the jQuery Core Files

3 participants