One of the realities of the modern web is that every new technology needs to balance between functionality and security. In this article, we talk about one particular case of this balance that comes into play and how it may affect working with virtual reality technology on the web.
In fact, this is a major security risk. For example, imagine Bar.com is a web server that displays scanned documents. For illustrative purposes, let’s pretend Bar.com is actually “IRS.com”, and contains millions of users’ scanned tax records. In the scenario above, without any security measures in place, our Foo.js file would be able to reach into Bar.com, grab a secret file, plop it into the page’s <canvas> tag, read out the contents, and store it back to the Foo.com server for further exploitation. The server administrator at Foo.com would then have access to millions of users’ tax records data that had been maliciously sniped from Bar.com. It’s easy to see, then, that scripts like Foo.js can quickly become a security risk. Content that “crosses origins”–that loads from separate places on the Internet–needs to prevented, from co-mingling in potentially malicious ways.
The solution? Browsers, by default, will block this type of cross-origin content loading altogether! If your website and script are being loaded from Foo.com, then your browser forces the website to “stick to its lane”. Foo.com webpages will only be allowed to load other content that comes from Foo.com, and will be blocked from loading–and potentially exploiting–content from Bar.com.
Cross-origin protection and WebVR
This basic situation plays out in many different ways within web technology. A cross-origin image can’t be read back into an HTML <canvas>, and, importantly for our conversation, can’t be used as a WebGL texture. WebGL is the technology underlying all of the web-based virtual reality tools like AFrame and ThreeJS. The specifics of why cross-domain images can’t be used as textures in WebGL are pretty fascinating, but also pretty complicated.
Cross-Origin Resource Sharing (CORS)
Fortunately, there’s a solution called Cross Origin Resource Sharing. This is a way to tell your web servers to explicitly opt-in to cross-domain uses of their content. It allows a webserver like Bar.com to say “I expect to send resources to scripts at Foo.com, so allow those requests to go through and load into the browser.” It’s basically the Internet equivalent of telling the bouncer at your favorite club to put your buddy on a VIP access list, rather than leaving him standing at the door. As long as the bouncer…erm, browser…sees that a specific source of data is vouched for, it will allow the requests to go through.
Doing these CORS checks requires some extra communication between the browser and the server, so occasionally the browser skips CORS checks. However, when creating VR content in particular, sometimes we want to explicitly ask the browser to perform a CORS check so that the content can be loaded into a secure element like an HTML <canvas> or WebGL texture for VR display. In this case, the “crossdomain” attribute on HTML elements is necessary. If we load an image using the HTML code
<img src="http://bar.com/image.jpg" crossorigin="anonymous"/> the browser will perform a CORS check before loading the image for the user to view. Assuming the server hosting the image (in this case, Bar.com) has CORS allowed for the target website (Foo.com), that image will be considered safe for things like loading into an HTML <canvas> or using as a WebGL texture on Foo.com. In this way, VR websites hosted on one server can continue to load pre-approved resources from other remote servers, as long as those servers provide the necessary “OK” for CORS.
Even worse, some browsers have broken or unreliable implementations of CORS. For example, Safari on Mac OS X cannot currently load videos via CORS, regardless of the browser and server settings. As a general tip, if you see errors in your browser’s web developer console that mention any sort of security restriction, start by looking into whether you’ve come up against a CORS-related issue.