Transitioning to TLS

tl;dr: Migrating old content and infrastructure to TLS is still f’ing hard. If you are using CloudFlare, see “How do I fix the infinite redirect loop error after enabling Flexible SSL with WordPress?“.

After the recent push by many in the standards community to transition our sites to TLS, I decided to move my blog over to TLS. The push is driven the the need to generally try to make the Web more secure + we are trying to move the Web forward by requiring TLS for certain APIs (e.g., Service Workers).

This is not the first time I’ve moved this blog to use TLS.

Early attempt

The first time I did this was a few years ago when I became interested in encryption. During that time, AFAIK, in order to have a SSL certificate you needed to have a static IP address. Furthermore, there was no intermediary services, like StartSSL or CloudFlare, to provide sites with essentially free certificates. Doing the transition to SSL with my host (DreamHost) was fairly straight forward, but quite expensive for me at the time (I was a student or a junior engineer at the time). I don’t recall the exact numbers, but it was effectively something like $25/year for a static IP and then probably something like $50/year for the cert. This on top of the 10/year for the domain + $150 something/year I pay for hosting. Eventually, the cost became a burden to me: only a small handful of people ever visit this site (I don’t know how many as I don’t use analytics our of respect for my visitors) – but I just didn’t feel it was worth the cost so I abandoned it.

This was pre-Snowden, so I was fairly naive to the dragnet activities of the likes of the those assholes at the NSA. I also didn’t understand that, even if your site’s content is harmless, it serves as a data-point in a visitors history. By using TLS, one obscures the navigational trail: they may know you looked at, but not what you were reading. It can help a little.


More recently, in light of all the bad shit that’s happening in the world, and prompted by Anne van Kesteren, I decided to re-encrypt this site. However, this time around I had a very negative experience trying to transition my personal blog to TLS.

After complaining to Anne about the costs, he pointed me to CloudFlare with the claims about it being free. The setup experience with CloudFlare was pretty straight forward: put a few things into a form and then go and tell DreamHost that the DNS values had changed. No big deal… but then things started to get fun.

Firstly, although my site started working straight away over TLS, I had to wait 4 days for the certificate to actually say it was for “”- during which time browsers accessing my site over HTTPS would see the red warning screen (effectively blocking anyone visiting the site over HTTPS). Thankfully, I had left plain old HTTP access enabled.

Once my certificate was actually granted and working, I decided to disable HTTP altogether. I did this by telling WordPress that this site’s URL was now “” – which immediately triggered a cascade of shit. Firstly, the site went into an infinite redirect loop and the whole site became inaccessible. I tried to revert this change in WordPress’ database, but it didn’t seem to help. I then tried to revert various things – but also didn’t work so I just left it be as I had other work to do.

I was offline for about 1 week, then thankfully WordPress issued an update. This seemed to fix things somewhat: at least the site started working again over HTTP. However, switching to HTTPS is still quite broken – the admin section is still completely broken. It won’t load styles because WordPress is too stupid to realize it is running over HTTPS instead of HTTP.

Anyway, and I’m still struggling with various things. Migrating old content and infrastructure to TLS is still hard.


I recently found myself (re)reading Neil Stephenson’s Snow Crash for the one billionth time. In it, there is a great passage about “gargoyles”:

“Gargoyles represent the embarrassing side of the Central Intelligence Corporation. Instead of using laptops, they wear their computers on their bodies, broken up into separate modules that hang on the waist, on the back, on the headset. They serve as human surveillance devices, recording everything that happens around them. Nothing looks stupider; these getups are the modern-day equivalent of the slide-rule scabbard or the calculator pouch on the belt, marking the user as belonging to a class that is at once above and far below human society. They are a boon to Hiro because they embody the worst stereotype of the CIC stringer. They draw all the attention. The payoff for this self-imposed ostracism is that you can be in the Metaverse all the time… Gargoyles are rude by definition.”

What’s great about this bit of the book is how concisely Stephenson captures the anxiety about wearables and surveillance. The simultaneously positive and negative societal response to things like Google Glass and even BlueTooth headsets. At once, we are fascinated by the affordances of these technologies for personal use – while at the same time we are repulsed by the lack of agency and sense of disempowerment that comes from people using them around us – and so “marking the user as belonging to a class above and far below human society”.

In public spaces, we’ve come to naturalize that corporations and the government constantly survey us through, for example, ceiling mounted cameras (to the degree that we believe that such actions keep us safe or protect property) – but the thought that a fellow citizen would partake in such dehumanizing activities tends to put those people in a class far below human society. I say these are dehumanizing activities because the can so easily be used to violate our right to privacy – even in public spaces: this can be at work, at a bar, of just out on the street. It’s not possible to know if we are either being recorded by the user or if we are being watched remotely by a nefarious third-party (without the consent or knowledge of the wearer). And the fact that the wearer cannot provide any guarantees about what the device is doing marks them as suspicious at best, and arrogant or even naive at worst (a class far below human society).

At the same time, our fascination with the new affordances of these devices draws us to the wearers of such devices – putting them in a class above. The chosen ones. The explorers. “What’s it like?”, we either ask directly or just wonder.

*In Snow Crash, the CIA has been privatized – hence Central Intelligence Corporation.

Why manifests and permissions don’t mix

I often get requests to add fine-grained API permissioning to the Web Manifest format. Fine grained permissioning would be something like: “I want to access contacts, but I only need read only access”. The opposite being course grain permissioning: “I want to access contacts… and do all the things! (i.e., read, write, update, and delete)”.

