fix(server): fix setCookie with __Host- prefix, __Secure- prefix (#8526)

Co-authored-by: Zach Bloomquist <github@chary.us>
This commit is contained in:
Ben Kucera
2020-09-28 11:00:12 -04:00
committed by GitHub
parent b66bcd4532
commit 644d75e3e3
5 changed files with 115 additions and 6 deletions

View File

@@ -8,12 +8,6 @@ describe('src/cy/commands/cookies', () => {
})
context('test:before:run:async', () => {
it('can test unstubbed, real server', () => {
Cypress.automation.restore()
cy.setCookie('foo', 'bar')
})
it('clears cookies before each test run', () => {
Cypress.automation
.withArgs('get:cookies', { domain: 'localhost' })

View File

@@ -0,0 +1,86 @@
describe('e2e cookies spec', () => {
it('simple cookie', () => {
cy.setCookie('foo', 'bar')
cy.getCookie('foo', 'bar')
.then((cookie) => expect(cookie).exist)
})
context('__Host- prefix', () => {
// https://github.com/cypress-io/cypress/issues/8261
it('can set __Host- cookie', () => {
cy.visit('https://example.com')
cy.setCookie('__Host-foobar', 'someval', {
domain: 'example.com',
sameSite: 'strict',
secure: true,
})
cy.getCookie('__Host-foobar').then(((cookie) => {
expect(cookie).exist
expect(cookie.domain).match(/^\.?example\.com$/)
expect(cookie.path).eq('/')
expect(cookie.secure).is.true
}))
})
it('errors when __Host- cookie and secure:false', (done) => {
cy.visit('https://example.com')
cy.setCookie('__Host-foobar', 'someval')
cy.on('fail', (err) => {
expect(err.message)
.contain('__Host-')
.contain('must be set with `{ secure: true }`')
done()
})
})
it('errors when __Host- cookie and path', (done) => {
cy.visit('https://example.com')
cy.setCookie('__Host-foobar', 'someval', {
secure: true,
path: '/foo',
})
cy.on('fail', (err) => {
expect(err.message).contain('__Host-').contain('the path must be')
done()
})
})
})
context('__Secure- prefix', () => {
it('can set __Secure- cookie', () => {
cy.visit('https://example.com')
cy.setCookie('__Secure-foobar', 'someval', {
domain: 'example.com',
path: '/foo',
secure: true,
})
cy.getCookie('__Secure-foobar').then(((cookie) => {
expect(cookie).exist
expect(cookie.domain).match(/^\.?example\.com$/)
expect(cookie.path).eq('/foo')
expect(cookie.secure).is.true
}))
})
it('errors when __Secure- cookie secure:false', (done) => {
cy.visit('https://example.com')
cy.setCookie('__Secure-foobar', 'someval', {
domain: 'example.com',
path: '/foo',
})
cy.on('fail', (err) => {
expect(err.message)
.contain('__Secure-')
.contain('must be set with `{ secure: true }`')
done()
})
})
})
})

View File

@@ -57,6 +57,14 @@ const normalizeSameSite = (sameSite) => {
return sameSite
}
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#Attributes
function cookieValidatesHostPrefix (options) {
return options.secure === false || (options.path && options.path !== '/')
}
function cookieValidatesSecurePrefix (options) {
return options.secure === false
}
module.exports = function (Commands, Cypress, cy, state, config) {
const automateCookies = function (event, obj = {}, log, timeout) {
const automate = () => {
@@ -285,6 +293,14 @@ module.exports = function (Commands, Cypress, cy, state, config) {
$errUtils.throwErrByPath('setCookie.invalid_arguments', { onFail })
}
if (options.name.startsWith('__Secure-') && cookieValidatesSecurePrefix(options)) {
$errUtils.throwErrByPath('setCookie.secure_prefix', { onFail })
}
if (options.name.startsWith('__Host-') && cookieValidatesHostPrefix(options)) {
$errUtils.throwErrByPath('setCookie.host_prefix', { onFail })
}
return automateCookies('set:cookie', cookie, options._log, options.timeout)
.then((resp) => {
options.cookie = resp

View File

@@ -1480,6 +1480,14 @@ module.exports = {
docsUrl: 'https://on.cypress.io/setcookie',
}
},
host_prefix: {
message: 'Cookies starting with the `__Host-` prefix must be set with `{ secure: true }`, and the path must be `/`',
docsUrl: 'https://on.cypress.io/setcookie',
},
secure_prefix: {
message: 'Cookies starting with the `__Secure-` prefix must be set with `{ secure: true }`',
docsUrl: 'https://on.cypress.io/setcookie',
},
},
shadow: {

View File

@@ -116,6 +116,11 @@ export const CdpAutomation = (sendDebuggerCommandFn: SendDebuggerCommand) => {
}
}
if (setCookieRequest.name.startsWith('__Host-')) {
setCookieRequest.url = `https://${cookie.domain}`
delete setCookieRequest.domain
}
return setCookieRequest
}