<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Ruud Schroën</title>
    <description>The latest articles on Forem by Ruud Schroën (@ruudje).</description>
    <link>https://forem.com/ruudje</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F199153%2Fa980dc99-8ba6-4cf8-b9e2-9d008d9ecfc4.jpeg</url>
      <title>Forem: Ruud Schroën</title>
      <link>https://forem.com/ruudje</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/ruudje"/>
    <language>en</language>
    <item>
      <title>Redirect IE11 users in NextJS</title>
      <dc:creator>Ruud Schroën</dc:creator>
      <pubDate>Thu, 17 Jun 2021 19:32:36 +0000</pubDate>
      <link>https://forem.com/ruudje/redirect-ie11-users-in-nextjs-39bo</link>
      <guid>https://forem.com/ruudje/redirect-ie11-users-in-nextjs-39bo</guid>
      <description>&lt;p&gt;A while ago, a client I work for decided after a lot of discussions to finally drop support for IE11. &lt;em&gt;Hurray!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

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

&lt;p&gt;So we decided to redirect all IE11 users to a simple static page.&lt;/p&gt;

&lt;h2&gt;
  
  
  Redirects in NextJS
&lt;/h2&gt;

&lt;p&gt;Since version 9.5 it is possible to &lt;a href="https://nextjs.org/docs/api-reference/next.config.js/redirects" rel="noopener noreferrer"&gt;declare your redirects&lt;/a&gt; in &lt;code&gt;next.config.js&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;redirects&lt;/code&gt; property accepts an async function, that returns an array of redirects.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;redirects&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;source&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;permanent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;destination&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/ie_warning.html&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;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.&lt;/p&gt;

&lt;h2&gt;
  
  
  Matching the User-Agent header
&lt;/h2&gt;

&lt;p&gt;So what if we only want to redirect users that are using IE11?&lt;/p&gt;

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

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;redirects&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;source&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;has&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
          &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;header&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;User-Agent&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;(.*Trident.*)&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="na"&gt;permanent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;destination&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/ie_warning.html&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Restart NextJS again, and go to the homepage in IE11. It will still redirect you, while other browsers will not.&lt;/p&gt;

&lt;p&gt;But right now the redirect only triggers on the homepage. You'll want this to trigger on all pages, which we'll do next.&lt;/p&gt;

&lt;h2&gt;
  
  
  Site-wide redirect
&lt;/h2&gt;

&lt;p&gt;In order to trigger a redirect on all pages, we can make use of a regex-like string again.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;redirects&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;source&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/:path((?!ie11_warning.html$).*)&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;has&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
          &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;header&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user-agent&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;(.*Trident.*)&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="na"&gt;permanent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;destination&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/ie11_warning.html&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;Hope this was helpful!&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Always double-check what you copy from websites</title>
      <dc:creator>Ruud Schroën</dc:creator>
      <pubDate>Thu, 18 Mar 2021 20:30:02 +0000</pubDate>
      <link>https://forem.com/ruudje/always-double-check-what-you-copy-from-websites-2kg3</link>
      <guid>https://forem.com/ruudje/always-double-check-what-you-copy-from-websites-2kg3</guid>
      <description>&lt;p&gt;Let's say you are following a guide on the internet and it provides a command for installing a package.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;sudo apt install package&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;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:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;sudo rm -rf /&lt;/code&gt; &lt;strong&gt;*do not actually run this command!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Goodbye precious data!&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How can this happen?
&lt;/h2&gt;

&lt;p&gt;There are three ways how websites can trick you into copying something else:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;By using the &lt;em&gt;execCommand&lt;/em&gt; method from the Document interface&lt;/li&gt;
&lt;li&gt;By changing the clipboard data within the &lt;em&gt;copy&lt;/em&gt; event&lt;/li&gt;
&lt;li&gt;By placing hidden and/or offscreen text within the visible text&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  The execCommand method
&lt;/h3&gt;

&lt;p&gt;If you'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.&lt;/p&gt;

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

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

&lt;p&gt;An example is given below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hiddenInput&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;input&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;hiddenInput&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Text that should be copied&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;hiddenInput&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;select&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execCommand&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;copy&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;The tricky part is that malicious websites can have that button copy something completely different from what you are expecting.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;So if you are on a website that you don'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.&lt;/p&gt;

&lt;h3&gt;
  
  
  Changing the clipboard data within the copy event
&lt;/h3&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleCopyEvent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ClipboardEvent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Set the clipboard contents to a string of your choice.&lt;/span&gt;
  &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;clipboardData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text/plain&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sudo rm -rf /&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="c1"&gt;// DON'T RUN THIS COMMAND&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Prevent the default action from overriding the data&lt;/span&gt;
  &lt;span class="c1"&gt;// we just set.&lt;/span&gt;
  &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;preventDefault&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;h3&gt;
  
  
  Placing hidden and/or offscreen text within the visible text
&lt;/h3&gt;

&lt;p&gt;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.&lt;/p&gt;

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

&lt;p&gt;Some examples that hide text but still allow it to be selected are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Using &lt;code&gt;font-size: 0&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Moving text offscreen with absolute or fixed positioning&lt;/li&gt;
&lt;li&gt;Using absolute or fixed positioning in combination with &lt;code&gt;transform: scale(0)&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Just to name a few.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  How to protect yourself?
&lt;/h2&gt;

&lt;p&gt;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?&lt;/p&gt;

&lt;h3&gt;
  
  
  Meet Copy Guard
&lt;/h3&gt;

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

&lt;p&gt;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.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  A note on cryptocurrency
&lt;/h2&gt;

&lt;p&gt;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.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;There are multiple ways how websites can trick you into copying something different from what you expect.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;At least do this for websites you don't trust.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>security</category>
      <category>javascript</category>
      <category>html</category>
    </item>
  </channel>
</rss>
