I'm not familiar with Javascript, but I want to know what can't be done in this steps in order to bypass SOP and extract sensitive data :

  1. set the tag <script src="https://facebook.com/messages"></script>
  2. the browser retrives the content of https://facebook.com/messages
  3. the browser, thinking it's a JS code, put the HTML content inside <script> tag
  4. another piece of JS code get the content of the <script> tag and send it to attacker's server

Because step 4 is impossible. Not just because of the same-origin policy, but because there's simply no way to retrieve the content of a script tag via JavaScript.

There's HTMLScriptElement.text, but that only retrieves the text between the script start and end tags. It can't retrieve content loaded via the src attribute.

That said, there actually is a way script tags can be used to bypass the same-origin policy under limited circumstances. If you load a script from another domain and execute it, then you might be able to derive some information from the side-effects of that execution. That's how JSONP works. This isn't usually a security issue though, as most JSONP endpoints are designed with cross-origin access in mind, and most other types of scripts are static assets that do not contain sensitive information.


As mentionnet by @Ajedi32 there is no function to retrieve the content of a script dynamically loaded.

However, you might still be able to retrieve some of the content if the ressource is valid javascript. This attack is called xssi.

The HTTP headers Content-Type and X-Content-Type-Options are used to prevent this type of attack :

  • Content-Type specify which kind of content the document is. For a webpage, it usually should be text/html and application/javascript for a script.
  • X-Content-Type-Options: nosniff prevent the browser to try to change the MIME type of the ressource. So even if a ressource is loaded in a script tag and is valid javascript, if the Content-type is text/html it won't execute.

If you take a look at https://facebook.com/messages headers, you will find both headers.

  1. the browser, thinking it's a JS code, put the HTML content inside <script> tag

When the browser loads a script referenced via <script src=...>, it doesn't actually add its content to the DOM. So document.scripts[0].textContent would just give you an empty string.

Instead, the browser tries to execute the referenced script as JS, and in your example, this fails in all browsers because the HTML document at https://facebook.com/messages isn't valid JS, resulting in a syntax error. Even if it was somehow valid JS, the document is served with a MIME type of text/html and a X-Content-Type-Options: nosniff header, so your browser will refuse to execute it as a script.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.