The Whacky World of Security, Browser Extensions, and Networking

Discovering and communicating with local devices within the confines of browser security


I recently worked on a custom hardware project for the display of digital art. This was a standalone component where the idea was that a customer would buy the hardware, put it in their home, connect it to their local WiFi network, and be able to control it from either an iOS client, or a web browser.

One of the specific aspects I worked on was discovery of and communication with the hardware via a web browser. What quickly became apparent was that web browsers are sandboxed (for good reasons) in a number of ways that made this more difficult than it sounds.

Browsers have added layers of security, limiting their networking capabilities.

Javascript Multicast Requests

The first problem I ran into involved doing DIAL discovery from the browser. DIAL involves sending a multicast request to the network, which is forwarded by the router to all endpoints on the network, and then waiting for responses to come back from DIAL enabled devices at those endpoints. The issue was initiating the multicast request via Javascript in the browser. This request is an M-Search UDP request.

Sending a UDP packet violates basic browser security. Therefore, sending an M-Search request for DIAL discovery is not currently possible from the browser. After some further investigation, I found there is a W3 standard for discovering network services. Unfortunately, this is not implemented in any major browser despite the standard and implementation requests for this dating from 2009. Chrome apps can be enabled to issue multicast requests, but not Chrome extensions, and the separate UI required for a Chrome app vs an extension was not an acceptable user experience.

At this point I was fairly frustrated. I eventually had to bite the bullet and implement a non-ideal solution involving the hardware reporting itself to a centralized server, the browser querying the server, and the server returning devices that have reported themselves from that same public IP. This is not ideal for a variety of reasons, but given the constraints, it was deemed an acceptable solution.

HTTPs and HTTP

The next hurdle involved HTTPS (SSL). The entire web application is served over HTTPS. Pages served over HTTPS can not load content from non-HTTPS sources, and any AJAX requests to non-HTTPS endpoints are blocked by the browser. The hardware would not be able to serve HTTPS, as that requires the browser to trust its SSL certificate. The hardware only had a local IP address on the network, and therefore could not be issued a certificate from a trusted Certificate Authority. We experimented using a self-signed certificate, but this yielded a big ugly browser warning the first time a user tried to contact the hardware, since the certificate was not trusted by the browser. This was not an acceptable user experience, so an alternative had to be found.

Browser error message for an untrusted certificate.

Having recently investigated browser extensions and Chrome apps, I had an idea. After some experimentation, I verified that browser extensions are not limited in the same way as the page’s Javascript itself is when it comes to HTTPS communication. Some background on the browser extension ecosystem:

Basic schematic for communication between web page, browser extension, and local network hardware.

As can be seen above, the extension exists within the context of the browser, not the web page itself. A secure web page can communicate with an extension, and the extension can communicate with external endpoints via standard AJAX. The extension can be used as a proxy between the secure page and the non-HTTPS hardware endpoint.

Communication between the web page and the extension is done through message passing in Chrome, and event dispatching in Firefox and Safari.

Using an extension to handle communication also had the advantage of allowing state information about the hardware to be held in the extension instead of duplicated across multiple browser pages. Extensions typically exist as singletons in the browser, so multiple pages can access and interact with the same extension.

Of course, the user now had to add an extension to their browser for communication with the hardware device to work, but this is significantly more straightforward and easier for users to understand than a Chrome app.

Takeaways

Surprisingly, the majority of this project involved working around browser security measures. Blocking information from non-HTTPS sources on a secure page is undoubtedly necessary for maintaining the integrity of a secure page. Similarly, requiring a trusted SSL certificate to be included as part of the HTTPS protocol is vital to preventing man-in-the-middle attacks.

However, providing more straightforward, user-friendly methods of interacting with network-connected devices through a web-browser will be important as we move towards an internet of things culture, where more and more everyday objects can connect to local networks and the internet.

Preventing Javascript from making multicast requests directly is grounded in the sound reasoning. For instance, ensuring a single script loaded on a webpage will not flood every address on the user’s network with requests — causing significant network delays and potentially bringing the network down entirely — is a good thing. However, the lack of browser support for discovering available devices on a local network is very limiting, especially considering the existence of the W3 standard for network service discovery.

Despite the headaches, this was a very interesting project that touched on a number of aspects of browser security and network architecture that is often not encountered during more standard web development. The entire team learned a lot about browser internals, and ultimately I was able to build a functional solution with an acceptable user experience within the constraints of current web browser technologies.