8

I am building small offline web app using HTML and JavaScript. CSV file is used to store data.

To read CSV (using jquery-csv library) file I use following code.

<script>
    $(document).ready(function(){

        var filepath = 'data.csv';
        var data_string = $.get(filepath);
    });

</script>

But I can't read it because of following error.

XMLHttpRequest cannot load file:///C:/Users/Nimal/Desktop/javascript-csv/data.csv. Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, https


Then I could learned about same origin policy concept.

Then, I found many related articles from here.

  1. "Cross origin requests are only supported for HTTP." error when loading a local file
  2. XMLHttpRequest cannot load file. Cross origin requests are only supported for HTTP
  3. Ways to circumvent the same-origin policy

From Wikipedia,

In computing, the same-origin policy is an important concept in the web application security model. Under the policy, a web browser permits scripts contained in a first web page to access data in a second web page, but only if both web pages have the same origin.

But I have a problem.

If I use <img src="abc.jpg"> I can load the image.

Why is there an exception for images?

How all we can load images, but we can't load other file types?

I thought same origin policy should apply all file types including images.

Or have I understand same-orgin-policy wrongly?

Suraj Jain
  • 4,463
  • 28
  • 39
  • 4
    I like your name – Peter Haddad Sep 14 '17 at 05:54
  • @PeterHaddad Thank You. :-) – I am the Most Stupid Person Sep 14 '17 at 05:55
  • The way `$.get(filepath)` works is different than requesting an image within HTML. The problem is that you are not using a web server to serve your page so requesting a local file from local file with `$.get()` will not work. I would also suggest using [`localStorage`](https://www.w3schools.com/html/html5_webstorage.asp) instead of CSV files. – mnewelski Sep 14 '17 at 05:58
  • You would have to embed your csv data in your document directly, e.g as a string in a js script. Or if it's for personal uses, you can configure your browser so that it accepts requests on `file://` protocol. – Kaiido Sep 14 '17 at 06:06
  • 1
    Possible duplicate of [Loading local files with Javascript without a web server](https://stackoverflow.com/questions/19902538/loading-local-files-with-javascript-without-a-web-server) – Kaiido Sep 14 '17 at 06:10
  • @Kaiido This is not a duplicate question for it... I am asking really really different question. I am not asking how can I load file with JS locally. Please read question before mark as duplicate questions. – I am the Most Stupid Person Sep 14 '17 at 07:05
  • So what's the question exactly? You want a solution to your problem or you just want to know why different browsers have decided to set more restrictive security features on XHR than on `` or `` etc.? Either a dupe, either primarily opinion based, your call. – Kaiido Sep 14 '17 at 07:08
  • Yes. I just wanted know the difference how can I load image, but no the files. – I am the Most Stupid Person Sep 14 '17 at 07:10
  • Well to know that you would have to ask browsers' dev teams why they made these choice. Note that it does evolve with the time, FF was one of the more restrictive a few years ago, while now it does accept any request made in the same folder and subfolders. The only general answer would be *This all goes done to how much confident browser vendors are of their security measures.* – Kaiido Sep 14 '17 at 07:15
  • 1
    @Kaiido The person asked a genuine question, as to why images are not restricted, and you are marking it as duplicate, or as an opinion based, seriously why you people do that. It is clearly a good question. – Suraj Jain Oct 02 '17 at 07:11
  • @SurajJain I first voted as duplicate because before your edit the question was not clearly asking for a *why* or an *how to avoid it* and now because of your edit, it is asking both... (You could have edited its title to avoid this ambiguity I you felt so btw). And I then said it was opinion based because there is no way to know why some browsers do allow some file types and not others since the specs don't say anything about it, and browser's rules do change overtime time and thus, these rules are only tied by decisions individuals do over time. – Kaiido Oct 02 '17 at 15:26

1 Answers1

3

To comprehend the problem, you have to understand the same origin policy (hereafter called as sop) and how it's being handled. It is an important concept when writing an application that allows users to browse the world wide web. Before that concept, many security violations has occurred.

In short, you can see sop as a tuple with three elements: (scheme,host,port).

When you are visiting a page with a script that obtains information from multiple URLs. The tuple on this page is eg. tuple_main. If the script loads content from another URL, a tuple is generated from the URL: tuple_request. Two situations can occur here:

1) tuple_main == tuple_request
 ===> OK  => get content

2) tuple_main != tuple_request
 ===> NOK => do not get content and show that sop is being violated.

Initially, the sop is invented to protect content in your DOM against malicious adversaries. Throughout the years, this got broadened to secure other parts of the information that the browser is handling. A most notable example is the global javascript variables. 10+ years ago, developers started to store sensible information in their javascript as var foo in global space. It was easy for malicious adversaries to get it and abuse it...

