From 5198a866bd4e6b7cc1ecc5261f740087cc9e9e0d Mon Sep 17 00:00:00 2001 From: Ben Kucera <14625260+Bkucera@users.noreply.github.com> Date: Mon, 9 Nov 2020 09:57:31 -0500 Subject: [PATCH] fix: only modify js on AUT domain in proxy (#9018) --- .eslintignore | 4 ++-- .../proxy/lib/http/response-middleware.ts | 5 ++-- packages/server/test/e2e/7_proxying_spec.ts | 16 +++++++++++++ .../e2e/cypress/integration/proxying_spec.js | 24 +++++++++++++++++++ .../projects/e2e/cypress/plugins/index.js | 3 +++ .../e2e/static/simple_obstructive_code.js | 3 +++ packages/server/test/support/helpers/e2e.ts | 4 ++++ 7 files changed, 55 insertions(+), 4 deletions(-) create mode 100644 packages/server/test/e2e/7_proxying_spec.ts create mode 100644 packages/server/test/support/fixtures/projects/e2e/cypress/integration/proxying_spec.js create mode 100644 packages/server/test/support/fixtures/projects/e2e/static/simple_obstructive_code.js diff --git a/.eslintignore b/.eslintignore index e88d53b385..088756bc01 100644 --- a/.eslintignore +++ b/.eslintignore @@ -11,8 +11,8 @@ **/support/fixtures/* !**/support/fixtures/projects **/support/fixtures/projects/**/_fixtures/* +**/support/fixtures/projects/**/static/* **/support/fixtures/projects/**/*.jsx -**/support/fixtures/projects/**/jquery.js **/support/fixtures/projects/**/fail.js **/test/fixtures **/vendor @@ -41,4 +41,4 @@ npm/webpack-preprocessor/examples/use-babelrc/cypress/integration/spec.js **/.cy **/.git -/npm/react/bin/* \ No newline at end of file +/npm/react/bin/* diff --git a/packages/proxy/lib/http/response-middleware.ts b/packages/proxy/lib/http/response-middleware.ts index 17c499f340..2a21253c04 100644 --- a/packages/proxy/lib/http/response-middleware.ts +++ b/packages/proxy/lib/http/response-middleware.ts @@ -237,12 +237,13 @@ const PatchExpressSetHeader: ResponseMiddleware = function () { const SetInjectionLevel: ResponseMiddleware = function () { this.res.isInitial = this.req.cookies['__cypress.initial'] === 'true' + const isReqMatchOriginPolicy = reqMatchesOriginPolicy(this.req, this.getRemoteState()) const getInjectionLevel = () => { if (this.incomingRes.headers['x-cypress-file-server-error'] && !this.res.isInitial) { return 'partial' } - if (!resContentTypeIs(this.incomingRes, 'text/html') || !reqMatchesOriginPolicy(this.req, this.getRemoteState())) { + if (!resContentTypeIs(this.incomingRes, 'text/html') || !isReqMatchOriginPolicy) { return false } @@ -261,7 +262,7 @@ const SetInjectionLevel: ResponseMiddleware = function () { this.res.wantsInjection = getInjectionLevel() } - this.res.wantsSecurityRemoved = this.config.modifyObstructiveCode && ( + this.res.wantsSecurityRemoved = this.config.modifyObstructiveCode && isReqMatchOriginPolicy && ( (this.res.wantsInjection === 'full') || resContentTypeIsJavaScript(this.incomingRes) ) diff --git a/packages/server/test/e2e/7_proxying_spec.ts b/packages/server/test/e2e/7_proxying_spec.ts new file mode 100644 index 0000000000..ac71241f7c --- /dev/null +++ b/packages/server/test/e2e/7_proxying_spec.ts @@ -0,0 +1,16 @@ +import e2e from '../support/helpers/e2e' + +describe('e2e proxying spec', () => { + e2e.setup({ + servers: { + port: 7878, + static: true, + cors: true, + https: true, + }, + }) + + e2e.it('integrity check', { + spec: 'proxying_spec.js', + }) +}) diff --git a/packages/server/test/support/fixtures/projects/e2e/cypress/integration/proxying_spec.js b/packages/server/test/support/fixtures/projects/e2e/cypress/integration/proxying_spec.js new file mode 100644 index 0000000000..7409d2f967 --- /dev/null +++ b/packages/server/test/support/fixtures/projects/e2e/cypress/integration/proxying_spec.js @@ -0,0 +1,24 @@ +describe('proxying', () => { + // load a script that has obstructive code and would otherwise be modified by the proxy + // https://github.com/cypress-io/cypress/issues/8983 + it('does not fail integrity check for cross-origin scripts', () => { + cy.visit('/index.html') + .then((win) => { + /** + * @type {Document} + */ + const document = win.document + const script = document.createElement('script') + + script.src = 'https://localhost:7878/static/simple_obstructive_code.js' + script.integrity = 'sha256-iVKZPZrzbe7YNdMKYWJ1+f74j5lD3gRFvGjqtLyji6A=' + script.crossOrigin = 'anonymous' + document.head.append(script) + + return new Promise((resolve, reject) => { + script.onload = resolve + script.onerror = () => reject(new Error('script failed to load, check the console. Possibly a failed integrity check')) + }) + }) + }) +}) diff --git a/packages/server/test/support/fixtures/projects/e2e/cypress/plugins/index.js b/packages/server/test/support/fixtures/projects/e2e/cypress/plugins/index.js index b88d7624d7..c758734b11 100644 --- a/packages/server/test/support/fixtures/projects/e2e/cypress/plugins/index.js +++ b/packages/server/test/support/fixtures/projects/e2e/cypress/plugins/index.js @@ -8,6 +8,9 @@ const path = require('path') const Promise = require('bluebird') const { useFixedFirefoxResolution } = require('../../../utils') +/** + * @type {Cypress.PluginConfig} + */ module.exports = (on, config) => { let performance = { track: () => Promise.resolve(), diff --git a/packages/server/test/support/fixtures/projects/e2e/static/simple_obstructive_code.js b/packages/server/test/support/fixtures/projects/e2e/static/simple_obstructive_code.js new file mode 100644 index 0000000000..867d1ce67f --- /dev/null +++ b/packages/server/test/support/fixtures/projects/e2e/static/simple_obstructive_code.js @@ -0,0 +1,3 @@ +(function () { + if (top != self) {console.log('loaded!')} +})() diff --git a/packages/server/test/support/helpers/e2e.ts b/packages/server/test/support/helpers/e2e.ts index 3a55ad7727..0426060490 100644 --- a/packages/server/test/support/helpers/e2e.ts +++ b/packages/server/test/support/helpers/e2e.ts @@ -202,6 +202,10 @@ const startServer = function (obj) { app.use(morgan('dev')) + if (obj.cors) { + app.use(require('cors')()) + } + const s = obj.static if (s) {