Skip to content
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

fix: Disallow same-superdomain-origin cy.origin blocks #24569

Merged
Merged
38 changes: 38 additions & 0 deletions packages/driver/cypress/e2e/e2e/origin/origin.cy.ts
Expand Up @@ -10,6 +10,44 @@ describe('cy.origin', { browser: '!webkit' }, () => {
})
})

it('creates and injects into google subdomains', () => {
// Intercept google to keep our tests independent from google.
cy.intercept('https://www.google.com', {
body: '<html><head><title></title></head><body><p>google.com</p></body></html>',
})

cy.intercept('https://accounts.google.com', {
body: '<html><head><title></title></head><body><p>accounts.google.com</p></body></html>',
})

cy.visit('https://www.google.com')
cy.visit('https://accounts.google.com')
cy.origin('https://accounts.google.com', () => {
cy.window().then((win) => {
expect(win.Cypress).to.not.be.undefined
mjhenkes marked this conversation as resolved.
Show resolved Hide resolved
})
})
})

it('creates and injects into google subdomains when visiting in an origin block', () => {
// Intercept google to keep our tests independent from google.
cy.intercept('https://www.google.com', {
body: '<html><head><title></title></head><body><p>google.com</p></body></html>',
})

cy.intercept('https://accounts.google.com', {
body: '<html><head><title></title></head><body><p>accounts.google.com</p></body></html>',
})

cy.visit('https://www.google.com')
cy.origin('https://accounts.google.com', () => {
cy.visit('https://accounts.google.com')
cy.window().then((win) => {
expect(win.Cypress).to.not.be.undefined
})
})
})

