Security



JavaScript brings many security issues while running in a browser. Browsers download pages and execute JavaScript in the background. Some actions must be limited to prevent client data from being stolen, read or destroyed. Basically, browsers must prohibit JavaScript from accessing client files directly.

However, there are still many considerable security issues. For instance, you can display a message in the status bar of the old browser; but this produces hidden troubles. In some conditions, one can fake a message in the status bar to deceive users. For instance, the status bar shows the linked URL when the mouse point hovers over a hyperlink; if JavaScript alters the URL, users will be misled. For example:  
<html>
  <head>
    <script type="text/javascript">
        window.onload = function() {
            document.getElementById('link').onmouseover = function() {
                window.defaultStatus = 'https://openhome.cc';
            };
        };
    </script>
  </head>
  <body>
      <a id="link" href="http://caterpillar.onlyfun.net">caterpillar</a>
  </body>
</html>
Some browsers have discarded the defaultStatus property; but Internet Explorer still allows it. Nevertheless, when the mouse point hovers over a hyperlink, the status bar shows the URL even in Internet Explorer because of security constraint; only if the mouse point leaves the hyperlink, the defaultStatus text is shown. The status bar has security concern, so some modern browsers don't include a status bar, such as Firefox 4, IE9, Chrome, etc.

JavaScript can open a new window; but the opened window has minimum size limitation. This is a natural and right consideration. Users won't notice the opened window if it's too small; the invisible window could be used to execute malicious code.

Due to security considerations, if the type attribute of the input element is "file", browsers will ignore the value attribute; even it's assigned by JavaScript. Users must choose a file by their own hand.

Then, how to clear the selected file just one click on a button? Using JavaScript to set the value attribute an empty string is useless; the basic idea is to ask the browser to create a new file input element. For example: 
<html>
  <head>
    <script type="text/javascript">
        window.onload = function() {
            document.getElementById('clear').onclick = function() {
                var fileupload = document.getElementById('fileupload');
                fileupload.innerHTML = fileupload.innerHTML;
            };
        };
    </script>
  </head>
  <body>
      <div id="fileupload"><input name="upload" type="file"></div>
      <button id="clear">Clear</button>
  </body>
</html>

In the above example, if you select a file and click the Clear button, the fileupload.innerHTML will be '<input name="upload" type="file" value="...">'. When you assign it back to fileupload.innerHTML, browsers will parse the HTML and ignore the value property; a new element for '<input name="upload" type="file">' will be created. From users' point of view, the display looks like clearing the content of the input element.

As another example, you can use files.item(0).size to get the file size in Firefox and Chrome. For example: 
<html>
  <head>
    <script type="text/javascript">
        window.onload = function() {
            document.getElementById('size').onclick = function() {
                var size = document.getElementById('upload')
                                   .files.item(0).size;
                document.getElementById('console')
                        .innerHTML = 'Size: ' + size;
            };
        };
    </script>
  </head>
  <body>
      <input id="upload" name="upload" type="file"><br>
      <button id="size">Size</button><br>
      <span id="console"></span>
  </body>
</html>

In Internet Explorer, you cannot use the above method, but in the past (Internet Explorer 6 or before), you can create the Image or ActiveXObject (Scripting.FileSystemObject) instance to get the file size. Because of security concern, however, they don't work in the new version of Internet Explorer. Take creating the Image instance for example. In the past, you can...
<html>
  <head>
    <script type="text/javascript">
        window.onload = function() {
            document.getElementById('size').onclick = function() {
                var img = new Image();
                img.onload = function() {
                    var size = this.fileSize;
                    document.getElementById('console')
                            .innerHTML = 'Size: ' + size;
                };
                img.src = document.getElementById('upload').value;
            };
        };
    </script>
  </head>
  <body>
      <input id="upload" name="upload" type="file"><br>
      <button id="size">Size</button><br>
      <span id="console"></span>
  </body>
</html>

The above way doesn't work now. This way, actually, is downloading the specified file. If it's allowed, one can specify any file in the client, load it into the Image instance and upload to a server. In Internet Explorer, there's no ready-made solution to get the file size. You can just use Flash or else for instead.

A similar restriction is happening on the iframe element. For example:  
<html>
    <head>
        <script type="text/javascript">
            window.onload = function() {
                alert(window.frames['page'].document.body.innerHTML);
            };
        </script>
    </head>
    <body>
        <iframe id="page" name="page" 
                src="https://openhome.cc"></iframe>
    </body>
</html>

You can use JavaScript to get the page content loaded by the iframe element but the page must have the same origin as this document. Without this limitation, one can specify the src attribute an URL of your intranet, get the content of the iframe element and upload it to a server. That is; I can steal the content located in your intranet.

If you use Ajax, the asynchronous object has the same limitation. It can get another page only if the page has the same origin as the document making asynchronous requests; pages from different origin are not available.

This is called the same origin policy. The same origin means that; two documents come from the same domain name, application layer protocol, and port number. Only if one document has the same origin as the document running the script, the asynchronous request can retrieve its content. If any one of the domain name, protocol and port number is different, the content is not available. For example, if the origin of the current document is http://openhome.cc:80/Gossip/demo.html, the following documents are considered as different origins.
  • https://openhome.cc:80/Gossip/demo.html (different protocol)
  • http://caterpillar.onlyfun.net:80/Gossip/demo.html (different domain name, even it's hosted on the same machine)
  • http://192.168.0.1:80/Gossip/demo.html (viewed as a different domain name)
  • http://openhome.cc:8080/Gossip/demo.html (different port number)
You can specify the src attribute of the script element an external URL. The js files from different sites can run in the same document, and use each other's variable or function; but the scripts can only get the content which has the same origin as the document running the script, not that of the js files.

A page may change its own origin with some limitations. The document.domain returns the domain name that the current document is loaded from. For instance, the document.domain of the page "http://doc.openhome.cc:80/Gossip/demo.html" is 'doc.openhome.cc'. By default, you cannot use JavaScript – no matter through iframe or Ajax – to retrieve the content from "ooo.openhome.cc", "xxx.openhome.cc", etc. If you set document.domain to 'openhome.cc', the shorter domain is used for subsequent origin checks. That is; documents coming from "ooo.openhome.cc", "xxx.openhome.cc" will be viewed as the same origin. But pay attention! You can only specify document.domain a suffix of the current domain.

The above are some common security issues of JavaScript. Of course, there are more not mentioned; even some of them are not limited by browsers but prohibited by anti-virus software or firewall.