Other extensions were added to secure Adobe Flash, MS Silverlight plugins, javascript mechanisms (like XMLHttpRequest), ect ... throughout the years. The sop ensures that the content of the webpage you are visiting does not leak to malicious adversaries (mostly by XSS)

Now, your question was initially (which is a description of the problem):

To read CSV (using jquery-csv library) file I use following code.

<script>
    $(document).ready(function(){

      var filepath = 'data.csv';
      var data_string = $.get(filepath);
    });
</script>

But I can't read it because of following error.

XMLHttpRequest cannot load file:///C:/Users/Nimal/Desktop/javascript-csv/data.csv. Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, https

Since the tuple is different, you are violating the sop. So you will get this message of course.

But your main question is

If I use <img src="abc.jpg"> I can load the image.

Why is there an exception for images?

To answer that, another concept and (eh ...) some history (old IE ages) are used here. To give developers means to use resources from a different sop location, a cross-origin concept is added. From this concept, there are three mechanisms (source):

  1. Cross-origin writes.

Here, we are talking about links to another sites, HTTP redirects and form submissions.

  1. Cross-origin reads

"Reading from another source" which is discouraged. But you can work-around it by embedding it. This leads us to the last mechanism:

  1. Cross-origin embedding

This is what you were doing when loading the csv file. This mechanism is added to allow web developers to use content from other sources such as stylesheets, scripts, images... You can see this as an "exception to the Same origin Policy principle".

If you are building a web page and you want to use jQuery (a script), then the browser will load that script. But embedded. You can run the script, but not read the content of the <script> tag.

That's what happens here at images. When loading the image by <img> tag, the browser is only reading the image. It cannot access the content (the byte information behind the file name that describes the whole image). Therefore, you can see the image on the page you're viewing.

If you want to load the image in a <canvas> element, then it will not be able to do so because it violates the rules. Your script is trying to access the byte information behind that file name. That is not allowed.

Why was I talking about IE history? Well, long time ago, IE was a mainstream browser. Since many companies started to "come online" they have build applications that uses IE for their business tasks. For example a financial employee was using IE to have a monthly summary of sales.

But the same origin policy was not extended in the way we have now. Loading sources from other domains were "not an issue". Companies started to setup websites with third party scripts (Ext js was used heavily back then), third party stylesheets and "third party" images. There are images on the world wide web that are free-to-use (and hosted by sites like tinypic, imageshack, ...). Lots of companies have used these images for their websites.

If those exceptions were not implemented, then lots of legacy websites would break. Images would not load. Scripts would not run. The economical cost of fixing it would be huge. So to anticipate that, this embedding mechanism got added.

A personal note: I am kinda happy that this exception exists otherwise maintaining a website would be a developer nightmare. If the sop is strict as intended, then you have to download the scripts and images and host it from your server. By this, your website can access these and use these. If a script got an update, you have to download it and overwrite your local script...

You are trying to read the content of the csv file which violates the security measurements behind the embedding mechanism.. Since it contains sensible information that should not be leaked to malicious adversaries, the browser informs you that you cannot load it. Just to prevent you for some security problems.

If you want to work locally, you have to use CORS. Or launch the browser without sop restrictions (albeit I don't recommend it).

Community
  • 1
  • 1
KarelG
  • 5,176
  • 4
  • 33
  • 49
  • 2
    That's a nice story, but mostly wrong. In OPs case, the tuple *scheme host port* is not violated at all. He loads his file through an relative path, so the browser will use the same scheme host and port to do the request. This is why you can do the exact same XHR on FF... SOP over `file://` protocol is an per browser implementation security rule. Some versions will be stricter than others, and only browser's devs know why they prefer to be strict or not. – Kaiido Oct 02 '17 at 15:48
  • 1
    Also on most current browsers, if you did load your page through http (e.g localhost) and tried to access an image through the `file://` protocol, then your `` would throw an error so your point about *reading* is also off (btw how do they display it without gaining access to the bytes... they don't give js the access, but they've got it ;-)). And less importantly, you can load and draw cross-origin images on a canvas, but you can't export it (*load* is a bit ambiguous in your text. – Kaiido Oct 02 '17 at 15:54
  • Nicely stated. Would you mind clarifying the difference between read and embedding mechanisms? – wlnirvana Nov 11 '20 at 03:49
  • Hmm, if the SOP were as strict as originally intended, we wouldn't have to worry about "leeching" as webhosts: images would be as secure as bank pages by default — opt-in to remote access, when appropriate – JamesTheAwesomeDude Mar 13 '21 at 01:50