<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>ruudje</title>
    <link>https://ruud.je/</link>
    <description>Software developer and retro geek based in the Netherlands</description>
    <pubDate>Sat, 11 Apr 2026 08:17:35 +0000</pubDate>
    <item>
      <title>Running Windows XP on the Intel NUC DC53427HYE</title>
      <link>https://ruud.je/running-windows-xp-on-the-intel-nuc-dc53427hye</link>
      <description>&lt;![CDATA[windowsxp&#xA;&#xA;Disclaimer: the Amazon links in this post are affiliate links.&#xA;&#xA;If you are just looking for the drivers, you can find them on the Internet Archive.&#xA;&#xA;Windows XP holds a special place in many retro gaming enthusiasts&#39; hearts, serving as the perfect platform for experiencing games from the late 1990s and early 2000s. While most users opt for hardware of the era to ensure maximum compatibility with XP&#39;s drivers, there&#39;s something intriguing about running this classic operating system on more modern hardware.&#xA;&#xA;!--more--&#xA;&#xA;I had several Intel NUC DC53427HYE devices lying around. Released in 2013, this model features an i5-3427U CPU with Intel HD Graphics 4000 and supports up to 16GB of DDR3 memory through two 8GB slots. For storage, it includes an mSATA slot. The I/O options consist of one USB 3.0 port on the front, two USB 2.0 ports on the back, Ethernet, HDMI, and two Mini Displayports. My unit also had a Wi-Fi card installed.&#xA;&#xA;Windows XP extended support ended on April 8, 2014. As this Intel NUC is from 2013, it may just be old enough to run Windows XP properly.&#xA;&#xA;So let&#39;s give it a shot.&#xA;&#xA;Installing Windows&#xA;&#xA;I created a bootable Windows XP installer USB using WinSetupFromUSB. Upon booting the installer and initiating setup, I encountered a BSOD due to missing SATA drivers.&#xA;&#xA;While this could be resolved by switching to IDE mode in BIOS settings, I opted instead to use a modified Windows XP SP3 image from the Internet Archive that included built-in SATA drivers, allowing for AHCI mode operation. &#xA;&#xA;The installation succeeded, leaving only standard driver installation remaining.&#xA;&#xA;Installing the drivers&#xA;&#xA;It took a bit of searching, but I was able to find the drivers needed to make everything work. I have created a backup of these drivers and uploaded them to the Internet Archive.&#xA;&#xA;All you need to do is mount the ISO file using a tool like WinCDEmu and let the driver wizard search for removable media.&#xA;&#xA;The backup contains the following drivers:&#xA;&#xA;Intel(R) HD Graphics 4000&#xA;Intel(R) 7 Series Chipset Family SATA AHCI Controller&#xA;Intel(R) Display Audio&#xA;Intel(R) 82579LM Gigabit Network Connection&#xA;Intel(R) Centrino(R) Advanced-N 6205&#xA;Intel(R) Active Management Technology - SOL&#xA;Intel(R) 7 Series/C216 Chipset Family Universal Serial Bus (USB) Controller - 1E31&#xA;Intel(R) 7 Series/C216 Chipset Family SMBus Host Controller - 1E22&#xA;Intel(R) Management Engine Interface&#xA;Intel(R) Trusted Platform Module&#xA;&#xA;Adding sound&#xA;&#xA;Note: It is possible to get sound via HDMI without any additional hardware, if your monitor supports it&#xA;&#xA;As the NUC does not come with built-in audio ports, we will need to use USB adapters. This Sabrent USB adapter that does not require drivers will do just fine.&#xA;&#xA;Adding Bluetooth&#xA;&#xA;While Bluetooth technically works on Windows XP, from my experience the audio latency is very big. Connecting other peripherals like mice is also hit or miss. For these reasons I do not recommend Bluetooth.&#xA;&#xA;That said, if you still would like to add Bluetooth, the TP-Link UB400 V1 is confirmed to work. TP-Link still has a Windows XP driver for this product on their website. Make sure you get V1 of this product. V2 will not work. Amazon sells the UB400 as well, but it is the V2 version, even though the product description says it supports Windows XP.&#xA;&#xA;Conclusion&#xA;&#xA;For those interested in running Windows XP, whether for retro gaming or other purposes, the Intel NUC DC53427HYE is an excellent choice, combining compact dimensions with robust performance.]]&gt;</description>
      <content:encoded><![CDATA[<p><a href="https://ruud.je/tag:windowsxp" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">windowsxp</span></a></p>

<p><em>Disclaimer: the Amazon links in this post are affiliate links.</em></p>

<p><em>If you are just looking for the drivers, you can <a href="https://archive.org/details/xp_x86_intel_nuc_dc53427hye_drivers" rel="nofollow">find them on the Internet Archive</a>.</em></p>

<p>Windows XP holds a special place in many retro gaming enthusiasts&#39; hearts, serving as the perfect platform for experiencing games from the late 1990s and early 2000s. While most users opt for hardware of the era to ensure maximum compatibility with XP&#39;s drivers, there&#39;s something intriguing about running this classic operating system on more modern hardware.</p>



<p>I had several <a href="https://web.archive.org/web/20241208012801/https://www.intel.com/content/www/us/en/products/sku/74483/intel-nuc-kit-dc53427hye/specifications.html" rel="nofollow">Intel NUC DC53427HYE</a> devices lying around. Released in 2013, this model features an i5-3427U CPU with Intel HD Graphics 4000 and supports up to 16GB of DDR3 memory through two 8GB slots. For storage, it includes an mSATA slot. The I/O options consist of one USB 3.0 port on the front, two USB 2.0 ports on the back, Ethernet, HDMI, and two Mini Displayports. My unit also had a Wi-Fi card installed.</p>

<p>Windows XP extended support ended on April 8, 2014. As this Intel NUC is from 2013, it may just be old enough to run Windows XP properly.</p>

<p>So let&#39;s give it a shot.</p>

<h2 id="installing-windows" id="installing-windows">Installing Windows</h2>

<p>I created a bootable Windows XP installer USB using <a href="https://winsetupfromusb.en.lo4d.com/windows" rel="nofollow">WinSetupFromUSB</a>. Upon booting the installer and initiating setup, I encountered a BSOD due to missing SATA drivers.</p>

<p>While this could be resolved by switching to IDE mode in BIOS settings, I opted instead to use a <a href="https://archive.org/details/en_windows_xp_professional_sp3_nov_2013_incl_sata_drivers_202111" rel="nofollow">modified Windows XP SP3 image</a> from the Internet Archive that included built-in SATA drivers, allowing for AHCI mode operation.</p>

<p>The installation succeeded, leaving only standard driver installation remaining.</p>

<h2 id="installing-the-drivers" id="installing-the-drivers">Installing the drivers</h2>

<p>It took a bit of searching, but I was able to find the drivers needed to make everything work. I have created a <a href="https://archive.org/details/xp_x86_intel_nuc_dc53427hye_drivers" rel="nofollow">backup</a> of these drivers and uploaded them to the Internet Archive.</p>

<p>All you need to do is mount the ISO file using a tool like <a href="https://wincdemu.sysprogs.org/download/" rel="nofollow">WinCDEmu</a> and let the driver wizard search for removable media.</p>

<p>The backup contains the following drivers:</p>
<ul><li>Intel® HD Graphics 4000</li>
<li>Intel® 7 Series Chipset Family SATA AHCI Controller</li>
<li>Intel® Display Audio</li>
<li>Intel® 82579LM Gigabit Network Connection</li>
<li>Intel® Centrino® Advanced-N 6205</li>
<li>Intel® Active Management Technology – SOL</li>
<li>Intel® 7 Series/C216 Chipset Family Universal Serial Bus (USB) Controller – 1E31</li>
<li>Intel® 7 Series/C216 Chipset Family SMBus Host Controller – 1E22</li>
<li>Intel® Management Engine Interface</li>
<li>Intel® Trusted Platform Module</li></ul>

<h2 id="adding-sound" id="adding-sound">Adding sound</h2>

<p><em>Note: It is possible to get sound via HDMI without any additional hardware, if your monitor supports it</em></p>

<p>As the NUC does not come with built-in audio ports, we will need to use USB adapters. This <a href="https://amzn.to/3OuaQgj" rel="nofollow">Sabrent USB adapter</a> that does not require drivers will do just fine.</p>

<h2 id="adding-bluetooth" id="adding-bluetooth">Adding Bluetooth</h2>

<p>While Bluetooth technically works on Windows XP, from my experience the audio latency is very big. Connecting other peripherals like mice is also hit or miss. For these reasons I do not recommend Bluetooth.</p>

<p>That said, if you still would like to add Bluetooth, the <a href="https://www.redable.nl/en/product/479980/tp-link-ub400-v1-ub400-v1" rel="nofollow">TP-Link UB400 V1</a> is confirmed to work. TP-Link still has a Windows XP driver for this product <a href="https://www.tp-link.com/en/support/download/ub400/v1/" rel="nofollow">on their website</a>. <strong>Make sure you get V1 of this product</strong>. V2 will not work. Amazon sells the UB400 as well, but it is the V2 version, even though the product description says it supports Windows XP.</p>

<h2 id="conclusion" id="conclusion">Conclusion</h2>

<p>For those interested in running Windows XP, whether for retro gaming or other purposes, the Intel NUC DC53427HYE is an excellent choice, combining compact dimensions with robust performance.</p>
]]></content:encoded>
      <guid>https://ruud.je/running-windows-xp-on-the-intel-nuc-dc53427hye</guid>
      <pubDate>Thu, 16 Jan 2025 20:48:10 +0000</pubDate>
    </item>
    <item>
      <title>Redirect IE11 users in NextJS</title>
      <link>https://ruud.je/redirect-ie11-users-in-nextjs</link>
      <description>&lt;![CDATA[#javascript #nextjs&#xA;&#xA;A while ago, a client I work for decided after a lot of discussions to finally drop support for IE11. Hurray!&#xA;&#xA;Later, they decided to a show a nice page with an explanation to anyone who might still be using IE11 and encourage them to download a more modern browser.&#xA;&#xA;But because we dropped support a while ago, we didn&#39;t test in IE11 anymore, and so any page we tried to load didn&#39;t work. Trying to make the pages work would be a waste of time, because in time they might stop working again.&#xA;&#xA;So we decided to redirect all IE11 users to a simple static page.&#xA;&#xA;!--more--&#xA;&#xA;Redirects in NextJS&#xA;&#xA;Since version 9.5 it is possible to declare your redirects in next.config.js.&#xA;&#xA;The redirects property accepts an async function, that returns an array of redirects.&#xA;&#xA;The redirect in this array goes from the homepage to /iewarning.html (which is a file served from the public folder), and is set to be non-permanent, meaning that the server will return a 302 HTTP status code. If permanent is set to true, a 301 code is returned instead.&#xA;&#xA;module.exports = {&#xA;  redirects: async () =  {&#xA;    return [&#xA;      {&#xA;        source: &#39;/&#39;,&#xA;        permanent: false,&#xA;        destination: &#39;/iewarning.html&#39;,&#xA;      },&#xA;    ]&#xA;  },&#xA;}&#xA;&#xA;After restarting NextJS, the homepage should redirect you to the static file. But right now this will happen in all browsers, which is not what we want.&#xA;&#xA;Matching the User-Agent header&#xA;&#xA;So what if we only want to redirect users that are using IE11?&#xA;&#xA;That&#39;s easy! Redirects also accept a has property, that contains a list of &#34;things&#34; the request should contain. These can be headers, cookies or query parameters.&#xA;&#xA;We will be checking against a header. the User-Agent. All IE11 user-agents contain the word Trident) in their user-agent, so we can simply use a regex-like string to check if the header contains that word.&#xA;&#xA;module.exports = {&#xA;  redirects: async () =  {&#xA;    return [&#xA;      {&#xA;        source: &#39;/&#39;,&#xA;        has: [&#xA;          {&#xA;            type: &#39;header&#39;,&#xA;            key: &#39;User-Agent&#39;,&#xA;            value: &#39;(.Trident.)&#39;,&#xA;          },&#xA;        ],&#xA;        permanent: false,&#xA;        destination: &#39;/iewarning.html&#39;,&#xA;      },&#xA;    ]&#xA;  },&#xA;}&#xA;&#xA;Restart NextJS again, and go to the homepage in IE11. It will still redirect you, while other browsers will not.&#xA;&#xA;But right now the redirect only triggers on the homepage. You&#39;ll want this to trigger on all pages, which we&#39;ll do next.&#xA;&#xA;Site-wide redirect&#xA;&#xA;In order to trigger a redirect on all pages, we can make use of a regex-like string again.&#xA;&#xA;module.exports = {&#xA;  redirects: async () =  {&#xA;    return [&#xA;      {&#xA;        source: &#39;/:path((?!ie11warning.html$).)&#39;,&#xA;        has: [&#xA;          {&#xA;            type: &#39;header&#39;,&#xA;            key: &#39;user-agent&#39;,&#xA;            value: &#39;(.Trident.*)&#39;,&#xA;          },&#xA;        ],&#xA;        permanent: false,&#xA;        destination: &#39;/ie11warning.html&#39;,&#xA;      },&#xA;    ]&#xA;  },&#xA;}&#xA;&#xA;Restart NextJS one more time and now the redirect will trigger on all pages, except /ie_warning.html. The exception is required to prevent a redirect loop.&#xA;&#xA;Conclusion&#xA;&#xA;As you can see, it is quite easy to setup a redirect for a specific browser. Personally I had some trouble with the regex-like strings at first, but then again, regex is difficult anyway.&#xA;&#xA;Hope this was helpful!&#xA;]]&gt;</description>
      <content:encoded><![CDATA[<p><a href="https://ruud.je/tag:javascript" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">javascript</span></a> <a href="https://ruud.je/tag:nextjs" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">nextjs</span></a></p>

<p>A while ago, a client I work for decided after a lot of discussions to finally drop support for IE11. <em>Hurray!</em></p>

<p>Later, they decided to a show a nice page with an explanation to anyone who might still be using IE11 and encourage them to download a more modern browser.</p>

<p>But because we dropped support a while ago, we didn&#39;t test in IE11 anymore, and so any page we tried to load didn&#39;t work. Trying to make the pages work would be a waste of time, because in time they might stop working again.</p>

<p>So we decided to redirect all IE11 users to a simple static page.</p>



<h2 id="redirects-in-nextjs" id="redirects-in-nextjs">Redirects in NextJS</h2>

<p>Since version 9.5 it is possible to <a href="https://nextjs.org/docs/api-reference/next.config.js/redirects" rel="nofollow">declare your redirects</a> in <code>next.config.js</code>.</p>

<p>The <code>redirects</code> property accepts an async function, that returns an array of redirects.</p>

<p>The redirect in this array goes from the homepage to <code>/ie_warning.html</code> (which is a file served from the <code>public</code> folder), and is set to be non-permanent, meaning that the server will return a <code>302</code> HTTP status code. If <code>permanent</code> is set to <code>true</code>, a <code>301</code> code is returned instead.</p>

<pre><code class="language-typescript">module.exports = {
  redirects: async () =&gt; {
    return [
      {
        source: &#39;/&#39;,
        permanent: false,
        destination: &#39;/ie_warning.html&#39;,
      },
    ]
  },
}
</code></pre>

<p>After restarting NextJS, the homepage should redirect you to the static file. But right now this will happen in all browsers, which is not what we want.</p>

<h2 id="matching-the-user-agent-header" id="matching-the-user-agent-header">Matching the User-Agent header</h2>

<p>So what if we only want to redirect users that are using IE11?</p>

<p>That&#39;s easy! Redirects also accept a <a href="https://nextjs.org/docs/api-reference/next.config.js/redirects#header-cookie-and-query-matching" rel="nofollow">has</a> property, that contains a list of “things” the request should contain. These can be headers, cookies or query parameters.</p>

<p>We will be checking against a header. the <code>User-Agent</code>. All IE11 user-agents contain the word <a href="https://en.wikipedia.org/wiki/Trident_(software)" rel="nofollow">Trident</a> in their user-agent, so we can simply use a regex-like string to check if the header contains that word.</p>

<pre><code class="language-typescript">module.exports = {
  redirects: async () =&gt; {
    return [
      {
        source: &#39;/&#39;,
        has: [
          {
            type: &#39;header&#39;,
            key: &#39;User-Agent&#39;,
            value: &#39;(.*Trident.*)&#39;,
          },
        ],
        permanent: false,
        destination: &#39;/ie_warning.html&#39;,
      },
    ]
  },
}
</code></pre>

<p>Restart NextJS again, and go to the homepage in IE11. It will still redirect you, while other browsers will not.</p>

<p>But right now the redirect only triggers on the homepage. You&#39;ll want this to trigger on all pages, which we&#39;ll do next.</p>

<h2 id="site-wide-redirect" id="site-wide-redirect">Site-wide redirect</h2>

<p>In order to trigger a redirect on all pages, we can make use of a regex-like string again.</p>

<pre><code class="language-typescript">module.exports = {
  redirects: async () =&gt; {
    return [
      {
        source: &#39;/:path((?!ie11_warning.html$).*)&#39;,
        has: [
          {
            type: &#39;header&#39;,
            key: &#39;user-agent&#39;,
            value: &#39;(.*Trident.*)&#39;,
          },
        ],
        permanent: false,
        destination: &#39;/ie11_warning.html&#39;,
      },
    ]
  },
}
</code></pre>

<p>Restart NextJS one more time and now the redirect will trigger on all pages, except <code>/ie_warning.html</code>. The exception is required to prevent a redirect loop.</p>

<h2 id="conclusion" id="conclusion">Conclusion</h2>

<p>As you can see, it is quite easy to setup a redirect for a specific browser. Personally I had some trouble with the regex-like strings at first, but then again, regex is difficult anyway.</p>

<p>Hope this was helpful!</p>
]]></content:encoded>
      <guid>https://ruud.je/redirect-ie11-users-in-nextjs</guid>
      <pubDate>Wed, 16 Jun 2021 22:36:30 +0000</pubDate>
    </item>
    <item>
      <title>Always double-check what you copy from websites</title>
      <link>https://ruud.je/always-double-check-what-you-copy-from-websites</link>
      <description>&lt;![CDATA[#javascript #security&#xA;&#xA;Let&#39;s say you are following a guide on the internet and it provides a command for installing a package.&#xA;&#xA;sudo apt install package&#xA;&#xA;Without a second thought, you copy the command and quickly paste it in your terminal. Now imagine there was a different command in your clipboard, like this one:&#xA;&#xA;sudo rm -rf / *\do not actually run this command!&#xA;&#xA;This command forcefully and recursively deletes all your files and folders starting from the root directory. If you paste text containing a newline character in your terminal, it will automatically be executed. If your terminal has elevated permissions, because you already executed a sudo command in the same session, it will not ask for your password.&#xA;&#xA;Goodbye precious data!&#xA;&#xA;!--more--&#xA;&#xA;How can this happen?&#xA;&#xA;There are three ways how websites can trick you into copying something else:&#xA;&#xA;By using the execCommand method from the Document interface&#xA;By changing the clipboard data within the copy event&#xA;By placing hidden and/or offscreen text within the visible text&#xA;&#xA;The execCommand method&#xA;&#xA;If you&#39;ve ever copied a command from a website, you may have noticed that some offer a button that, once clicked, copies the command for you.&#xA;&#xA;These buttons use the execCommand method from the Document interface. It is deprecated and can be removed at any time, but for now it is still working.&#xA;&#xA;As the name implies, it allows you to execute a command. One of the commands you can execute is copy. By executing this command you can copy the current selection to the clipboard.&#xA;&#xA;An example is given below:&#xA;&#xA;const hiddenInput = document.querySelector(&#34;input&#34;);&#xA;hiddenInput.value = &#34;Text that should be copied&#34;;&#xA;hiddenInput.select();&#xA;document.execCommand(&#34;copy&#34;);&#xA;&#xA;The tricky part is that malicious websites can have that button copy something completely different from what you are expecting.&#xA;&#xA;So if you are on a website that you don&#39;t trust and you use one of these buttons, always double check what is currently in your clipboard by pasting it in a safe place, Notepad for example.&#xA;&#xA;Changing the clipboard data within the copy event&#xA;&#xA;Whenever you copy something using CTRL + C or the context menu, a copy event is fired. A handler for this event can modify the clipboard contents using the following code:&#xA;&#xA;const handleCopyEvent = (event: ClipboardEvent) =  {&#xA;  // Set the clipboard contents to a string of your choice.&#xA;  event.clipboardData.setData(&#xA;    &#34;text/plain&#34;,&#xA;    &#34;sudo rm -rf /&#34; // DON&#39;T RUN THIS COMMAND&#xA;  );&#xA;&#xA;  // Prevent the default action from overriding the data&#xA;  // we just set.&#xA;  event.preventDefault();&#xA;};&#xA;&#xA;The code should be self-explanatory but if you want a more detailed explanation I recommend reading Stop Rashly Copying Commands From Websites by Louis Petrik, where I originally read about this exploit. It also includes an example and a link to a browser extension that I have created. More on that in a minute.&#xA;&#xA;Placing hidden and/or offscreen text within the visible text&#xA;&#xA;When you select text on a website it becomes highlighted. You would expect that the highlighted part is exactly what you are going to copy.&#xA;&#xA;The problem is that, in some cases, invisible or offscreen text will also be part of your selection, even when it&#39;s not highlighted.&#xA;&#xA;Some examples that hide text but still allow it to be selected are:&#xA;&#xA;Using font-size: 0&#xA;Moving text offscreen with absolute or fixed positioning&#xA;Using absolute or fixed positioning in combination with transform: scale(0)&#xA;&#xA;Just to name a few.&#xA;&#xA;There is an example that demonstrates this trick. The commands that you see there contain a span that is moved offscreen.&#xA;&#xA;How to protect yourself?&#xA;&#xA;A good practice is to always double-check what is in your clipboard, by pasting it in a safe environment first. But what if your browser could warn you when your clipboard data is altered? How about a browser extension?&#xA;&#xA;Meet Copy Guard&#xA;&#xA;I have created a simple browser extension that does exactly that! It is called Copy Guard** and its source code can be found on my GitHub. By using my extension you can let your browser warn you when a website is using the second or third method.&#xA;&#xA;It injects a script which listens to the copy event. Whenever you copy something using CTRL+C or the context menu, it takes your current text selection and compares it to the data that is placed in your clipboard. Aside from that, it also checks if your text selection contains any hidden or offscreen elements.&#xA;&#xA;Available for Chrome, Firefox and Edge.&#xA;&#xA;A note on cryptocurrency&#xA;&#xA;When I posted my browser extension on Reddit, I was told that stuff like this happens within the crypto community as well, which makes perfect sense. A website could have you copy a totally different wallet address. If you were to send your precious crypto to this address, it could be lost forever.&#xA;&#xA;Something similar happened to a Reddit user once. Although this particular user probably had malware on their computer, it could also happen on the web, without any malware.&#xA;&#xA;Conclusion&#xA;&#xA;There are multiple ways how websites can trick you into copying something different from what you expect.&#xA;&#xA;Always double-check your clipboard. My browser extension can at least warn you when something is fishy, but a good practice is to paste your selection in a safe environment first, before you paste it in your terminal.&#xA;&#xA;At least do this for websites you don&#39;t trust.&#xA;]]&gt;</description>
      <content:encoded><![CDATA[<p><a href="https://ruud.je/tag:javascript" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">javascript</span></a> <a href="https://ruud.je/tag:security" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">security</span></a></p>

<p>Let&#39;s say you are following a guide on the internet and it provides a command for installing a package.</p>

<p><code>sudo apt install package</code></p>

<p>Without a second thought, you copy the command and quickly paste it in your terminal. Now imagine there was a different command in your clipboard, like this one:</p>

<p><code>sudo rm -rf /</code> <strong>*do not actually run this command!</strong></p>

<p>This command forcefully and recursively deletes all your files and folders starting from the root directory. If you paste text containing a newline character in your terminal, it will automatically be executed. If your terminal has elevated permissions, because you already executed a sudo command in the same session, it will not ask for your password.</p>

<p><em>Goodbye precious data!</em></p>



<h2 id="how-can-this-happen" id="how-can-this-happen">How can this happen?</h2>

<p>There are three ways how websites can trick you into copying something else:</p>
<ol><li>By using the <em>execCommand</em> method from the Document interface</li>
<li>By changing the clipboard data within the <em>copy</em> event</li>
<li>By placing hidden and/or offscreen text within the visible text</li></ol>

<h3 id="the-execcommand-method" id="the-execcommand-method">The execCommand method</h3>

<p>If you&#39;ve ever copied a command from a website, you may have noticed that some offer a button that, once clicked, copies the command for you.</p>

<p>These buttons use the <a href="https://developer.mozilla.org/en-US/docs/Web/API/Document/execCommand" rel="nofollow">execCommand</a> method from the <a href="https://developer.mozilla.org/en-US/docs/Web/API/Document" rel="nofollow">Document</a> interface. It is deprecated and can be removed at any time, but for now it is still working.</p>

<p>As the name implies, it allows you to execute a command. One of the commands you can execute is <code>copy</code>. By executing this command you can <em>copy</em> the current selection to the clipboard.</p>

<p>An example is given below:</p>

<pre><code class="language-javascript">const hiddenInput = document.querySelector(&#34;input&#34;);
hiddenInput.value = &#34;Text that should be copied&#34;;
hiddenInput.select();
document.execCommand(&#34;copy&#34;);
</code></pre>

<p><strong>The tricky part is that malicious websites can have that button copy something completely different from what you are expecting.</strong></p>

<p>So if you are on a website that you don&#39;t trust and you use one of these buttons, always double check what is currently in your clipboard by pasting it in a safe place, Notepad for example.</p>

<h3 id="changing-the-clipboard-data-within-the-copy-event" id="changing-the-clipboard-data-within-the-copy-event">Changing the clipboard data within the copy event</h3>

<p>Whenever you copy something using <code>CTRL + C</code> or the context menu, a <a href="https://developer.mozilla.org/en-US/docs/Web/API/Element/copy_event" rel="nofollow">copy event</a> is fired. A handler for this event can modify the clipboard contents using the following code:</p>

<pre><code class="language-typescript">const handleCopyEvent = (event: ClipboardEvent) =&gt; {
  // Set the clipboard contents to a string of your choice.
  event.clipboardData.setData(
    &#34;text/plain&#34;,
    &#34;sudo rm -rf /&#34; // DON&#39;T RUN THIS COMMAND
  );

  // Prevent the default action from overriding the data
  // we just set.
  event.preventDefault();
};
</code></pre>

<p>The code should be self-explanatory but if you want a more detailed explanation I recommend reading <a href="https://medium.com/javascript-in-plain-english/why-you-should-never-rashly-copy-commands-from-websites-4ae476441530" rel="nofollow">Stop Rashly Copying Commands From Websites</a> by Louis Petrik, where I originally read about this exploit. It also includes an example and a link to a <a href="https://github.com/roedesh/copyguard" rel="nofollow">browser extension</a> that I have created. More on that in a minute.</p>

<h3 id="placing-hidden-and-or-offscreen-text-within-the-visible-text" id="placing-hidden-and-or-offscreen-text-within-the-visible-text">Placing hidden and/or offscreen text within the visible text</h3>

<p>When you select text on a website it becomes highlighted. You would expect that the highlighted part is exactly what you are going to copy.</p>

<p>The problem is that, in some cases, invisible or offscreen text will also be part of your selection, even when it&#39;s not highlighted.</p>

<p>Some examples that hide text but still allow it to be selected are:</p>
<ul><li>Using <code>font-size: 0</code></li>
<li>Moving text offscreen with absolute or fixed positioning</li>
<li>Using absolute or fixed positioning in combination with <code>transform: scale(0)</code></li></ul>

<p>Just to name a few.</p>

<p>There is an example that <a href="https://thejh.net/misc/website-terminal-copy-paste" rel="nofollow">demonstrates this trick</a>. The commands that you see there contain a <code>span</code> that is moved offscreen.</p>

<h2 id="how-to-protect-yourself" id="how-to-protect-yourself">How to protect yourself?</h2>

<p>A good practice is to always double-check what is in your clipboard, by pasting it in a safe environment first. But what if your browser could warn you when your clipboard data is altered? How about a browser extension?</p>

<h3 id="meet-copy-guard" id="meet-copy-guard">Meet Copy Guard</h3>

<p>I have created a simple browser extension that does exactly that! It is called <strong>Copy Guard</strong> and its source code can be found on <a href="https://github.com/roedesh/copyguard" rel="nofollow">my GitHub</a>. By using my extension you can let your browser warn you when a website is using the second or third method.</p>

<p>It injects a script which listens to the copy event. Whenever you copy something using CTRL+C or the context menu, it takes your current text selection and compares it to the data that is placed in your clipboard. Aside from that, it also checks if your text selection contains any hidden or offscreen elements.</p>

<p>Available for <a href="https://chrome.google.com/webstore/detail/copy-guard/kobgknfkonpcnijbmjpepfonpnkeefij" rel="nofollow">Chrome</a>, <a href="https://addons.mozilla.org/en-US/firefox/addon/copy-guard/" rel="nofollow">Firefox</a> and <a href="https://microsoftedge.microsoft.com/addons/detail/copy-guard/nkdddmepblpmknbobcpebakjehldaebj" rel="nofollow">Edge</a>.</p>

<h2 id="a-note-on-cryptocurrency" id="a-note-on-cryptocurrency">A note on cryptocurrency</h2>

<p>When I posted my browser extension on Reddit, I was told that stuff like this happens within the crypto community as well, which makes perfect sense. A website could have you copy a totally different wallet address. If you were to send your precious crypto to this address, it could be lost forever.</p>

<p>Something similar happened to a <a href="https://www.reddit.com/r/CryptoCurrency/comments/igt0g6/warningplease_guys_be_extremely_careful/" rel="nofollow">Reddit user</a> once. Although this particular user probably had malware on their computer, it could also happen on the web, without any malware.</p>

<h2 id="conclusion" id="conclusion">Conclusion</h2>

<p>There are multiple ways how websites can trick you into copying something different from what you expect.</p>

<p>Always double-check your clipboard. My browser extension can at least warn you when something is fishy, but a good practice is to paste your selection in a safe environment first, before you paste it in your terminal.</p>

<p>At least do this for websites you don&#39;t trust.</p>
]]></content:encoded>
      <guid>https://ruud.je/always-double-check-what-you-copy-from-websites</guid>
      <pubDate>Wed, 17 Mar 2021 23:34:45 +0000</pubDate>
    </item>
  </channel>
</rss>