Same-origin policy
You can’t access an <iframe> with different origin using JavaScript, it would be a huge security flaw if you could do it. For the same-origin policy browsers block scripts trying to access a frame with a different origin.
Origin is considered different if at least one of the following parts of the address isn’t maintained:
protocol://hostname:port/...
Protocol, hostname and port must be the same of your domain if you want to access a frame.
NOTE: Internet Explorer is known to not strictly follow this rule, see here for details.
Examples
Here’s what would happen trying to access the following URLs from http://www.example.com/home/index.html
URL RESULT
http://www.example.com/home/other.html -> Success
http://www.example.com/dir/inner/another.php -> Success
http://www.example.com:80 -> Success (default port for HTTP)
http://www.example.com:2251 -> Failure: different port
http://data.example.com/dir/other.html -> Failure: different hostname
https://www.example.com/home/index.html:80 -> Failure: different protocol
ftp://www.example.com:21 -> Failure: different protocol & port
https://google.com/search?q=james+bond -> Failure: different protocol, port & hostname
Workaround
Even though same-origin policy blocks scripts from accessing the content of sites with a different origin, if you own both the pages, you can work around this problem using window.postMessage and its relative message event to send messages between the two pages, like this:
-
In your main page:
const frame = document.getElementById('your-frame-id'); frame.contentWindow.postMessage(/*any variable or object here*/, 'https://your-second-site.example');The second argument to
postMessage()can be'*'to indicate no preference about the origin of the destination. A target origin should always be provided when possible, to avoid disclosing the data you send to any other site. -
In your
<iframe>(contained in the main page):window.addEventListener('message', event => { // IMPORTANT: check the origin of the data! if (event.origin === 'https://your-first-site.example') { // The data was sent from your site. // Data sent with postMessage is stored in event.data: console.log(event.data); } else { // The data was NOT sent from your site! // Be careful! Do not use it. This else branch is // here just for clarity, you usually shouldn't need it. return; } });
This method can be applied in both directions, creating a listener in the main page too, and receiving responses from the frame. The same logic can also be implemented in pop-ups and basically any new window generated by the main page (e.g. using window.open()) as well, without any difference.
Disabling same-origin policy in your browser
There already are some good answers about this topic (I just found them googling), so, for the browsers where this is possible, I’ll link the relative answer. However, please remember that disabling the same-origin policy will only affect your browser. Also, running a browser with same-origin security settings disabled grants any website access to cross-origin resources, so it’s very unsafe and should NEVER be done if you do not know exactly what you are doing (e.g. development purposes).
- Google Chrome
- Mozilla Firefox
- Safari
- Opera: same as Chrome
- Microsoft Edge: same as Chrome
- Brave: same as Chrome
- Microsoft Edge (old non-Chromium version): not possible
- Microsoft Internet Explorer
Blocked a frame with origin from accessing a cross-origin frame is an error that you’ll see in the Google Chrome console when your code violates the “Same-origin Policy” (SOP). This article will explain why you’re seeing this error and how you can get rid of it.
Throughout this article, we’ll explain the fundamentals of “Same-origin Policy browser” restrictions and why web browsers like Google Chrome implement it. Now, you’re about to learn a lot, so grab your notebook, and let’s explain everything that you need to know about it.
Contents
- Why Did Google Chrome Block a Cross-origin Frame? Major Culprits
- – You Violated the Same-origin Policy (Sop)
- How To Fix the Cross-origin Error in Google Chrome? The Best Solutions
- – Host Your Code on a Server
- – Use “window.postmessage()” for Communication
- – Disable Same-origin Policy in Google Chrome
- Conclusion
Why Did Google Chrome Block a Cross-origin Frame? Major Culprits
Google Chrome blocked a “cross-origin frame” because you violated the Same-origin Policy. This policy is a security measure in Chrome and other web browsers that prevents a site from loading the content of another site if they don’t have the same origin i.e, the same port, protocol, and host.
– You Violated the Same-origin Policy (Sop)
When you violate the Same-origin Policy, that’s when Google Chrome will show the “uncaught DOMexception” that it blocked a frame. This error message means a code on your web page is trying to access a frame from another origin.
For example, the first part of the following HTML belongs to “test.html”, and it’s adding the “calculate_factorial.html” using an “<iframe>”. When you run the code, you can’t calculate the factorial using the form because it violates the Same-origin Policy.
<head>
<script>
function get_factorial(number){
var number_factorial = 1;
for (;number >0; number–) number_factorial *= number;
return number_factorial;
}
</script>
</head>
<body>
<frame>
<iframe id=”my-iframe-id” src=”calculate_factorial.html” height=”200″ width=”300″></iframe>
</frame>
</body>
<!– Code for “calculate_factorial.html” –>
<head>
<script>
function button_calc_factorial(){
let to_be_factorial = document.factorial_form.factorial_form_value.value;
let to_be_factorial_result = document.factorial_form.factorial_form_result;
try {
if (window.top.get_factorial == null)
throw “The factorial function does not exist.”;
if (to_be_factorial === “” || to_be_factorial.trim().length === 0)
throw “_Value cannot be empty.”;
if (isNaN(to_be_factorial))
throw “_You did not enter a number.”;
if (to_be_factorial < 0)
throw “_Only positive numbers are allowed.”;
to_be_factorial_result.value = window.top.get_factorial(document.factorial_form.factorial_form_value.value);
}
catch(exception){
if (typeof(exception) == “string”){
if (exception.charAt(0) == “_”){
alert(exception.substr(1));
to_be_factorial.focus();
to_be_factorial.select();
}
else console.log(exception);
}
else console.log(“Error: ” + exception.message);
}
}
</script>
</head>
<body>
<form action=”” name=”factorial_form”>
<input type=”text” name=”factorial_form_value” size=”3″ /> in factorial is:
<input type=”text” name=”factorial_form_result” size=”25″ /><br/>
<input type=”button” value=”Calculate Factorial” onclick=”button_calc_factorial()” />
</form>
</body>
How To Fix the Cross-origin Error in Google Chrome? The Best Solutions
You can fix the cross-origin error that appears in Google Chrome if you host your code on a server or use “window.postMessage()” to send messages between a parent document and a child iframe. If you’re in a development environment, you can disable the Same-origin Policy before you open Chrome.
– Host Your Code on a Server
We accessed our previous code example using the “file:///” protocol, and that’s why the Same-origin Policy blocked JavaScript from accessing the iframe.
The first solution is to host the code on a server, and by doing this, the JavaScript and the “< iframe>” will have the same origin, and your web browser will allow the communication. To host the code on a server, do the following:
- Download XAMPP from Apache Friends.
- Install XAMPP and launch the XAMPP control panel.
- Locate the “htdocs” folder in your XAMPP installation.
- Create a new folder in the “htdocs” folder and move your HTML code to this folder.
- Start the Apache server via the XAMPP control panel.
- Navigate to your project folder using “http://localhost/your_project_folder”.
- Try the calculator, and it will work without a cross-origin error.
Alternatively, you can host the code on GitHub Pages. To do this, use the following steps:
- Sign up for a GitHub account.
- Log in to your account and create a new repository.
- Upload your files to this new repository.
- Navigate to the “Settings” tab of the repository.
- Scroll down and turn on “GitHub Pages”.
- Wait for the process to complete, and you’ll get a GitHub Pages URL that points to a live version of the files in your repository.
- Access the main page that’s loading the calculator via the “< iframe>” and it should work.
– Use “window.postmessage()” for Communication
The “window.postMessage()”, can allow you to safely pass information between documents that have the same or different origins (cross-origin). Unlike the previous code that you had to host on a server for it to work, with “window.postMessage()”, the code will work with and without a server.
For example, the following contains code for two HTML documents; you can fill the form in “parent_frame.html” and it will show in “child_frame.html”. If you’re running this without a server, the origin will be “null”, else it will be the address of the web server.
<head>
<title>Parent Frame HTML</title>
</head>
<body>
<form id=”msg_form” action=”/”>
<input type=”text” id=”your_msg” value=”Your message”>
<input type=”submit” value=”postMessage”>
</form>
<frame>
<iframe id=”my-iframe-id” src=”child-frame.html” height=”200″ width=”300″></iframe>
</frame>
</body>
<script>
window.onload = function () {
let my_iframe = document.querySelector(“#my-iframe-id”).contentWindow;
let form = document.querySelector(“#msg_form”);
let your_msg = document.querySelector(“#your_msg”);
your_msg.select();
form.onsubmit = function () {
// The second value of postMessage should the
// name of your website. Here, we pass “*” so that
// it can work on your computer.
my_iframe.postMessage(your_msg.value, “*”);
return false;
};
};
</script>
<!– Code for “child_frame.html” –>
<head>
<meta charset=”utf-8″>
<Title>Child Frame HTML</title>
<script>
function displayMessage_NOT_SECURE (event) {
// This function is not safe. Use it on your computer only.
// A safer version will validate the origin
let message = “New message: ” + event.data + ” from ” + event.origin;
document.getElementById(“inbox”).innerHTML = message;
}
if (window.addEventListener) {
window.addEventListener(“message”, displayMessage_NOT_SECURE, false);
}else {
window.attachEvent(“onmessage”, displayMessage_NOT_SECURE);
}
</script>
</head>
<body>
<p id=”inbox”>You have no new message!</p>
</body>
– Disable Same-origin Policy in Google Chrome
“Disabling same-origin” in Google Chrome will allow cross-origin communications, but you should only do it for testing purposes.
There are two commands that you can use to disable the Same-origin Policy in Google Chrome, and the steps below show you how to use them on Microsoft Windows:
- Use “Windows key” and “R” on your keyboard to launch the “Run” dialog box.
- Disable the Same-origin in older versions of Chrome: chrome.exe –user-data-dir=”C:/dev session” –disable-web-security
- Disable the Same-origin Policy in newer versions of Chrome (version 103+): chrome.exe –disable-site-isolation-trials –disable-web-security –user-data-dir=”C:/dev session”
When you execute either of the previous commands, you’ll start Chrome in a confined sandbox, and you’ll see a warning that you can ignore. Also, you’ll find all the data for this isolated Chrome in the folder “dev session” under the “C:/” drive, so when you’re done it’s best to delete this folder.
Finally, you can now run the first code example in this article (without a server), and it will work because cross-origin communication is now allowed by default.
Conclusion
This article explained why Google Chrome and other web browsers block cross-origin communications and what you can do to allow or prevent the error. The following are the highlights of our discussion:
- The Same-origin Policy is why Google Chrome blocked your JavaScript code from accessing a cross “origin frame” on your web page.
- You can use “windows.postMessage()” for cross-origin communications with and without a server.
- If Google Chrome blocks your JavaScript code for violating the Same-origin Policy, host your code on a web server (local or GitHub Pages).
- For testing purposes, you can disable the Same-origin Policy in Chrome using the “–disable-site-isolation-trials” and “–disable-web-security” flags.
- When you’re using “windows.postMessge()”, always validate the origin of the message before using it on your web page.
Now, you know how cross-origin communications work and how to use it in Google Chrome. Use your new knowledge to become a better developer and teach others about the Same-origin “Policy browser” restrictions.
- Author
- Recent Posts
Your Go-To Resource for Learn & Build: CSS,JavaScript,HTML,PHP,C++ and MYSQL. Meet The Team
![]()
Здравствуйте! Пытаюсь получить доступ к document в ifrmae, содержащем видео youtube, и сделать какие либо действия на странице (например, удалить кнопку пуск видео). Я испольхую iframe.contentWindow.document и от туда получаю элементы через querySelectorAll. Но возвразается ошибка:
Uncaught DOMException: Blocked a frame with origin «null» from accessing a cross-origin frame.
at HTMLIFrameElement.iframe.onload (file:///C:/Users/%D0%96%D0%B5%D0%BD%D1%8F/Desktop/%D0%92%D0%B0%D0%B6%D0%BD%D1%8B%D0%B5%20%D0%B4%D0%BE%D0%BA%D1%83%D0%BC%D0%B5%D0%BD%D1%82%D1%8B/JavaScriptProjects/test.html:6:35)
Вот сам код:
<body>
<iframe width="560" height="315" src="https://www.youtube.com/embed/6abPOYMDDgM" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen id="iframe"></iframe>
</body>
<script>
iframe.onload = function(e){
console.log(iframe.contentWindow.document.getElementsByClassName("style-scope")[0]);
}
</script>
-
Вопрос заданболее трёх лет назад
-
19435 просмотров
Пригласить эксперта
Так как страница, которая загружается во фрейме, находится на другом домене, то у вас нет прав для доступа и редактирования этой страницы.
Что бы была возможность редактировать страница, которая загружает фрейм, и которая загружается во фрейме, должны быть на одном домене. Иначе нужно проксировать через свой сервер и домен, вот одна из статей как такое делать
Никак.
Вам русским по белому написано, что так нельзя.
А вы просто скройте эту кнопку элементами родительского окна, тогда пользователь
до нее не дотянется, потому что не увидит.
-
Показать ещё
Загружается…
21 июн. 2023, в 19:05
2000 руб./за проект
21 июн. 2023, в 19:05
1000 руб./в час
21 июн. 2023, в 19:04
2000 руб./за проект
Минуточку внимания
Политика безопасности одинакового происхождения
Вы не можете получить доступ к <iframe> с помощью Javascript, это может стать огромным недостатком безопасности, если вы сможете это сделать. Для политики того же происхождения браузеры блокируют скрипты, пытающиеся получить доступ к кадру с другим происхождением.
Происхождение считается другим, если не поддерживается хотя бы одна из следующих частей адреса:
<protocol>://<hostname>:<port>/path/to/page.html
Протокол, имя хоста и порт должны совпадать с вашим доменом, если вы хотите получить доступ к фрейму.
Примеры
Здесь произойдет попытка доступа к следующим URL-адресам из http://www.example.com/home/index.html
URL RESULT
http://www.example.com/home/other.html -> Success
http://www.example.com/dir/inner/another.php -> Success
http://www.example.com:80 -> Success (default port for HTTP)
http://www.example.com:2251 -> Failure: different port
http://data.example.com/dir/other.html -> Failure: different hostname
https://www.example.com/home/index.html.html -> Failure: different protocol
ftp://www.example.com:21 -> Failure: different protocol & port
https://google.com/search?q=james+bond -> Failure: different hostname & protocol
Обход
Несмотря на то, что политики одного и того же происхождения блокируют доступ к контенту сайтов с другим происхождением, , если у вас есть обе страницы, вы можете обойти эту проблему, используя window.postMessage и его относительное событие message для отправки сообщений между двумя страницами, например:
-
На главной странице:
var frame = document.getElementById('your-frame-id'); frame.contentWindow.postMessage(/*any variable or object here*/, '*'); -
В
<iframe>(содержится на главной странице):window.addEventListener('message', function(event) { // IMPORTANT: Check the origin of the data! if (~event.origin.indexOf('http://yoursite.com')) { // The data has been sent from your site // The data sent with postMessage is stored in event.data console.log(event.data); } else { // The data hasn't been sent from your site! // Be careful! Do not use it. return; } });
Этот метод может применяться в в обоих направлениях, создавая слушателя на главной странице и получая ответы от фрейма. Та же логика также может быть реализована во всплывающих окнах и в основном в любом новом окне, создаваемом главной страницей (например, используя window.open()) без каких-либо различий.
Отключение политики одного и того же происхождения в вашем браузере
Уже есть хорошие ответы на эту тему (я просто нашел их googling), поэтому для браузеров, где это возможно, я свяжу относительный ответ. Однако помните, что отключение политики одного и того же происхождения (или CORS) повлияет только на ваш браузер. Кроме того, при запуске браузера с отключенными настройками безопасности с одним и тем же источником доступ к ресурсам кросс-источника запрещен любым сайтом, поэтому он очень опасен и должен выполняться только для целей разработки.
- Google Chrome
- Mozilla Firefox
- Apple Safari: невозможно, только CORS.
- Опера: невозможно.
- Microsoft Edge: невозможно.
- Microsoft Internet Explorer: невозможно, только CORS.
Solution 1
Same-origin policy
You can’t access an <iframe> with different origin using JavaScript, it would be a huge security flaw if you could do it. For the same-origin policy browsers block scripts trying to access a frame with a different origin.
Origin is considered different if at least one of the following parts of the address isn’t maintained:
protocol://hostname:port/...
Protocol, hostname and port must be the same of your domain if you want to access a frame.
NOTE: Internet Explorer is known to not strictly follow this rule, see here for details.
Examples
Here’s what would happen trying to access the following URLs from http://www.example.com/home/index.html
URL RESULT
http://www.example.com/home/other.html -> Success
http://www.example.com/dir/inner/another.php -> Success
http://www.example.com:80 -> Success (default port for HTTP)
http://www.example.com:2251 -> Failure: different port
http://data.example.com/dir/other.html -> Failure: different hostname
https://www.example.com/home/index.html:80 -> Failure: different protocol
ftp://www.example.com:21 -> Failure: different protocol & port
https://google.com/search?q=james+bond -> Failure: different protocol, port & hostname
Workaround
Even though same-origin policy blocks scripts from accessing the content of sites with a different origin, if you own both the pages, you can work around this problem using window.postMessage and its relative message event to send messages between the two pages, like this:
-
In your main page:
const frame = document.getElementById('your-frame-id'); frame.contentWindow.postMessage(/*any variable or object here*/, 'http://your-second-site.com');The second argument to
postMessage()can be'*'to indicate no preference about the origin of the destination. A target origin should always be provided when possible, to avoid disclosing the data you send to any other site. -
In your
<iframe>(contained in the main page):window.addEventListener('message', event => { // IMPORTANT: check the origin of the data! if (event.origin.startsWith('http://your-first-site.com')) { // The data was sent from your site. // Data sent with postMessage is stored in event.data: console.log(event.data); } else { // The data was NOT sent from your site! // Be careful! Do not use it. This else branch is // here just for clarity, you usually shouldn't need it. return; } });
This method can be applied in both directions, creating a listener in the main page too, and receiving responses from the frame. The same logic can also be implemented in pop-ups and basically any new window generated by the main page (e.g. using window.open()) as well, without any difference.
Disabling same-origin policy in your browser
There already are some good answers about this topic (I just found them googling), so, for the browsers where this is possible, I’ll link the relative answer. However, please remember that disabling the same-origin policy will only affect your browser. Also, running a browser with same-origin security settings disabled grants any website access to cross-origin resources, so it’s very unsafe and should NEVER be done if you do not know exactly what you are doing (e.g. development purposes).
- Google Chrome
- Mozilla Firefox
- Safari
- Opera
- Microsoft Edge: not possible
- Microsoft Internet Explorer
Solution 2
Complementing Marco Bonelli’s answer: the best current way of interacting between frames/iframes is using window.postMessage, supported by all browsers
Solution 3
Check the domain’s web server for http://www.<domain>.com configuration for X-Frame-Options
It is a security feature designed to prevent clickJacking attacks,
How Does clickJacking work?
- The evil page looks exactly like the victim page.
- Then it tricked users to enter their username and password.
Technically the evil has an iframe with the source to the victim page.
<html>
<iframe src='victim_domain.com'/>
<input id="username" type="text" style="display: none;"/>
<input id="password" type="text" style="display: none;"/>
<script>
//some JS code that click jacking the user username and input from inside the iframe...
<script/>
<html>
How the security feature work
If you want to prevent web server request to be rendered within an iframe add the x-frame-options
X-Frame-Options DENY
The options are:
- SAMEORIGIN //allow only to my own domain render my HTML inside an iframe.
- DENY //do not allow my HTML to be rendered inside any iframe
- «ALLOW-FROM https://example.com/» //allow specific domain to render my HTML inside an iframe
This is IIS config example:
<httpProtocol>
<customHeaders>
<add name="X-Frame-Options" value="SAMEORIGIN" />
</customHeaders>
</httpProtocol>
The solution to the question
If the web server activated the security feature it may cause a client-side SecurityError as it should.
Solution 4
For me i wanted to implement a 2-way handshake, meaning:
— the parent window will load faster then the iframe
— the iframe should talk to the parent window as soon as its ready
— the parent is ready to receive the iframe message and replay
this code is used to set white label in the iframe using [CSS custom property]
code:
iframe
$(function() {
window.onload = function() {
// create listener
function receiveMessage(e) {
document.documentElement.style.setProperty('--header_bg', e.data.wl.header_bg);
document.documentElement.style.setProperty('--header_text', e.data.wl.header_text);
document.documentElement.style.setProperty('--button_bg', e.data.wl.button_bg);
//alert(e.data.data.header_bg);
}
window.addEventListener('message', receiveMessage);
// call parent
parent.postMessage("GetWhiteLabel","*");
}
});
parent
$(function() {
// create listener
var eventMethod = window.addEventListener ? "addEventListener" : "attachEvent";
var eventer = window[eventMethod];
var messageEvent = eventMethod == "attachEvent" ? "onmessage" : "message";
eventer(messageEvent, function (e) {
// replay to child (iframe)
document.getElementById('wrapper-iframe').contentWindow.postMessage(
{
event_id: 'white_label_message',
wl: {
header_bg: $('#Header').css('background-color'),
header_text: $('#Header .HoverMenu a').css('color'),
button_bg: $('#Header .HoverMenu a').css('background-color')
}
},
'*'
);
}, false);
});
naturally you can limit the origins and the text, this is easy-to-work-with code
i found this examlpe to be helpful:
[Cross-Domain Messaging With postMessage]
Solution 5
There is a workaround, actually, for specific scenarios.
If you have two processes running on the same domain but different ports, the two windows can interact without limitations. (i.e. localhost:3000 & localhost:2000). To make this work, each window needs to change their domain to the shared origin:
document.domain = 'localhost'
This also works in the scenario that you are working with different subdomains on the same second-level domain, i.e. you are on john.site.com trying to access peter.site.com or just site.com
document.domain = 'site.com'
By explicitily setting document.domain; the browser will ignore the hostname difference and the windows can be treated as coming from the ‘same-origin’. Now, in a parent window, you can reach into the iframe: frame.contentWindow.document.body.classList.add('happyDev')
Comments
-
I am loading an
<iframe>in my HTML page and trying to access the elements within it using Javascript, but when I try to execute my code, I get the following error:SecurityError: Blocked a frame with origin "http://www.<domain>.com" from accessing a cross-origin frame.Can you please help me to find a solution so that I can access the elements in the frame?
I am using this code for testing, but in vain:
$(document).ready(function() { var iframeWindow = document.getElementById("my-iframe-id").contentWindow; iframeWindow.addEventListener("load", function() { var doc = iframe.contentDocument || iframe.contentWindow.document; var target = doc.getElementById("my-target-id"); target.innerHTML = "Found it!"; }); });
