Skip to content
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

feat(runtime-dom): a new __VUE_PROD_TRUSTED_TYPES__ flag for trusted types compatibility #10844

Open
wants to merge 11 commits into
base: main
Choose a base branch
from

Conversation

sodatea
Copy link
Member

@sodatea sodatea commented Apr 30, 2024

This PR introduces a new __VUE_PROD_TRUSTED_TYPES__ feature flag to enable support for Trusted Types. Addressing vuejs/rfcs#614.

For Trusted Types, I created a vue policy to convert the HTML string output from the Vue compiler to the TrustedHTML type.
This implementation works with the current enforcement of Google Workspace products without any issue.

In some rare circumstances, where the user explicitly configured allowed policy names and not allowing duplicates (Content-Security-Policy: trusted-types vue <their-custom-policy>; without a trailing allow-duplicates), a second version of Vue on the same web page would fail to create the built-in trusted types policy.
This may be solved by allowing users to customize the built-in policy name, but I don't think it's worth the complexity at this moment, considering the low adoption rate of this feature.

Note that the in-browser compiler doesn't benefit from this PR because it's already incompatible with many content security policies anyway.

Remaining todos:

This isn't a complete fix because `innerHTML` assignment also occurs
in `insertStaticContent`. But at least this makes the hello-world app
work with trusted types enabled.

I'm still figuring out how to add test cases for trusted types.

Remaining todos:
- [ ] Add test cases for trusted types.
- [ ] Fix `insertStaticContent` to be compatible with trusted types,
we may need a `vue` policy for that case.
- [ ] Add a note in the docs about trusted types compatibility.
- [ ] Allow trusted values to be passed to `v-html` and other props,
this ultimately fixes vuejs/rfcs#614
Copy link

github-actions bot commented Apr 30, 2024

Size Report

Bundles

File Size Gzip Brotli
runtime-dom.global.prod.js 90.8 kB (+87 B) 34.5 kB (+32 B) 31.1 kB (+31 B)
vue.global.prod.js 148 kB (+87 B) 53.7 kB (+43 B) 48.1 kB (+111 B)

Usages

Name Size Gzip Brotli
createApp 51.2 kB (+433 B) 20.1 kB (+227 B) 18.2 kB (+140 B)
createSSRApp 54.6 kB (+431 B) 21.4 kB (+229 B) 19.4 kB (+141 B)
defineCustomElement 53.5 kB (+431 B) 20.8 kB (+228 B) 18.9 kB (+156 B)
overall 64.8 kB (+326 B) 25 kB (+140 B) 22.7 kB (+132 B)

@yyx990803
Copy link
Member

replaceChildren seems to require browser support that is above ES2016 baseline.

…p mounting

Because `replaceChildren` isn't supported in all browsers, we still need
to use `innerHTML` to clear the container before mounting the app.

I left the compat mode implementation in `runtime-core` as is because it
doesn't feel right to use a DOM-only API in `runtime-core`.
It seems that the only source of the `content` is the output of
`stringifyStatic` in `compiler-dom`. I guess no additional check is
needed here.
Setting `textContent` to empty string is the equivalent of setting
`innerHTML` to empty string, but it doesn't trigger trusted types policy
violation.

Though maybe not as clear and performant as `trustedTypes.emptyHTML`,
the code is more succint considering that we don't need to check for the
existence of `trustedTypes` before using it.
@sodatea sodatea changed the title fix: ensure no trusted types violations on fresh mount fix: ensure no trusted types violations by default May 7, 2024
@sodatea sodatea changed the title fix: ensure no trusted types violations by default feat: ensure no trusted types violations by default May 8, 2024
@sodatea sodatea marked this pull request as ready for review May 8, 2024 07:56
@sodatea sodatea requested a review from yyx990803 May 8, 2024 07:56
@sodatea sodatea changed the title feat: ensure no trusted types violations by default feat: ensure no trusted types violations May 8, 2024
@sodatea sodatea changed the title feat: ensure no trusted types violations feat: ensure no trusted types violations when __VUE_PROD_TRUSTED_TYPES__ enabled May 8, 2024
@sodatea sodatea changed the title feat: ensure no trusted types violations when __VUE_PROD_TRUSTED_TYPES__ enabled feat(runtime-dom): a new __VUE_PROD_TRUSTED_TYPES__ flag for trusted types compatibility May 8, 2024
@lukewarlow
Copy link

Remaining todos:

Add a section in https://vuejs.org/guide/best-practices/security.html about trusted types compatibility, we can take https://angular.io/guide/security#enforcing-trusted-types as an example.

Am I correct in thinking this also could have a follow up to allow TrustedHTML objects to be passed to v-html? Or is that automatically handled?

@sodatea
Copy link
Member Author

sodatea commented May 8, 2024

Am I correct in thinking this also could have a follow up to allow TrustedHTML objects to be passed to v-html? Or is that automatically handled?

This is automatically handled as this test case shows: https://github.com/vuejs/core/pull/10844/files#diff-5329e45cfbe289d331762479cc76fe38b6657526dc2a9e2cd6f4729baa6b3e44R81-R102

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
ready for review This PR requires more reviews
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants