diff --git a/CHANGELOG.md b/CHANGELOG.md index 97adcfc..187ea5f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,19 @@ All notable changes to `@ngbracket/a11y-devtools` are documented here. This project adheres to [Semantic Versioning](https://semver.org/). +## 0.18.3 + +### Fixed + +- Report mode now scans pages served with a strict Content-Security-Policy or + Trusted Types. The scan runs as an injected script, which a policy such as + `script-src 'self'` or `require-trusted-types-for 'script'` blocked, so the + page was reported as an error with no findings. The scanning browser now + ignores the page's CSP, whether it comes from a header or a `` tag. + Your app's policy is unchanged. Because the scan runs without the policy, + anything the policy would block for real users (a web font, an inline style) + loads during the scan, so a problem caused by the CSP itself isn't reported. + ## 0.18.2 ### Fixed diff --git a/package-lock.json b/package-lock.json index 2cdf0fe..fb31bdb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@ngbracket/a11y-devtools", - "version": "0.18.2", + "version": "0.18.3", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@ngbracket/a11y-devtools", - "version": "0.18.2", + "version": "0.18.3", "license": "MIT", "dependencies": { "axe-core": "^4.13.0" diff --git a/package.json b/package.json index 8e75ecb..0f5764f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@ngbracket/a11y-devtools", - "version": "0.18.2", + "version": "0.18.3", "description": "Finds accessibility problems in Angular apps and names the component behind each one. A dev overlay, or headless reports for CI.", "license": "MIT", "author": "Duncan Faulkner", diff --git a/src/report/headless.ts b/src/report/headless.ts index e6b8334..88f2ca2 100644 --- a/src/report/headless.ts +++ b/src/report/headless.ts @@ -214,7 +214,14 @@ async function scanPass( config: PassConfig, ): Promise { const { baseUrl, routes, labels, waitMs, axeOptions, inPageScript, frameworkPrefixes } = config; - const context = await browser.newContext({ viewport: { width: 1280, height: 900 }, colorScheme }); + // bypassCSP: the scan runs as an injected inline script (plus a style tag that + // hides the overlay), which a strict Content-Security-Policy or Trusted Types + // would block. It only lifts the policy in this scanning browser. + const context = await browser.newContext({ + viewport: { width: 1280, height: 900 }, + colorScheme, + bypassCSP: true, + }); const pages: PageReport[] = []; try { const page = await context.newPage(); diff --git a/src/testing/e2e-report.spec.ts b/src/testing/e2e-report.spec.ts index c99b3bb..48cce21 100644 --- a/src/testing/e2e-report.spec.ts +++ b/src/testing/e2e-report.spec.ts @@ -57,6 +57,20 @@ const PAGES: Record = { Help `, + // Served with a strict Content-Security-Policy and Trusted Types (see the + // server below), which block the injected scan unless the browser bypasses CSP. + '/csp': ` +
+

Strict CSP

+ +
`, + // The same policy set by a tag instead (the server adds it + // to ), which is how many Angular apps ship a CSP. + '/csp-meta': ` +
+

Strict CSP in a meta tag

+ +
`, // Healthy: native controls in order, plus an iframe (Tab inside a frame shows // up as repeated focus on the