Cypress & iFrames/x-origin issues.
Currently working Browsers & Modes
- Chrome Headed
- Cypress UI
- Cypress CLI
- Chrome Headless
- Cypress UI
- Cypress CLI
- Electron Headed
- Cypress UI
- Cypress CLI
- Chrome Headed
- Cypress UI
- Cypress CLI
There are a considerations for automating your web application with Cypress, that you may come across, which may lead you to the Cypress Web Security Docs or trawling through Cypress raised issues for potential workarounds/solutions.
Problems you may encounter
Cypress Docs - disabling web security
- Display insecure content
- Navigate to any superdomain without cross origin errors
- Access cross origin iframes that are embedded in your application.
Simply by setting chromeWebSecurity
to false in your cypress.json
{
"chromeWebSecurity": false
}
If you set it in your base cypress.json
, then you will apply this to all your sites, which may not be ideal, as you may only want to cater for insecure content on your dev machine, but secure content, in testing in prod.
See how to configure Cypress per env configuration files
However we wanted to check a journey that integrates with a 3rd party, and came across some cross site issues
Uncaught DOMException: Blocked a frame with origin "https://your_site_here" from accessing a cross-origin frame.
So we switch off chromeWebSecurity: false
and then get this error
Refused to display 'https://your_site_here' in a frame because it set 'X-Frame-Options' to 'sameorigin'.
Looks like these guys had the same issue
So hi-ho, it's off to docs we go
chromium-command-line-switches
We want to disable the following features
-
--disable-features=CrossSiteDocumentBlockingAlways,CrossSiteDocumentBlockingIfIsolating
Cross-Origin Read Blocking (CORB) blocked cross-origin response https://www.example.com/example.html with MIME type text/html.
- See for more details
-
-disable-features=IsolateOrigins,site-per-process
- Require dedicated processes for a set of origins, specified as a comma-separated list.`
- Enforces a one-site-per-process security policy: Each renderer process, for its whole lifetime, is dedicated to rendering pages for just one site. * Thus, pages from different sites are never in the same process. * A renderer process's access rights are restricted based on its site. * All cross-site navigations force process swaps.
<iframe>s
are rendered out-of-process whenever the src= is cross-site.
add the following to cypress/index.js
const path = require('path');
module.exports = (on, config) => {
on('before:browser:launch', (browser = {}, args) => {
console.log(config, browser, args);
if (browser.name === 'chrome') {
args.push("--disable-features=CrossSiteDocumentBlockingIfIsolating,CrossSiteDocumentBlockingAlways,IsolateOrigins,site-per-process");
}
return args;
});
};
Drop X-Frame-Options and Content-Security-Policy HTTP response headers, allowing all pages to be iframed.
- 'content-security-policy',
- 'x-frame-options
We can use Ignore X-Frame headers chrome extension
we need to load it into our cypress instance, so we can download it from https://chrome-extension-downloader.com/ and place is your cypress/extensions
folder
add the following to cypress/index.js
const path = require('path');
module.exports = (on, config) => {
on('before:browser:launch', (browser = {}, args) => {
console.log(config, browser, args);
if (browser.name === 'chrome') {
const ignoreXFrameHeadersExtension = path.join(__dirname, '../extensions/ignore-x-frame-headers');
args.push(args.push(`--load-extension=${ignoreXFrameHeadersExtension}`));
}
return args;
});
};
We can also do this a little les manually
npm i chrome-ext-downloader --save-dev
or yarn add chrome-ext-downloader --dev
put the following in package.json
{
"scripts": {
"download-extension": "ced gleekbfjekiniecknbkamfmkohkpodhe extensions/ignore-x-frame-headers"
},
"dependencies": {
"chrome-ext-downloader": "^1.0.4",
}
}
We can update our cypress/plugins/index.js
file to incorpoate both of these
const path = require('path');
module.exports = (on, config) => {
on('before:browser:launch', (browser = {}, args) => {
console.log(config, browser, args);
if (browser.name === 'chrome') {
const ignoreXFrameHeadersExtension = path.join(__dirname, '../extensions/ignore-x-frame-headers');
args.push(args.push(`--load-extension=${ignoreXFrameHeadersExtension}`));
args.push("--disable-features=CrossSiteDocumentBlockingIfIsolating,CrossSiteDocumentBlockingAlways,IsolateOrigins,site-per-process");
}
return args;
});
};