Clipboards!

9 min read Original article ↗

"How the hell does Discord know the file name of this picture I copied from my browser?" is an example of a thought that will help me kill half an hour instead of being productive.

So, a quick surface search gives me this :

A window can place more than one object on the clipboard, each representing the same information in a different clipboard format. Users need not be aware of the clipboard formats used for an object on the clipboard.
- From <https://learn.microsoft.com/en-us/windows/win32/dataxchg/clipboard-formats>

And funny enough, here's what the clipboard looked like when I copied the text above :

InsideClipboard screenshot
InsideClipboard, a software that looks.. inside clipboards.

Don't get overwhelmed, it's just a screenshot of a neat software displaying all sorts of different data types. You'll understand most of it in a bit.
So to re-iterate, whenever you copy anything from anywhere, it will copy and store the information you copied in "different clipboard formats", which is really just a roundabout way of saying metadata.

Data Trap by xkcd
Every time this xkcd is quoted it creates more data

There's all sorts of extra information stored based on the type of data being copied. For the definition above for example, there's the text itself, which is what you expected to copy. And then there's the "HTML Format", which is still the same data, but including some HTML information.

(Shoutout to NirSoft Freeware for providing us with InsideClipboard, the software helping us peep inside whatever clipboards we're going to copy in our little adventure.)

Let's now look at the HTML Format, which is twice the size of the text I just copied :

    Version:0.9
    StartHTML:00000183
    EndHTML:00000481
    StartFragment:00000217
    EndFragment:00000445
    SourceURL:https://learn.microsoft.com/en-us/windows/win32/dataxchg/clipboard-formats
    <html><body>
    <!--StartFragment--><p>A window can place more than one object on the clipboard, each representing the same information in a different clipboard format. Users need not be aware of the clipboard formats used for an object on the clipboard.</p><!--EndFragment-->
    </body>
    </html>
    

For my non-tech readers, this above is just the website's HTML structure of the text I copied. Now for the Firefox special text/_moz_htmlcontext :

        <html class="layout layout-holy-grail show-table-of-contents conceptual show-breadcrumb default-focus theme-dark" lang="en-us" dir="ltr" data-authenticated="false" data-auth-status-determined="true" data-target="docs" x-ms-format-detection="none" style="--window-inner-height: 751px !important; --atlas-header-height: 256px !important; --atlas-footer-height: 128px !important; --atlas-header-visible-height: 150.39999389648438px !important; --atlas-footer-visible-height: 0px !important;">
            <body id="body" data-bi-name="body" class="layout-body " lang="en-us" dir="ltr">
                <main id="main" role="main" class="layout-body-main " data-bi-name="content" lang="en-us" dir="ltr">
                    <div data-main-column="" class="padding-sm padding-top-none padding-top-sm-tablet">
                        <div>
                            <div class="content">
                            </div>
                        </div>
                    </div>
                </main>
            </body>
        </html>
    

This htmlcontext on the other hand, is the complete code structure of the full page surrounding the line I copied. Thank you Firefox, for shipping the entire page along into my clipboard, making sure everyone understands the "context" of my 2 line shitpost.

Firefox Context

Back to the first HTML Format : it is the de-facto standard when copying any kind of content from any browser. When you copy text online, the HTML format in your clipboard will store: the text you copied, the URL that content was copied from, and an HTML "fragment" from that page.

Note that "web" content here is a loose term, and theoretically any app, can serve an HTML Format with the text you copy from it.

For example, I like to use OneNote as my text editor when writing these blogs, and here's an example of what copying from OneNote looks like :

    Version:1.0
    StartHTML:0000000105
    EndHTML:0000000641
    StartFragment:0000000588
    EndFragment:0000000595
    <head>
    <meta http-equiv=Content-Type content="text/html; charset=utf-8">
    <meta name=ProgId content=OneNote.File>
    <meta name=Generator content="Microsoft OneNote 15">
    </head>
    <body lang=en-US style='font-family:Calibri;font-size:11.0pt'>
    <p style='margin:0in;font-family:Calibri;font-size:11.0pt'><!--StartFragment-->and then he said, I didn't ask for context, I asked for a sandwich with cheese!<!--EndFragment--></p>
    </body>
    </html>
    

OneNote is a good example because unlike Discord or VSCode, which are written in JavaScript, OneNote is coded in-house by Microsoft in C++/C#, and still chooses to provide its copied text information in HTML Format too.

Any app can choose to write to your clipboard in any format.

In many cases, apps will use this HTML Format to include styling information, like the font used, the text size, text color, background color, and so on.. This is good, it's in fact a great idea as to be able to move rich text around with style. Still, every time you copy data, you might be carrying around a lot more information than you'd expect.

For example, why am I carrying around the "Source URL" of where my data was copied from? I know damn well I'll never need to use that data when pasting my text into any app I use. In any case, saving my privacy rants for another day, as I was researching this I found the weirdest behavior from ChatGPT, Claude, Gemini, Grok, and Mistral AI. Kimi, Deepseek, Perplexity AI, all behaved normally.

When you copy data from virtually every website online, it will copy along this source URL, which is the link from where you were copying your text.
But the 5 LLM websites I just mentioned, will intentionally strip the source URL from the clipboard. Gemini specifically, will ONLY strip it from responses, but not from your own prompts.

For some (stupid) reason, because this behavior also omits Firefox's "HTML context" we mentioned earlier, I (stupidly) thought this unnatural behavior was caused by the browser rather than the websites. So, my first reaction was to send an e-mail to the Firefox CTO (wait what), highlighting the special behavior. He responded (what), asking me for more clarifications. I apologized as I figured out a day later that it was code specific to the websites above, and completely unrelated to the browser. (Incredible thanks to @Bobby Holley for being on top of things, great person!)

In fact, recreating that logic to remove the source URL was fairly easy, ChatGPT & others simply intercept your copy action as soon as it happens, clean up the HTML, and then place it in your clipboard, which ends up removing the source URL. But while that answers our question on the "how?", the "why?" is still up for speculation. If anyone eventually figures that out, shoot me an e-mail! I don't I'll be e-mailing any other CEOs any time soon.

After this I spent more time tinkering with copy/paste logic, I tried a LOT of things in the spirit of trying to break things. Alas I'm really just another dev, and the spec is pretty much locked down :

  1. Any website always needs explicit permission to read/write to your clipboard, which is displayed in a special popup in all browsers.
  2. Except when the user is directly copying from/pasting into the page, the website can then hook into those events. It can either write whatever it wants to the clipboard when you try to copy, or read whatever you just pasted, without any special permissions.
  3. Another special case is when you're interacting with the site in any way, the website has a time window of roughly 5 seconds after that interaction to WRITE to your clipboard (simulating a copy action, this is how websites provide you with a "Copy Data" button). Read access is impossible, so even if you're interacting with the page they cannot read from your clipboard, unless explicit permissions were granted as specified in 1. (Firefox is cooler here, where they will allow read access if the content is from the "same-source", meaning if you copy from a webpage, firefox will let that same webpage read the copied content for the next 5 seconds, without needing extra permissions.)
  4. I couldn't find a way to spoof data types, meaning pass text as an image, there's at least some form of data checking. You can pass an image blob as text, but I couldn't find anything meaningful from tampering with it.
  5. Images specifically, do not trigger the copy event. To copy images, you need to click a special button ("Copy Image") in the browser's menu, which doesn't trigger the usual event for copying. I still came up with this abomination which should in theory allow access to some copied media through javascript :

    let potentialSrc = null;

    //This trick listens first to the context menu
    //and then stores whatever item the user right clicked
    document.addEventListener("contextmenu", (e) => {
    const specialElements = ["IMG", "A", "VIDEO", "AUDIO", "SVG"];
    if (specialElements.includes(e.target.tagName)) {
        potentialSrc = e.target;
    } else potentialSrc = null;
    });

    //Then through the clipboardchange event, we construct whatever we think the clipboard has
    //based on nothing but the MIME types exposed in the event
    navigator.clipboard.addEventListener("clipboardchange", async (event) => {
    if (potentialSrc !== null) {
        if (event.types[0] === "text/plain") {
        console.log([
            new ClipboardItem({
            "text/plain": potentialSrc.href
                ? potentialSrc.href
                : potentialSrc.src,
            }),
        ]); //If it's textual, the user probably clicked "Copy Image/Video/Email URL"
            //so their clipboard has the href source of whatever was in the context
        }

        //If they clicked "Copy Image", their clipboard would have the image png blob
        if (event.types.includes("image/png")) {
        const img = potentialSrc;
        const canvas = document.createElement("canvas");
        canvas.width = img.naturalWidth;
        canvas.height = img.naturalHeight;
        canvas.getContext("2d").drawImage(img, 0, 0);
        canvas.toBlob(async (blob) => {
            console.log([
            new ClipboardItem({
                "image/png": blob,
                "text/html": img.src,
            }),
            ]);
        }, "image/png");
        }
        potentialSrc = null;
    }
    });
          

So, 4 days into the half-hour I expected this would take, I still don't know how Discord knows the name of my copied picture. I copy an image and check its HTML Format :

    Version:0.9
    StartHTML:00000097
    EndHTML:00000384
    StartFragment:00000131
    EndFragment:00000348
    <html><body>
    <!--StartFragment--><img src="https://i.ytimg.com/vi/fC7oUOUEEi4/maxresdefault.jpg" jsaction="" class="sFlh5c FyHeAf iPVvYb" style="max-width: 1280px; width: 555px; height: 312px; margin: 0px;" jsname="kn3ccd"><!--EndFragment-->
    </body>
    </html>
    

Ah yes, it just reads the url and grabs the file name. "maxresdefault.jpg" here for example. Fascinating.

So, how does one conclude a tech article about a fringe tech gimmick? Figuring out how Discord knows the filenames of my pasted memes on random online servers is a good itch I've now scratched.

Writing about it on the other hand, is a selfless act from me to you, my content craved fans who deserve only the best of technical shitposts. Now go forth my children, educate your fellow peers on the wonders of the Clipboard's HTML Format.

Peace <3.