Lessons from open-source: Use window.trustedTypes to prevent DOM XSS.
Tags: javascript, opensource, nextjs, react
Published: 2024-04-08 22:34:20

This lesson is picked from [Next.js source code](https://github.com/vercel/next.js/blob/canary/packages/next/src/client/trusted-types.ts#L14). In this article, you will learn what are window.trustedTypes.

![trusted-types](https://media.licdn.com/dms/image/D4E12AQHkRvEhA_Tgpg/article-inline_image-shrink_1000_1488/0/1712615137552?e=1718236800&v=beta&t=XmDgOSKdZAZVD5X6N4hW9sI7oR3zVHy2Bk4IeDESXWo)

I was looking at [client/trusted-types.ts](https://github.com/vercel/next.js/blob/canary/packages/next/src/client/trusted-types.ts#L14) and found window.trustedTypes?.createPolicy. At first, I thought trustedTypes must be an Object set some wherelse in the Next.js code base, but after a quick search across the codebase, I didn’t find any such declaration. I made the next obvious move — “Google it”

I found the following useful resources:

1.  [https://developer.mozilla.org/en-US/docs/Web/API/Trusted\_Types\_API](https://developer.mozilla.org/en-US/docs/Web/API/Trusted_Types_API)
2.  [https://web.dev/articles/trusted-types](https://web.dev/articles/trusted-types)
3.  [https://github.com/cure53/DOMPurify](https://github.com/cure53/DOMPurify)
4.  [https://www.npmjs.com/package/trusted-types](https://www.npmjs.com/package/trusted-types)

The following image shows the files that use TrustedTypes.

![usage of trusted-types](https://media.licdn.com/dms/image/D4E12AQFKVCtt8u4zdQ/article-inline_image-shrink_1500_2232/0/1712615138439?e=1718236800&v=beta&t=lOO2_EKQBYPMuBVxj1FciQVIO6xtuu8TnnxIFsrbWaY)

Carefully looking at client/router-loader.ts tells me that script urls are sanitised before they are used in functions such as [loadRoute](https://github.com/vercel/next.js/blob/f9ad49fc6f57f3bcf4f508b59deab695f06c74b1/packages/next/src/client/route-loader.ts#L377) and [prefetch](https://github.com/vercel/next.js/blob/f9ad49fc6f57f3bcf4f508b59deab695f06c74b1/packages/next/src/client/route-loader.ts#L423).

Here prefetch has a code snippet picked from [GoogleChromeLabs](https://github.com/GoogleChromeLabs/quicklink/blob/453a661fa1fa940e2d2e044452398e38c67a98fb/src/index.mjs#L115-L118) shown below:

```
// https://github.com/GoogleChromeLabs/quicklink/blob/453a661fa1fa940e2d2e044452398e38c67a98fb/src/index.mjs#L115-L118
// License: Apache 2.0
let cn
if ((cn = (navigator as any).connection)) {
  // Don't prefetch if using 2G or if Save-Data is enabled.
  if (cn.saveData || /2g/.test(cn.effectiveType)) return Promise.resolve()
}
```

Conclusion
----------

**“**If the sanitization logic in DOMPurify is buggy, your application might still have a DOM XSS vulnerability. Trusted Types force you to process a value _somehow_, but don’t yet define what the exact processing rules are, and whether they are safe.” — this caution from [web.dev](http://web.dev) makes me want to play around with TrustedTypes more and get a better understanding.

I found that Next.js source code uses Trusted types to sanitise the script urls before they are used in functions such as [loadRoute](https://github.com/vercel/next.js/blob/f9ad49fc6f57f3bcf4f508b59deab695f06c74b1/packages/next/src/client/route-loader.ts#L377) and [prefetch](https://github.com/vercel/next.js/blob/f9ad49fc6f57f3bcf4f508b59deab695f06c74b1/packages/next/src/client/route-loader.ts#L423).

I also discovered that if you are using any code snippets from open source that are Apache 2.0 licensed, make sure you provide the attribution. Found this from prefetch function as it uses a code snippet from Google Chrome Labs used to detect if the user is on 2G or if Save-Data is enabled. Sheesh! I need to attain this level of supporting edge cases.