Web pages can overwrite your system clipboard without your knowledge

August 28 2022 by Jeff Johnson

This blog post isn't just about Google Chrome, it's also about Safari and Firefox. Chrome is currently the worst offender, because the user gesture requirement for writing to the clipboard was accidentally broken in version 104. A public demonstration of the brokenness has been posted on Web Platform News. If you simply visit the demonstration page in Google Chrome or a Chromium browser, then your system clipboard will be overwritten with the text below. (It's all plain text in your clipboard, but I've added a hyperlink for your convenience.)

Hello, this message is in your clipboard because you visited the website Web Platform News in a browser that allows websites to write to the clipboard without the user’s permission. Sorry for the inconvenience. For more information about this issue, see https://github.com/w3c/clipboard-apis/issues/182.

This brokenness seems likely to be fixed soon, since the Chrome developers have already recognized the urgency of the problem. Nonetheless, the Chrome bug has brought to the public's attention the fact that web pages in all web browsers can overwrite your system clipboard with a user gesture. The crucial question is, which user gestures?

If the user gestures were limited to the keyboard shortcut for copy (⌘C on the Mac) or selecting the "Copy" command in a menu (main or contextual), that might be fine. But the gestures are not strictly limited in this way. In my testing, the following DOM events give a web page permission to use the clipboard API to overwrite your system clipboard:

Therefore, a gesture as innocent as clicking on a link or pressing the arrow key to scroll down the page gives the web site permission to overwrite your system clipboard! This is allowed in every web browser, including Safari (desktop and mobile) and Firefox.

There are two ways for a web page to write to the system clipboard: the old, deprecated document.execCommand API and the newer navigator.clipboard.writeText API. (Only the newer API was broken in Chrome version 104.) The newer API is significantly easier for web pages to use, because the old document.execCommand("copy") requires window.getSelection() to have a range of text on the page selected first, which may require adding an HTML element to the DOM. Whereas navigator.clipboard.writeText can write any arbitrary text to the system clipboard with no preparation required.

I've created a demonstration of how this works. Select either "document.execCommand" or "navigator.clipboard.writeText" below, and then continue to navigate this web page in various ways, such as clicking in the page or pressing keys. Afterward, do a paste somewhere, and you can see that this page has silently overwritten your system clipboard with a list of the navigation events that you've triggered, such as "click".

The potential for maliciousness should be obvious. While you're navigating a web page, the page can without your knowledge erase the current contents of your system clipboard, which may have been valuable to you, and replace them with anything the page wants, which could be dangerous to you the next time you paste. Why did web browser vendors ever allow this?

Your next question is likely to be, can web pages read your system clipboard too with an arbitrary user gesture? Thankfully, in my testing the answer appears to be no. There is an API to read the clipboard, but it requires a specific browser permission:

The "clipboard-read" permission of the Permissions API must be granted before you can read data from the clipboard.

Your final question may be, does my web browser extension StopTheMadness stop these clipboard API that allow overwriting your system clipboard? The answer is complicated. Roughly: sometimes. StopTheMadness does protect user gestures in certain situations, such as clicking a link. And it also stops web pages from overriding the "Copy" command to replace your selected text with different text. On the other hand, StopTheMadness does not currently stop web pages from overwriting your system clipboard in all circumstances, for all user gestures. I do believe it's possible for me to add this feature, though, and I've even done some initial testing of an implementation that seems to work. However, I'm worried about how much it would break on the web. There are many popular web pages that use the clipboard API. For example, "Copy link to Tweet" on Twitter calls document.execCommand("copy") to put the tweet URL (and some annoying tags at the end) on the clipboard. The good news is that within a few days I'm releasing a StopTheMadness update that will automatically remove the garbage tags at the end of tweet URLs when you use "Copy link to Tweet". As for blocking the clipboard API entirely, I could do it, but whether I do it depends on how much customer demand there is for this feature. Let me know!

Regardless of whether I add protections to my browser extension, everyone should be asking the browser vendors what they're going to do about the problem. Or at least get them to admit that it is a problem! The fundamental flaw is their design is equating user gestures with user consent. These aren't the same, they can't be the same, if users don't know what they're consenting to, if users don't even know that they are consenting to something via commonplace web page navigation.

Jeff Johnson (My apps, PayPal.Me)