Modern web applications rely on strict browser security features such as the same origin policy, secure cookies, and HTTPS enforcement to protect user data and prevent malicious behavior. While these safeguards are critical, they can create challenges when building automated end-to-end tests.
Testing frameworks like Cypress must operate within these restrictions while still accessing the full behavior of the application under test. Cypress takes an unusual approach to testing by running inside the browser alongside the application.
This gives it more control but also introduces complications. Browser rules that block cross-origin communication, iframe interactions, or mixed content can interfere with test execution.
This article explores how Cypress interacts with the browser security model, from handling secure connections over HTTPS to navigating common web security constraints. It also delves into workarounds for fixing cross-origin issues and ensuring seamless testing despite browser-imposed limitations.
Understanding Cypress and the Browser Security Model
All modern browsers enforce the same-origin policy by default. This rule blocks communication between elements like <iframes> if their origins (protocol, domain, or port) don’t match, serving as a core browser security feature that protects against cross-site attacks.
However, this policy also restricts automated test frameworks like Cypress, which require direct and continuous access to your application’s internals, regardless of whether it includes third-party scripts, iframes, or redirects.
To work within these constraints, Cypress employs a range of techniques:
- JavaScript injection and internal browser APIs allow Cypress to hook into your application without modifying your code.
- Network proxying rewrites all traffic so it appears to come from the exact origin.
- Document domain manipulation and URL rewriting enable access to cross-origin content under a unified origin.
- Cookies are handled intelligently. Even when iframes are cross-origin, Cypress ensures the top-level context is treated as your app’s origin, preserving the expected behavior for the document.cookie.
For example, when a test begins, Cypress first loads its own web app on a random port (e.g., http://localhost:65874/_/) and then proxies your app through it. When cy.visit() is called, Cypress updates the browser’s URL to match your app’s origin. From that point on, all test commands run as if they’re operating within the same domain, overcoming the initial SOP limitations.
These workarounds let Cypress automate cross-origin interactions smoothly while still respecting the browser’s security boundaries during testing.
To further enhance your testing experience and ensure comprehensive coverage across real devices and browsers, consider using BrowserStack.
BrowserStack provides a cloud-based testing platform that seamlessly integrates with Cypress, allowing you to run your tests on a wide range of real environments, ensuring consistent results across multiple browsers and devices.
How does Cypress support HTTPS?
Cypress makes testing HTTPS-enabled sites seamless by handling secure connections in the background, allowing developers to test with full control over network-level traffic. To enable real-time traffic manipulation, Cypress manages SSL certificates dynamically by acting as its own Certificate Authority (CA). This process ensures that requests to HTTPS sites can be intercepted and modified during testing.
While this approach provides the flexibility needed for automated tests, it can trigger browser warnings. For example, Chrome will display an “SSL certificate does not match” message, which is a valid alert. This happens because Cypress generates its own SSL certificate for the testing domain.
The warning is specific to the superdomain being tested and does not affect other traffic, as Cypress’s certificate applies only within the context of the test environment.
By handling SSL certificates in this way, Cypress ensures that HTTPS-based sites are fully accessible for testing without interrupting the security protocols of other traffic or external systems.
Key Browser Security Constraints When Using Cypress
When using Cypress for end-to-end testing, it’s important to understand the various browser security constraints that can impact your test execution.
These constraints are designed to protect users from malicious behavior, but they can introduce challenges for automated testing, particularly when dealing with complex app architectures.
Below are some key security constraints that Cypress encounters:
Superdomain
When using Cypress for testing, all URLs accessed during a single test must share the same superdomain. This is because Cypress modifies the URL of its own host to match the URL of the application being tested. This requirement is in place to ensure that Cypress operates within the same origin and avoids running into browser security restrictions like the Same-Origin Policy (SOP).
Superdomain Restrictions
If you attempt to visit two separate superdomains within the same test, Cypress will throw an error. However, superdomains can be visited separately in different tests. This limitation helps avoid conflicts between domains and maintains the integrity of the tests.
For example, the following will result in an error because it tries to visit two superdomains in one test:
it('navigates', () => {
cy.visit('https://www.cypress.io');
cy.visit('https://docs.cypress.io');
});On the other hand, visiting separate superdomains in different tests will work without issues:
it('navigates', () => {
cy.visit('https://testdocs.com');
cy.visit('https://sampleapp.com'); // error
});
it('navigates', () => {
cy.visit('https://testdocs.com');
});
// splits visiting different origin in another test
it('navigates to new origin', () => {
cy.visit('https://sampleapp.com'); // good
});When Superdomain Restrictions Trigger Errors
Certain actions in your tests can trigger superdomain errors. These include:
- Clicking on an <a> element that points to a different superdomain.
- Submitting a <form> that directs to another superdomain.
- JavaScript redirects (e.g., window.location.href = “…”) to another superdomain.
In any of these cases, Cypress cannot automate the navigation or interaction, and it will throw an exception.
Bypassing Superdomain Limitations with cy.origin()
To overcome the superdomain restriction, Cypress introduced the cy.origin() command, which allows for interaction with different domains within a single test. This command lets you run actions within the context of a different domain, which is particularly useful for cross-origin navigation.
it("navigates", () => {
cy.visit("https://apple.com");
cy.visit("https://google.com");
});To resolve this, use cy.origin() to interact with a second superdomain:
it("navigates", () => {
cy.visit("https://apple.com");
cy.origin("https://google.com", () => {});
});Configuration for cy.origin()
To use cy.origin(), you need to enable the experimentalSessionAndOrigin flag in your cypress.config.js file:
module.exports = {
experimentalSessionAndOrigin: true
};Once enabled, you can seamlessly switch between domains within a single test.
Example: Using cy.origin() with Session Management
Cypress also provides the cy.session() command to cache session data between tests, making it easier to reuse data without re-entering credentials or session information. Here’s an example demonstrating the use of cy.origin() and cy.session() to log in across two different domains:
describe("Two different URLs", function () {
it("Opens URLs", () => {
cy.visit("https://first-url.com");
cy.contains("Home");
cy.visit("https://first-url.com/subpage");
cy.origin("https://second-url.com", () => {
cy.visit("/login");
cy.get("#login_field").type("USERNAME");
cy.get("#password").type("PASSWORD");
cy.get("input").contains("Log In").click();
});
});
});In this example, cy.session() ensures that session data is preserved across the tests, so you don’t need to re-enter login information every time.
Read More: Cypress End-to-End Testing: Tutorial
Cross-origin iframes
Cypress is restricted from automating or interacting with cross-origin iframes, which are embedded iframes from a different domain than the parent page. This limitation arises due to the same-origin policy enforced by browsers, which prevents scripts on one domain from accessing or interacting with content on another domain.
While Cypress cannot natively access these cross-origin iframes, you can still handle such scenarios using workarounds similar to what tools like Selenium employ.
One common method is using window.postMessage() to send and receive messages between the parent page and the iframe, enabling communication and some control over the iframe content.
This workaround allows you to bypass the restrictions of cross-origin policies to interact with and automate actions inside the iframe. However, it does not provide full access to the iframe’s DOM; instead, it establishes a message-passing mechanism between the parent page and the iframe.
Read More: How to run specific test in Cypress
Unsafe Content
By default, Cypress will generate an error if you try to navigate back to an HTTP site while testing an HTTPS site. This behavior contributes to exposing a severe security vulnerability in your application.
Here is an instance of how to access unsafe content:
Suppose you have a test code that looks like this:
''cy.visit('https://myapp.org')'''You set the cookies and save a session on the browser in your application code. Now assume that your application code contains a single unsafe link (or JavaScript redirect).
<html>
<a href="http://myapp.org/page3">Page 3</a>
</html>
The following code will fail in Cypress:
// Test code
cy.visit(?https://myapp.org?)
cy.get('a').click() // will failBy default, browsers will not show insecure content on secure pages. And when the browser followed the href to http://myapp.org/page3, Cypress modified its URL to match https://myapp.org, and the browser declined to show the contents.
This behavior is a security issue in your application that Cypress is exposing to you rather than a flaw in Cypress. If the secure flag on a cookie is not set to true, the cookie will send its contents as clear text to an unsecured URL, making your application susceptible to session hijacking. You could believe that forcing a 301 redirect back to the HTTPS site will fix the issue, but this is untrue.
The original HTTP request leads to the exposure of insecure session information.
You will need to tweak your HTML and JavaScript code to prevent navigation to unsecured HTTP pages and exclusively utilize HTTPS in order to fix this issue. You should also make sure that the secure flag is set to true for cookies.
You can bypass this Cypress restriction by disabling web security if you don’t have access to the code or if there is no other way to get around it.
Also Read: Understanding Cypress HTML Reporter
Port
Cypress enforces a restriction that during a single test, all URLs must use the same port. This limitation aligns with the browser’s same-origin policy, which considers the protocol (HTTP/HTTPS), domain, and port number as part of the origin.
If you attempt to visit URLs with different port numbers within the same test, Cypress will throw an error. For instance, trying to navigate from http://localhost:3000 to http://localhost:4000 in the same test will not be allowed.
This restriction exists because, in the browser’s view, different ports are treated as separate origins, even if the protocol and domain are the same. Allowing tests to switch between ports within a single test could result in issues such as inconsistent session handling or mismatched cookies.
To work within this constraint, ensure that all URLs accessed within a single test use the same port or split tests across different ports.
While Cypress works around browser-imposed security constraints to enable smooth automation, replicating test behavior across various browsers, devices, and operating systems remains crucial for reliability.
BrowserStack lets you run Cypress tests at scale in real user conditions, helping ensure consistent functionality and user experience, no matter where or how your application is accessed.
Workaround for Fixing Cross-Origin Problems
To address the limitations, there are several workarounds available to help fix cross-origin issues and ensure smooth automation across different domains, origins, or ports.
External Navigation
This issue most frequently occurs when you click on a <a> that directs you to another superdomain.
<html>
<a href="https://google.com">Google</a>
</html>
// Test code
cy.visit('http://localhost:5000') // where your web server + HTML is
cy.get('a').click() // hosted browser attempt load googledotCom-CypressErrorsIt is not advised to access a superdomain in your tests that you are not in control of.
Instead, you can check to see if the HREF attribute is accurate.
cy.visit('http://localhost:5000')
cy.get('a').should('have.attr', 'href', 'https://google.com') // no page load!However, if you are concerned about Google.com displaying the correct HTML text, you can directly send a cy.request() to it. CORS and the same-origin policy are NOT constrained by cy.request().
cy.visit('http://localhost:5000')
cy.get('a').then(($a) => {
const url = $a.prop('href')
// make a cy.request to it
cy.request(url).its('body').should('include', '</html>')
})If you still need to go to a separate origin URL, you could choose to disable web security.
Also Read: Understanding Cypress HTML Reporter
Form Submission Redirects
In any case, the browser follows the HTTP(s) request when you submit a standard HTML form.
<html>
<form method="POST" action="/submit">
<input type="text" name="email" />
<input type="submit" value="Submit" />
</form>
</html>
cy.visit('http://localhost:5000')
cy.get('form').submit() // submits the form!You will experience a cross-origin error if your back-end server, which manages the /submit route, performs a 30x redirect to a different superdomain.
// your localhost:5000 server
app.post('/submit', (req, res) => {
// redirect the browser to google.com
res.redirect('https://google.com')
})Single sign-on is a prevalent use case for this. You can then POST to a different server and get redirected somewhere else in this scenario (typically with the session token in the URL).
If that’s the case, you can use cy.request() to test this behavior.
Cypress might skip the first visit entirely and POST directly to your SSO server.
cy.request('POST', 'https://samplesso.com/auth', { username: 'foo', password: 'bar' })
.then((response) => {
// pulls out the location redirect
const loc = response.headers['Location']
const token = parseOutMyToken(loc)
cy.visit('http://localhost:5000?token=' + token)
cy.visit(loc)
})You should think about deactivating web security if you still need to be able to be redirected to your SSO server.
Using JavaScript Redirects
The following is an example of a JavaScript redirect.
window.location.href = 'http://sample.superdomain.com'
As it frequently results from another source, this is arguably the most difficult case to test. You’ll need to ascertain the cause of your JavaScript code’s redirection. The setup may need to be handled elsewhere if you are not logged in.
If you want to use the code to access a different superdomain in the future, you might think about deactivating web security.
Turning off Web Security
If none of the problems can be resolved using the aforementioned solutions, you might want to think about turning off web security.
{
"chromeWebSecurity": false
}Only browsers built on Chrome support disabling web security.
Many well-known websites use a method known as framebusting to thwart clickjacking and iframe hosting. Some of these methods make it difficult for Cypress to operate efficiently. Because of this, the modifyObstructiveCode option is now available and activated by default.
Conclusion
Cypress provides native access to all objects within your application, offering full control over your tests. Whether it’s the window, document, DOM elements, application instances, functions, timers, or service workers, Cypress gives you complete visibility and interaction.
Its built-in stability mechanisms ensure consistent, reliable tests with minimal flakiness, enabling smooth transitions between different origins. Thanks to these advanced features, Cypress helps you seamlessly automate your application with confidence.

