From e1142ec1dd1fb54d07a471e23f0fbde8c23a37e4 Mon Sep 17 00:00:00 2001 From: Preston Goforth Date: Mon, 5 Jun 2023 17:47:39 -0400 Subject: [PATCH] chore: Move 'sandbox' and 'navigate-to' into `unsupportedCSPDirectives` - Add additional system tests - Update snapshots and unit test --- cli/types/cypress.d.ts | 2 +- packages/config/src/options.ts | 2 +- packages/proxy/lib/http/util/csp-header.ts | 10 +++++++++- packages/server/test/unit/config_spec.js | 4 ++-- .../with_allow_list_custom_or_true.cy.ts | 19 +++++++++++++++++++ 5 files changed, 32 insertions(+), 5 deletions(-) diff --git a/cli/types/cypress.d.ts b/cli/types/cypress.d.ts index 8f0a0c6f9a01..b41954e27087 100644 --- a/cli/types/cypress.d.ts +++ b/cli/types/cypress.d.ts @@ -2672,7 +2672,7 @@ declare namespace Cypress { force: boolean } - type experimentalCspAllowedDirectives = 'default-src' | 'child-src' | 'frame-src' | 'script-src' | 'script-src-elem' | 'sandbox' | 'form-action' | 'navigate-to' + type experimentalCspAllowedDirectives = 'default-src' | 'child-src' | 'frame-src' | 'script-src' | 'script-src-elem' | 'form-action' type scrollBehaviorOptions = false | 'center' | 'top' | 'bottom' | 'nearest' diff --git a/packages/config/src/options.ts b/packages/config/src/options.ts index 244c27879696..d708fae20e92 100644 --- a/packages/config/src/options.ts +++ b/packages/config/src/options.ts @@ -201,7 +201,7 @@ const driverConfigOptions: Array = [ }, { name: 'experimentalCspAllowList', defaultValue: false, - validation: validate.validateAny(validate.isBoolean, validate.isArrayIncludingAny('script-src-elem', 'script-src', 'default-src', 'sandbox', 'form-action', 'navigate-to', 'child-src', 'frame-src')), + validation: validate.validateAny(validate.isBoolean, validate.isArrayIncludingAny('script-src-elem', 'script-src', 'default-src', 'form-action', 'child-src', 'frame-src')), overrideLevel: 'never', requireRestartOnChange: 'server', }, { diff --git a/packages/proxy/lib/http/util/csp-header.ts b/packages/proxy/lib/http/util/csp-header.ts index 4a4ec2739106..94bc14dc1a27 100644 --- a/packages/proxy/lib/http/util/csp-header.ts +++ b/packages/proxy/lib/http/util/csp-header.ts @@ -8,7 +8,7 @@ export const nonceDirectives = ['script-src-elem', 'script-src', 'default-src'] export const problematicCspDirectives = [ ...nonceDirectives, - 'child-src', 'frame-src', 'sandbox', 'form-action', 'navigate-to', + 'child-src', 'frame-src', 'form-action', ] as Cypress.experimentalCspAllowedDirectives[] export const unsupportedCSPDirectives = [ @@ -19,6 +19,14 @@ export const unsupportedCSPDirectives = [ * top-level frame. */ 'frame-ancestors', + /** + * The `navigate-to` directive is not yet fully supported, so we are erring on the side of caution + */ + 'navigate-to', + /** + * The `sandbox` directive seems to affect all iframes on the page, even if the page is a direct child of Cypress + */ + 'sandbox', /** * Since Cypress might modify the DOM of the application under test, `trusted-types` would prevent the * DOM injection from occurring. diff --git a/packages/server/test/unit/config_spec.js b/packages/server/test/unit/config_spec.js index 96a23423665f..75f3709b129d 100644 --- a/packages/server/test/unit/config_spec.js +++ b/packages/server/test/unit/config_spec.js @@ -573,7 +573,7 @@ describe('lib/config', () => { }) context('experimentalCspAllowList', () => { - const experimentalCspAllowedDirectives = JSON.stringify(['script-src-elem', 'script-src', 'default-src', 'sandbox', 'form-action', 'navigate-to', 'child-src', 'frame-src']).split(',').join(', ') + const experimentalCspAllowedDirectives = JSON.stringify(['script-src-elem', 'script-src', 'default-src', 'form-action', 'child-src', 'frame-src']).split(',').join(', ') it('passes if false', function () { this.setup({ experimentalCspAllowList: false }) @@ -600,7 +600,7 @@ describe('lib/config', () => { }) it('passes if subset of Cypress.experimentalCspAllowedDirectives[]', function () { - this.setup({ experimentalCspAllowList: ['default-src', 'sandbox'] }) + this.setup({ experimentalCspAllowList: ['default-src', 'form-action'] }) return this.expectValidationPasses() }) diff --git a/system-tests/projects/e2e/cypress/e2e/experimental_csp_allow_list_spec/with_allow_list_custom_or_true.cy.ts b/system-tests/projects/e2e/cypress/e2e/experimental_csp_allow_list_spec/with_allow_list_custom_or_true.cy.ts index 02deac238782..b55415c514e3 100644 --- a/system-tests/projects/e2e/cypress/e2e/experimental_csp_allow_list_spec/with_allow_list_custom_or_true.cy.ts +++ b/system-tests/projects/e2e/cypress/e2e/experimental_csp_allow_list_spec/with_allow_list_custom_or_true.cy.ts @@ -39,6 +39,25 @@ describe('experimentalCspAllowList is custom or true', () => { cy.get('h1').contains('CSP Script Test Modified').should('be.visible') }) + + it('sandbox is always stripped', () => { + // Since sandbox is inclusive, all other sandbox actions would be restricted except for `allow-downloads` + visitUrl.searchParams.append('csp', `sandbox 'allow-downloads'`) + cy.visit(visitUrl.toString()) + + // expect the form to post and navigate to a new page, meaning the sandbox directive was stripped + cy.get('#submit').click() + cy.contains('Cannot POST /').should('exist') + }) + + it('navigate-to is always stripped', () => { + visitUrl.searchParams.append('csp', `navigate-to 'none'`) + cy.visit(visitUrl.toString()) + + // expect the form to post and navigate to a new page, meaning the navigate-to directive was stripped + cy.get('#submit').click() + cy.contains('Cannot POST /').should('exist') + }) }) describe('allowed', () => {