it('passes viewportWidth/Height state to the secondary origin', () => {
const expectedViewport = [320, 480]

Expand Down
101 changes: 101 additions & 0 deletions packages/driver/cypress/e2e/e2e/origin/validation.cy.ts
@@ -1,6 +1,7 @@
describe('cy.origin', { browser: '!webkit' }, () => {
describe('successes', () => {
it('succeeds on a localhost domain name', () => {
cy.visit('')
mjhenkes marked this conversation as resolved.
Show resolved Hide resolved
cy.origin('localhost', () => undefined)
cy.then(() => {
const expectedSrc = `https://localhost/__cypress/spec-bridge-iframes`
Expand All @@ -11,6 +12,7 @@ describe('cy.origin', { browser: '!webkit' }, () => {
})

it('succeeds on an ip address', () => {
cy.visit('')
cy.origin('127.0.0.1', () => undefined)
cy.then(() => {
const expectedSrc = `https://127.0.0.1/__cypress/spec-bridge-iframes`
Expand All @@ -23,6 +25,7 @@ describe('cy.origin', { browser: '!webkit' }, () => {
// TODO: $Location does not support ipv6
// https://github.com/cypress-io/cypress/issues/20970
it.skip('succeeds on an ipv6 address', () => {
cy.visit('')
cy.origin('0000:0000:0000:0000:0000:0000:0000:0001', () => undefined)
cy.then(() => {
const expectedSrc = `https://[::1]/__cypress/spec-bridge-iframes`
Expand All @@ -33,6 +36,7 @@ describe('cy.origin', { browser: '!webkit' }, () => {
})

it('succeeds on a unicode domain', () => {
cy.visit('')
cy.origin('はじめよう.みんな', () => undefined)
cy.then(() => {
const expectedSrc = `https://xn--p8j9a0d9c9a.xn--q9jyb4c/__cypress/spec-bridge-iframes`
Expand All @@ -43,6 +47,7 @@ describe('cy.origin', { browser: '!webkit' }, () => {
})

it('succeeds on a complete origin', () => {
cy.visit('')
cy.origin('http://foobar1.com:3500', () => undefined)
cy.then(() => {
const expectedSrc = `http://foobar1.com:3500/__cypress/spec-bridge-iframes`
Expand All @@ -53,6 +58,7 @@ describe('cy.origin', { browser: '!webkit' }, () => {
})

it('succeeds on a complete origin using https', () => {
cy.visit('')
cy.origin('https://www.foobar2.com:3500', () => undefined)
cy.then(() => {
const expectedSrc = `https://www.foobar2.com:3500/__cypress/spec-bridge-iframes`
Expand All @@ -62,7 +68,35 @@ describe('cy.origin', { browser: '!webkit' }, () => {
})
})

it('succeeds on a complete origin from https using https', () => {
cy.visit('https://www.foobar.com:3502/fixtures/primary-origin.html')
cy.origin('https://www.idp.com:3502', () => undefined)
cy.then(() => {
const expectedSrc = `https://www.idp.com:3502/__cypress/spec-bridge-iframes`
const iframe = window.top?.document.getElementById('Spec\ Bridge:\ https://www.idp.com:3502') as HTMLIFrameElement

expect(iframe.src).to.equal(expectedSrc)
})
})

it('succeeds if url is the super domain as top but the super domain is excepted and must be strictly same origin', () => {
// Intercept google to keep our tests independent from google.
cy.intercept('https://www.google.com', {
body: '<html><head><title></title></head><body><p></body></html>',
})

cy.visit('https://www.google.com')
cy.origin('accounts.google.com', () => undefined)
cy.then(() => {
const expectedSrc = `https://accounts.google.com/__cypress/spec-bridge-iframes`
const iframe = window.top?.document.getElementById('Spec\ Bridge:\ https://accounts.google.com') as HTMLIFrameElement

expect(iframe.src).to.equal(expectedSrc)
})
})

it('succeeds on a hostname and port', () => {
cy.visit('')
cy.origin('foobar3.com:3500', () => undefined)
cy.then(() => {
const expectedSrc = `https://foobar3.com:3500/__cypress/spec-bridge-iframes`
Expand All @@ -73,6 +107,7 @@ describe('cy.origin', { browser: '!webkit' }, () => {
})

it('succeeds on a protocol and hostname', () => {
cy.visit('')
cy.origin('http://foobar4.com', () => undefined)
cy.then(() => {
const expectedSrc = `http://foobar4.com/__cypress/spec-bridge-iframes`
Expand All @@ -83,6 +118,7 @@ describe('cy.origin', { browser: '!webkit' }, () => {
})

it('succeeds on a subdomain', () => {
cy.visit('')
cy.origin('app.foobar5.com', () => undefined)
cy.then(() => {
const expectedSrc = `https://app.foobar5.com/__cypress/spec-bridge-iframes`
Expand All @@ -93,6 +129,7 @@ describe('cy.origin', { browser: '!webkit' }, () => {
})

it('succeeds when only domain is passed', () => {
cy.visit('')
cy.origin('foobar6.com', () => undefined)
cy.then(() => {
const expectedSrc = `https://foobar6.com/__cypress/spec-bridge-iframes`
Expand All @@ -103,6 +140,7 @@ describe('cy.origin', { browser: '!webkit' }, () => {
})

it('succeeds on a url with path', () => {
cy.visit('')
cy.origin('http://www.foobar7.com/login', () => undefined)
cy.then(() => {
const expectedSrc = `http://www.foobar7.com/__cypress/spec-bridge-iframes`
Expand All @@ -113,6 +151,7 @@ describe('cy.origin', { browser: '!webkit' }, () => {
})

it('succeeds on a url with a hash', () => {
cy.visit('')
cy.origin('http://www.foobar8.com/#hash', () => undefined)
cy.then(() => {
const expectedSrc = `http://www.foobar8.com/__cypress/spec-bridge-iframes`
Expand All @@ -123,6 +162,7 @@ describe('cy.origin', { browser: '!webkit' }, () => {
})

it('succeeds on a url with a path and hash', () => {
cy.visit('')
cy.origin('http://www.foobar9.com/login/#hash', () => undefined)
cy.then(() => {
const expectedSrc = `http://www.foobar9.com/__cypress/spec-bridge-iframes`
Expand All @@ -133,6 +173,7 @@ describe('cy.origin', { browser: '!webkit' }, () => {
})

it('succeeds on a domain with path', () => {
cy.visit('')
cy.origin('foobar10.com/login', () => undefined)
cy.then(() => {
const expectedSrc = `https://foobar10.com/__cypress/spec-bridge-iframes`
Expand All @@ -143,6 +184,7 @@ describe('cy.origin', { browser: '!webkit' }, () => {
})

it('succeeds on a domain with a hash', () => {
cy.visit('')
cy.origin('foobar11.com/#hash', () => undefined)
cy.then(() => {
const expectedSrc = `https://foobar11.com/__cypress/spec-bridge-iframes`
Expand All @@ -153,6 +195,7 @@ describe('cy.origin', { browser: '!webkit' }, () => {
})

it('succeeds on a domain with a path and hash', () => {
cy.visit('')
cy.origin('foobar12.com/login/#hash', () => undefined)
cy.then(() => {
const expectedSrc = `https://foobar12.com/__cypress/spec-bridge-iframes`
Expand All @@ -163,6 +206,7 @@ describe('cy.origin', { browser: '!webkit' }, () => {
})

it('succeeds on a public suffix with a subdomain', () => {
cy.visit('')
cy.origin('app.foobar.herokuapp.com', () => undefined)
cy.then(() => {
const expectedSrc = `https://app.foobar.herokuapp.com/__cypress/spec-bridge-iframes`
Expand All @@ -173,6 +217,7 @@ describe('cy.origin', { browser: '!webkit' }, () => {
})

it('succeeds on a machine name', () => {
cy.visit('')
cy.origin('machine-name', () => undefined)
cy.then(() => {
const expectedSrc = `https://machine-name/__cypress/spec-bridge-iframes`
Expand All @@ -199,6 +244,7 @@ describe('cy.origin', { browser: '!webkit' }, () => {
})

it('finds the correct spec bridge even if a previous spec bridge host is a subset of the current host', () => {
cy.visit('')
// Establish a spec bridge with a 'bar.com' host prior to loading 'foobar.com'
cy.origin('http://www.bar.com:3500', () => undefined)

Expand Down Expand Up @@ -262,6 +308,8 @@ describe('cy.origin', { browser: '!webkit' }, () => {
done()
})

cy.visit('')

// @ts-ignore
cy.origin()
})
Expand All @@ -273,6 +321,8 @@ describe('cy.origin', { browser: '!webkit' }, () => {
done()
})

cy.visit('')

// @ts-ignore
cy.origin()
})
Expand All @@ -284,16 +334,48 @@ describe('cy.origin', { browser: '!webkit' }, () => {
done()
})

cy.visit('')

cy.origin('http://www.foobar.com?foo=bar', () => undefined)
})

it('errors if the url param is same superDomainOrigin as top', (done) => {
cy.on('fail', (err) => {
expect(err.message).to.include('`cy.origin()` requires the first argument to be either a url or a domain name that is cross origin when compared to the top url. You passed `http://localhost:3500` to the origin command, while top is at `http://localhost:3500`')
mjhenkes marked this conversation as resolved.
Show resolved Hide resolved

done()
})

cy.visit('')

cy.origin(window.origin, () => undefined)
})

it('errors if the url param is same origin as top', (done) => {
cy.on('fail', (err) => {
expect(err.message).to.include('`cy.origin()` requires the first argument to be either a url or a domain name that is cross origin when compared to the top url. You passed `https://www.google.com` to the origin command, while top is at `https://www.google.com`')

done()
})

// Intercept google to keep our tests independent from google.
cy.intercept('https://www.google.com', {
body: '<html><head><title></title></head><body><p></body></html>',
})

cy.visit('https://www.google.com')
cy.origin('https://www.google.com', () => undefined)
})

it('errors passing non-array to callback function', (done) => {
cy.on('fail', (err) => {
expect(err.message).to.equal('`cy.origin()` requires the \'options\' argument to be an object. You passed: `foo`')

done()
})

cy.visit('')

// @ts-ignore
cy.origin('foobar.com', 'foo', () => {})
})
Expand All @@ -309,6 +391,8 @@ describe('cy.origin', { browser: '!webkit' }, () => {
done()
})

cy.visit('')

cy.origin('foobar.com', {
// @ts-ignore
foo: 'foo',
Expand All @@ -329,6 +413,8 @@ describe('cy.origin', { browser: '!webkit' }, () => {
done()
})

cy.visit('')

const el = document.createElement('div')

cy.origin('foobar.com', { args: ['foo', '1', el] }, () => {})
Expand All @@ -341,6 +427,8 @@ describe('cy.origin', { browser: '!webkit' }, () => {
done()
})

cy.visit('')

// @ts-ignore
cy.origin('foobar.com')
})
Expand All @@ -352,8 +440,21 @@ describe('cy.origin', { browser: '!webkit' }, () => {
done()
})

cy.visit('')

// @ts-ignore
cy.origin('foobar.com', {})
})

it('errors and does not hang when throwing a mixed content error creating the spec bridge', { defaultCommandTimeout: 50 }, (done) => {
cy.on('fail', (err) => {
expect(err.message).to.include(`\`cy.origin()\` failed to create a spec bridge to communicate with the specified origin. This can happen when you attempt to create a spec bridge to an insecure (http) frame from a secure (https) frame.`)
AtofStryker marked this conversation as resolved.
Show resolved Hide resolved

done()
})

cy.visit('https://www.foobar.com:3502/fixtures/primary-origin.html')
cy.origin('http://www.foobar.com:3500', () => {})
})
})
})