Dark patterns with the HTML 5.2 <dialog> tag and Chrome for fun and profit

Tane Piper
3 min readJan 31, 2018
I couldn’t find a really good image for this story, so here is a stock hacker photo instead.

Recently I was introduced to the <dialog> tag and thought it was an interesting use of a web component pattern, but immediately I questioned the API and indeed after some minor digging, there really are some glaring issues regarding their use in terms of security, and as a major annoyance.

Update

I’ve added some additional comments to this post based on some feedback. As some have pointed out, you could really do this with any piece of the DOM and JavaScript — and they are correct. My suggestion is that however for something like a modal which is designed to focus user interaction you would have to ship something like jQuery or Bootstrap. This is now a feature in the platform and as such I think should be used responsibly (but I doubt it will — I’m sure we’ll soon see it being used for those annoying SIGN UP FOR MY NEWSLETTER popups). My main feature request would be to implement a global state like isThereAlreadyAModalOpen ? and disallow any future showModalcalls to avoid flooding the browser with dialogs and to have a way to always guarantee their closing, but I have been working on a solution for that below.

The Hacks

I’ve put them together in a Codepen and there are 4 main hacks:

  • Adding a listener over a close button to make it nearly impossible for the user to close it.
  • Having a close button that when pressed closes the modal but also triggers an undesirable path.
  • 2 Buttons that send you into an loop of death in creating modals.
  • Hijacking the Escape (and Tab) button

The whole thing calls itself to get into a loop if you press the right buttons. Below are the issues I found:

Overriding the DOM for fun

One issue is that you pretty much have full control over the DOM element of the dialog. This is good in many ways, but with great power…

With our annoying button, we use this to control the transform style of the modal itself and move it beyond the reach of the user. We add a second button that does close the modal using a call to modal.close() but after that we can trigger any JavaScript we want, such as loading new tabs, running bitcoin miners, searching for aliens, etc.

Blocking the Escape Route

But of course most users might try press the Escape key in hopes that whatever is on the screen will disappear, but we have that particular route covered.

In this case we hijack when we detect the keycode for the Escape key, ASCII 27 and we use it to just keep clicking the open button for creating the modal.

However it’s worse than that! As an added bonus pointed out to me if you also check for ASCII 9, 13 and 32 as the Tab, Enter and Space characters so you can also punish the user for trying to use the keyboard to close the modal. The code that captures them, and the arrow keys is:

const eventKeys = [9, 13, 27, 32, 37, 38, 39, 40];  // Capture Escape, Enter, Tab, Space and arrow keys

Killing the Browser

It’s quite easy to create a stack overflow with the dialog by just calling a setInterval on it:

Because this is quite easy to create from JavaScript alone, you have to be especially careful of 3rd-party scripts potentially using this to hijack pages using features built into the browser.

I’ve created another codepen with a web component that embeds the dialog in to a shadowroot and provides the global state so you cannot open more than one at a time.

Hopefully you enjoy the demo and this post, and this gives some pause for thought too in how we sometimes implement and use browser features. Users have already been taught bad habits for hitting buttons, especially on OSX these days.

--

--

Tane Piper

Senior Software Leader @ IKEA — Digital Acceleration and Data Transformation