Panic Button: a short intro to a quick exit

I’m a developer at Thick and for the last few months we’ve been working with WIRE on a project called Women Talk Money. It’s a website aimed at increasing financial literacy among women, and part of the material deals with advice on how to identify and respond to financial abuse.

Because of the sensitive nature of that content, the site designs included a “panic button” at the top of the page that would redirect the user to an innocuous site and hide what they were looking at.

We immediately started talking about how best to implement this. There was the obvious and easy solution of just making it a plain link, but what would happen in the case of a slow or disabled internet connection? For example, if an abusive partner had disconnected the power to the wifi? Any implementation would need to be able to respond to the worst-case scenario.

The solution to that particular problem was to erase the entire DOM as soon as the panic button is hit, and then redirect. The redirect will still fail in the case of the disconnected internet, but at least the user will be left with a blank page instead of anything incriminating.

As we talked more about the panic button functionality, we figured it would probably be worth developing it as a separate module and releasing it as open-source. The less friction involved in putting quick-exit behaviour on a sensitive site, the better, right?

So we set about doing exactly that and, a few solved problems later, here we are: panic-button is available for use today. If you’re creating a site that has vulnerable people as any proportion of its target audience, consider incorporating a quick exit — all it takes is pasting this code at the top of the page.

<!-- begin panic button -->
<div id="panic-container" class="panic-button">
<span class="panic-button__text">Protect yourself online.</span>
<a class="panic-button__link"
href="https://www.domesticshelters.org/safe-surfing"
>
Learn how to hide your browsing history.
</a>
<a id="panic-button" class="panic-button__button"
href="https://www.google.com"
>
<span class="panic-button__icon">&times;</span>
Quick exit (ESC)
</a>
</div>
<link rel="stylesheet" property="stylesheet" href="https://cdn.rawgit.com/studiothick/panic-button/v1.0.4/dist/panic.css" />
<script async src="https://cdn.rawgit.com/studiothick/panic-button/v1.0.4/dist/panic.min.js"></script>
<!-- end panic button -->

If you decide to use panic-button or have any thoughts or feedback, feel free to get in touch. Open an issue if it’s a bug or feature request, or tweet at me if you just want to say hi.


Some implementation details for the curious

Our goal with panic-button is to create a drop-in, bulletproof solution that can be incorporated into a website with as close to zero effort as possible.

My first approach was to package it all up in a single script that would create the relevant elements when a page loaded. One could include the file via NPM or Bower and it’d integrate with all kinds of latest-fashion tooling. But this came with three big downsides.

It was a pain to configure.

In the earliest version of panic-button, config was done by defining a global javascript object called panic_config. I was never comfortable with this, and soon switched to using data-attributes on a container element. I felt that that was better, but still a really ugly way of doing things.

It broke entirely if there was no Javascript support

Any computer running a pre-JS browser, or one with NoScript enabled, would just show nothing at all.

Async loading was janky, sync was slow

Spending too much time in Pagespeed Insights has made me permanently wary of any <script> tag that isn’t either inlined or async. But if the panic-button script was included asynchronously, the script would fire after the page had loaded. The creation of a new element at the top would shunt everything down a few lines, resulting in a nasty jolt. Inlining, on the other hand, would never work, because what kind of self-respecting package is distributed by getting the implementer to paste in a big old chunk of code?

The solution

The solution was, of course, realising that there are a ton of self-respecting packages that are implementable by pasting in a chunk of code. Facebook pixel tracking and Google Analytics both work that way, for example.

The pasted chunk is only a few lines longer than the global-object config version, and has the added bonus of being configurable by anyone with a passing understanding of HTML, not to mention showing up correctly in WYSIWYG editors and in NoScript situations.

A sidenote on “Learn how to hide your browsing history”

Currently, the “learn more” button directs to a site on DomesticShelters.org. This was just the best candidate from a quick Google search. There might be better destinations for this link, but that one seems pretty thorough. As with all elements of this project, I welcome feedback and suggestions.

Future work

The main limitation of panic-button is that it doesn’t erase or obfuscate any entries in the browser history. This is a technical limitation imposed by the browser — pages don’t have read or write permission to their own history entries, much less other ones — but it’s still a feature that is noticeably absent. Absent this behaviour, the banner includes a “safe browsing practices” link, but this is still a compromise. In a perfect world, a sensitive-materials site would be able to call some kind of history.ignoreMe() function that would effectively place a browser in always-private browsing mode for the page being viewed, or perhaps just a meta-tag indicating that a given page should not be stored in history. In any case, such a feature does not exist… yet.

I’ve also given some thought to detecting incognito/private mode and hiding parts of the banner based on that. I’m not sure it actually adds value to the plugin, though, and the hacks required to make that check — every browser does it differently — would doubtless make the whole thing significantly more error-prone.

Also, more generally, panic-button has only been in development for a relatively short time. We’ve caught the most obvious bugs, but as the end goal is a bulletproof solution for zero work, I’m sure there’re edge cases we haven’t thought of. As we catch them, we’ll be updating panic-button (and accepting fixes and polishes from anyone who wishes to submit them! Pull requests are welcome!). Those updates will percolate through the internet infrastructure, and help create a safer browsing experience for everyone.

panic-button is available at our github.