-
Notifications
You must be signed in to change notification settings - Fork 9.6k
new_audit: mitigate dom-based xss with trusted types #16493
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
Merged
Merged
Changes from 18 commits
Commits
Show all changes
39 commits
Select commit
Hold shift + click to select a range
2df023e
Add files to gitignore.
sebastian9er f95d133
Merge remote-tracking branch 'upstream/main'
sebastian9er e52e1b8
Merge branch 'GoogleChrome:main' into main
sebastian9er 3861727
Merge branch 'main' of https://github.com/sebastian9er/lighthouse
sebastian9er 8717e3c
Commit gitignore
sebastian9er 009af4e
Merge branch 'GoogleChrome:main' into main
sebastian9er b244376
Merge branch 'main' of https://github.com/sebastian9er/lighthouse
sebastian9er 47f4de5
Merge branch 'main' of https://github.com/sebastian9er/lighthouse
sebastian9er adadeca
Merge branch 'main' of https://github.com/sebastian9er/lighthouse
sebastian9er 3e41e00
Merge branch 'trusted-types' of https://github.com/sebastian9er/light…
sebastian9er f908dd6
Merge branch 'main' of https://github.com/sebastian9er/lighthouse
sebastian9er cc6c040
Initial version of the Trusted Types audit for Lighthouse.
sebastian9er ee508d7
Re-adding yarn.lock
sebastian9er da443d8
Fixing up yarn.lock (probably for the first time of many).
sebastian9er 9424b22
Fix up gitignore to stop complaining.
sebastian9er 491964a
Smokehouse tests for the trusted types Lighthouse audit.
sebastian9er e900a6b
Update docs for trusted types Lighthouse audit.
sebastian9er b08dd34
Merge branch 'GoogleChrome:main' into trusted-types
sebastian9er fe7e350
Fix date in copyright.
sebastian9er 979136c
Merge branch 'GoogleChrome:main' into trusted-types
sebastian9er 4a25028
Fix description, TODO link and include metadata for evaluation.
sebastian9er c42f57c
Update json files.
sebastian9er aef0048
Fix tests.
sebastian9er 8505587
Fix package.json to make PR workflows happy. Hopefully.
sebastian9er cee8d73
Merge branch 'main' into trusted-types
sebastian9er 5ce1dd8
Reverting changes to shared/localization/locales as requested in the PR.
sebastian9er 29ccd04
Fix gitignore and package.json
sebastian9er 8e477c1
Merge remote
sebastian9er 9610cbc
Fix sample flow and sample json
sebastian9er bfd2fb8
Merge branch 'main' into trusted-types
sebastian9er 77c5638
Clean checkout, fix yarn, fix lighthouse link and check in locales.
sebastian9er 70657a0
Lint fix
sebastian9er fff82a5
Adding yarn.lock back in.
sebastian9er 476cbc1
Fix sample flow file.
sebastian9er 5165f95
Fix UIStrings.
sebastian9er ff40967
Merge remote-tracking branch 'upstream/main'
sebastian9er 2923ce0
Merge branch 'main' into trusted-types
sebastian9er 4bc0ec8
Fix linter and update json.
sebastian9er aa94cfa
Add smokehouse-bin back in.
sebastian9er File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
27 changes: 27 additions & 0 deletions
27
cli/test/smokehouse/test-definitions/trusted-types-directive-present.js
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| /** | ||
| * @license | ||
| * Copyright 2025 Google LLC | ||
| * SPDX-License-Identifier: Apache-2.0 | ||
| */ | ||
|
|
||
| /** | ||
| * @type {Smokehouse.ExpectedRunnerResult} | ||
| * Expected Lighthouse results for a site with present DOM-XSS mitigations | ||
| * (through a Trusted-Types direcive in the Content-Security-Policy header). | ||
| */ | ||
| const expectations = { | ||
| lhr: { | ||
| requestedUrl: 'https://m.youtube.com/', | ||
| finalDisplayedUrl: 'https://m.youtube.com/', | ||
| audits: { | ||
| 'trusted-types-xss': { | ||
| score: null, | ||
| }, | ||
| }, | ||
| }, | ||
| }; | ||
|
|
||
| export default { | ||
| id: 'trusted-types-directive-present', | ||
| expectations, | ||
| }; |
36 changes: 36 additions & 0 deletions
36
cli/test/smokehouse/test-definitions/trusted-types-missing-directives.js
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| /** | ||
| * @license | ||
| * Copyright 2025 Google LLC | ||
| * SPDX-License-Identifier: Apache-2.0 | ||
| */ | ||
|
|
||
| /** | ||
| * @type {Smokehouse.ExpectedRunnerResult} | ||
| * Expected Lighthouse results for a site with missing DOM-XSS mitigations | ||
| * (through the lack of Trusted-Types direcives in the Content-Security-Policy | ||
| * headers). | ||
| */ | ||
| const expectations = { | ||
| lhr: { | ||
| requestedUrl: 'https://example.com/', | ||
| finalDisplayedUrl: 'https://example.com/', | ||
| audits: { | ||
| 'trusted-types-xss': { | ||
| score: 1, | ||
| details: { | ||
| items: [ | ||
| { | ||
| description: 'No Content-Security-Policy header with Trusted Types directive found', | ||
| severity: 'High', | ||
| }, | ||
| ], | ||
| }, | ||
| }, | ||
| }, | ||
| }, | ||
| }; | ||
|
|
||
| export default { | ||
| id: 'trusted-types-missing-directives', | ||
| expectations, | ||
| }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,122 @@ | ||
| /** | ||
| * @license | ||
| * Copyright 2025 Google LLC | ||
| * SPDX-License-Identifier: Apache-2.0 | ||
| */ | ||
|
|
||
| import {Audit} from './audit.js'; | ||
| import {MainResource} from '../computed/main-resource.js'; | ||
| import * as i18n from '../lib/i18n/i18n.js'; | ||
|
|
||
| const UIStrings = { | ||
| /** Title of a Lighthouse audit that evaluates whether the set CSP header and Trusted Types directive is mitigating DOM-based XSS. "CSP" stands for "Content-Security-Policy" and should not be translated. "XSS" stands for "Cross Site Scripting" and should not be translated. */ | ||
| title: 'Mitigate DOM-based XSS with Trusted Types', | ||
| /** Description of a Lighthouse audit that evaluates whether the set CSP header and Trusted Types directive is mitigating DOM-based XSS. This is displayed after a user expands the section to see more. "CSP" stands for "Content-Security-Policy" and should not be translated. "XSS" stands for "Cross Site Scripting" and should not be translated. No character length limits. The last sentence starting with 'Learn' becomes link text to additional documentation. */ | ||
| description: 'The `require-trusted-types-for` directive in the `Content-Security-Policy` (CSP) header instructs user agents to control the data passed to DOM XSS sink functions. [Learn more about mitigating DOM-based XSS](https://developer.chrome.com/docs/lighthouse/best-practices/TODO).', | ||
| /** Summary text for the results of a Lighthouse audit that evaluates whether the set CSP header and Trusted Types directive is mitigating DOM-based XSS. This text is displayed if the page does not respond with a CSP header and a Trusted Types directive. "CSP" stands for "Content-Security-Policy" and should not be translated. "XSS" stands for "Cross Site Scripting" and should not be translated. */ | ||
| noTrustedTypesToMitigateXss: 'No Content-Security-Policy header with Trusted Types directive found', | ||
sebastian9er marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| /** Label for a column in a data table; entries will be the severity of an issue with the page's CSP and Trusted Types directive. */ | ||
| columnSeverity: 'Severity', | ||
| }; | ||
|
|
||
| const str_ = i18n.createIcuMessageFn(import.meta.url, UIStrings); | ||
|
|
||
| class TrustedTypesXss extends Audit { | ||
| /** | ||
| * @return {LH.Audit.Meta} | ||
| */ | ||
| static get meta() { | ||
| return { | ||
| id: 'trusted-types-xss', | ||
| scoreDisplayMode: Audit.SCORING_MODES.INFORMATIVE, | ||
| title: str_(UIStrings.title), | ||
| description: str_(UIStrings.description), | ||
| requiredArtifacts: ['DevtoolsLog', 'URL'], | ||
| supportedModes: ['navigation'], | ||
| }; | ||
| } | ||
|
|
||
| /** | ||
| * @param {LH.Artifacts} artifacts | ||
| * @param {LH.Audit.Context} context | ||
| * @return {Promise<string[]>} | ||
| */ | ||
| static async getRawCsp(artifacts, context) { | ||
| const devtoolsLog = artifacts.DevtoolsLog; | ||
| const mainResource = | ||
| await MainResource.request({devtoolsLog, URL: artifacts.URL}, context); | ||
|
|
||
| const cspHeaders = mainResource.responseHeaders | ||
sebastian9er marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| .filter(h => { | ||
| return h.name.toLowerCase() === 'content-security-policy'; | ||
| }) | ||
| .flatMap(h => h.value.split(',')) | ||
| .filter(rawCsp => rawCsp.replace(/\s/g, '')); | ||
|
|
||
| return cspHeaders; | ||
| } | ||
|
|
||
| /** | ||
| * @param {LH.IcuMessage | string} findingDescription | ||
| * @param {LH.IcuMessage=} severity | ||
| * @return {LH.Audit.Details.TableItem} | ||
| */ | ||
| static findingToTableItem(findingDescription, severity) { | ||
| return { | ||
| description: findingDescription, | ||
| severity, | ||
| }; | ||
| } | ||
|
|
||
| /** | ||
| * @param {string[]} cspHeaders | ||
| * @return {{score: number, results: LH.Audit.Details.TableItem[]}} | ||
| */ | ||
| static constructResults(cspHeaders) { | ||
| // Check for require-trusted-types-for 'script' in CSP. | ||
| for (const cspHeader of cspHeaders) { | ||
| for (const directive of cspHeader.split(';')) { | ||
| if (directive.includes('require-trusted-types-for') && | ||
| directive.includes('script')) { | ||
sebastian9er marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| return {score: 1, results: []}; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| return { | ||
| score: 0, | ||
| results: [{ | ||
| severity: str_(i18n.UIStrings.itemSeverityHigh), | ||
| description: str_(UIStrings.noTrustedTypesToMitigateXss), | ||
| }], | ||
| }; | ||
| } | ||
|
|
||
| /** | ||
| * @param {LH.Artifacts} artifacts | ||
| * @param {LH.Audit.Context} context | ||
| * @return {Promise<LH.Audit.Product>} | ||
| */ | ||
| static async audit(artifacts, context) { | ||
| const cspHeaders = await this.getRawCsp(artifacts, context); | ||
| const {score, results} = this.constructResults(cspHeaders); | ||
|
|
||
| /** @type {LH.Audit.Details.Table['headings']} */ | ||
| const headings = [ | ||
connorjclark marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| /* eslint-disable max-len */ | ||
| {key: 'description', valueType: 'text', subItemsHeading: {key: 'description'}, label: str_(i18n.UIStrings.columnDescription)}, | ||
| {key: 'severity', valueType: 'text', subItemsHeading: {key: 'severity'}, label: str_(UIStrings.columnSeverity)}, | ||
| /* eslint-enable max-len */ | ||
| ]; | ||
| const details = Audit.makeTableDetails(headings, results); | ||
|
|
||
| return { | ||
| score, | ||
| notApplicable: !results.length, | ||
| details, | ||
| }; | ||
| } | ||
| } | ||
|
|
||
| export default TrustedTypesXss; | ||
| export {UIStrings}; | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.