There are quite a few problems with trying to rely on a manifest to grant permissioning – and we can easily see what they are by looking at platforms that rely on manifests for permissioning (e.g., Android, iOS, and Firefox OS). As iOS’s permissioning closely mirrors the Web’s API permissions model, I’m not going to discuss it (irrespective of apps being vetted through an App Store which weeds out most bad actors). The problems with Android’s up front permissioning model are well known (i.e., few people read/understand them), so we don’t even need to go there. It’s bad. End of story.

That leaves Firefox OS (FxOS). In this post, I’ll critically examine the issues that come up with FxOS’s use of a manifest to enable permissions and the somewhat sad implications of deciding to do permission in a manifest. FxOS is also a good platform to focus on because it is the platform that, despite being proprietary, most closely resembles the Web Platform: hence, we can learn a lot about what the implications would be if we brought the same permissioning model to the Web.

As a full disclaimer, I work for Mozilla who make FxOS (but I don’t work directly on FxOS!). I’m also one of the key contributors to the Web Manifest spec and I’m implementing the Web Manifest spec in Gecko.

FxOS’s permissioning

FxOS supports both course-grained and fine-grained permissioning in the manifest. Beyond the API capabilities afforded by the Web Platform, web apps targeted at FxOS can only enable permissions once they are explicitly “installed” by the user. FxOS exposes a proprietary API to enable installing a web site.

The implications is that web apps are restricted in functionality until users complete an installation process. However, because users are not able to experience the full application until they install an application, developers may be forced to nag users to install their app (e.g., by showing big “Install me!” buttons). This takes users out of context and forces them to do something that they might otherwise not want to do (install an app) to complete some task.

To overcome the “install me!” button problem, FxOS relies on having a centralized app store (Firefox marketplace), which is quite similar to Apple’s App Store or Google’s Play Store in how it operates. More on this below.

Security/Privacy sensitive Device API access

FxOS restricts the APIs a Web App can access to those exposed by the Web Platform + tiny handful of other proprietary APIs. Web apps targeting these FxOS-proprietary capabilities are known as “hosted apps”.

To allow access to more powerful APIs FxOS relies on a proprietary packaged application format, which bundles a digital signature, and the resources on an application (css, html, js) into a Zip file. And, of course, then relies on the Firefox marketplace to do the distribution. Packaged apps created by the average developer are called “privileged apps”. It is “privileged” in that Mozilla checks it, and, if it meets a set of criteria, it gets a stamp of approval in the form of a digital signature (a light weight form of DRM).

Packaged application rely on a manifest being available within a (zip) package – and because of its immediate availability, FxOS can use it as a means to enable fine-grained permissions. However, this comes with fairly severe scalability issues – and brings all the issues of traditional software distribution with it:

  • Developers must submit their application to a market place – leading to centralization.
  • Submitting an application to an App Store triggers a lengthy review process – and access to device/storage APIs are checked by a human reviewer. However, what we are essentially doing here is making the decision to allow apps to use certain APIs – and given users and assurance that this is ok (i.e., at runtime, we don’t prompt for security permissions – only for privacy ones like geo and accessing camera/microphone, etc.).
  • PKI infrastructure must be established, because APIs are only enabled if Mozilla’s signature is in the package.
  • Packaged apps don’t work well with the way the web is architectured – and this has lead Mozilla to introduce fairly insecure APIs to overcome these limitations. For example, FxOS allows developers to request a “SystemXHR” API, which essentially allows packaged apps to contact any server, ignoring CORS in the process.

How the Web Manifest differs

FxOS’s approach is in stark contrast with the way we (the community working on standardizing the manifest) are approaching the development and standardization of the Web Manifest format. The manifest is designed to be a non-critical and low priority resource: the manifest should only be downloaded “when needed” – and it should be treat it like a “progressive enhancement”. That is to say, web apps should not depend on it being either present or supported… it’s just “the cherry on-top” of a web apps ice cream.

Effectively, this means when the user attempts to “add to home screen” will the user agent initiate the d/l for the manifest. This naturally limits the utility of the manifest as a place to put permission policies for APIs – as the APIs could only become available after the manifest loads … leading to some bad race conditions.

Currently, the Web Manifest spec explicitly says not to delay the load event of the document. So, this means that there are limitations in detecting when the manifest actually loads (this is by design).

Additionally, in Gecko, we intend to support two ways of actually loading a manifest:

  1. link rel=”manifest”: non-blocking, but could fire an onload event to signal readiness.
  2. HTTP’s Link: header. As it’s outside the Document, it doesn’t interface with it (though it could, but it would be a bit of a layering violation).

The implication is that, as a dev, one would need to wait for the manifest to be available and ready before granting API permissions. This is not ideal, from my perspective, because it introduces significant delay and dependency on a resource that may never become available. A security implication of 2 is that a proxy can insert a header (though a proxy could also change the payload, so also affecting 1).

Hopefully this explains is why there has been reluctance (from me, at least) to add security critical permissions to the manifest, and instead continue to rely on the Web APIs themselves to handle permissioning.

So what’s the alternative

A different approach would be to simply limit the usage of an API when it is initialized – or limit access to an API from same origin, or the top-level browsing context, and maybe even requiring TLS. This is similar to what Service Workers and requestAutoComplete() are doing – they both require TLS. Doing so overcomes many of the issues I raised above: If security/context conditions are met, APIs can be used immediately without having to wait on some other external resources that dictates the policy of usage. This also removes fragility, in that policy is tightly bound to the API at point of usage.

It also removes the need for apps stores – but again forces API and UX designers to deal with the permission problems (instead of centralizing everything and having to have other humans do a review of the app before users can use it).

Bottom line: let’s use the Web’s security model + TLS to do API permissioning.