<?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: Shibly Noman</title>
    <description>The latest articles on DEV Community by Shibly Noman (@shibly_noman_b3dcb93c0227).</description>
    <link>https://dev.to/shibly_noman_b3dcb93c0227</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%2F3676273%2F63567b04-3bdb-48f4-972d-4b3c5b860863.jpg</url>
      <title>DEV Community: Shibly Noman</title>
      <link>https://dev.to/shibly_noman_b3dcb93c0227</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/shibly_noman_b3dcb93c0227"/>
    <language>en</language>
    <item>
      <title>Implementation Mistakes by Devs: How you should not use useEffect</title>
      <dc:creator>Shibly Noman</dc:creator>
      <pubDate>Thu, 08 Jan 2026 06:35:16 +0000</pubDate>
      <link>https://dev.to/shibly_noman_b3dcb93c0227/implementation-mistakes-by-devs-how-you-should-not-use-useeffect-369a</link>
      <guid>https://dev.to/shibly_noman_b3dcb93c0227/implementation-mistakes-by-devs-how-you-should-not-use-useeffect-369a</guid>
      <description>&lt;p&gt;The straightforward answer to the question is, We often find ourselves writing brute force code. Sometimes we are tempted to copy codes without understanding the fundamentals.&lt;/p&gt;

&lt;p&gt;I think, instead of asking “Why we should not….” it is more proper to ask “How we should not…” or “Where we should not….”&lt;/p&gt;

&lt;h3&gt;
  
  
  What is an Effect?
&lt;/h3&gt;

&lt;p&gt;React documentation literature says, Effects are an escape hatch from the React paradigm. Well, what do they mean by that?  Effects in React let you connect your components with things outside React. Like non-React widgets or the browser. Generally we use useEffect either for transforming data for rendering or handling user events.&lt;/p&gt;

&lt;p&gt;We don’t have non-React widgets on the server. And that's why we don’t have useEffect in the server component. Does that ring a bell? &lt;/p&gt;

&lt;p&gt;If you're just updating a component based on its own state or props, you don't need an Effect.  useEffect introduces additional computations and overhead to your component lifecycle. Interesting thing is, useEffect is not inherently slower. Improper usage of useEffect can potentially introduce performance issues. &lt;/p&gt;

&lt;p&gt;And as the rule of state- management-101, “Do not replicate!”&lt;/p&gt;

&lt;p&gt;So let's have some implementation details where we can avoid useEffect.&lt;/p&gt;

&lt;p&gt;Updating state based on props or state:&lt;/p&gt;

&lt;p&gt;When something can be calculated from the existing props or state, don’t put it in state. Instead, calculate it during rendering.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function Form() {
 const [firstName, setFirstName] = useState('Taylor');
 const [lastName, setLastName] = useState('Swift');

 // 🔴 Avoid: redundant state and unnecessary Effect
 const [fullName, setFullName] = useState('');
 useEffect(() =&amp;gt; {
   setFullName(firstName + ' ' + lastName);
 }, [firstName, lastName]);
 // ...
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is more complicated than necessary. It is inefficient too: it does an entire render pass with a stale value for fullName, then immediately re-renders with the updated value. Instead this can be done,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// ✅ this is calculated during rendering
 const fullName = firstName + ' ' + lastName;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or we can give the values to the dom&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// ✅ Will re-render
 &amp;lt;&amp;gt;{firstName} {lastName}&amp;lt;/&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Child component always re-renders if the prop value is changed. So what if we have to reset all component states depending on prop value, how do we do that?&lt;/p&gt;

&lt;p&gt;For example we want to clear out the comment state variable (or refetch from state) whenever the userId changes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export default function ProfilePage({ userId }) {
 const [comment, setComment] = useState('');

 // 🔴 Avoid: Resetting state on prop change in an Effect
 useEffect(() =&amp;gt; {
   setComment(''); // or have a selector
 }, [userId]);
 // ...
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instead of doing this, we can split the component and pass a unique key prop to the Profile component,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export default function ProfilePage({ userId }) {
 return (
   &amp;lt;Profile
     userId={userId}
     key={userId}
   /&amp;gt;
 );
}

function Profile({ userId }) {
 // ✅ This and any other state below will reset on key change automatically
 const [comment, setComment] = useState('');
 // ...
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Again, why do this? Because by passing userId as a key to the Profile component, you’re asking React to treat two Profile components with different userId as two different components that should not share any state. Whenever the key (which you’ve set to userId) changes, React will recreate the DOM and reset the state of the Profile component and all of its children. Now the comment field will clear out automatically when navigating between profiles.&lt;/p&gt;

&lt;p&gt;What if we want to adjust some of the state depending on props value but not all of it.&lt;br&gt;
For example we might tempted to do this,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function List({ items }) {
 const [isReverse, setIsReverse] = useState(false);
 const [selection, setSelection] = useState(null);

 // 🔴 Avoid: Adjusting state on prop change in an Effect
 useEffect(() =&amp;gt; {
   setSelection(null);
 }, [items]);
 // ...
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Again, this is not ideal. Every time the items change, the List and its child components will render with a stale selection value at first.&lt;/p&gt;

&lt;p&gt;Instead we can do this,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function List({ items }) {
 const [isReverse, setIsReverse] = useState(false);
 const [selection, setSelection] = useState(null);

 // Better: Adjust the state while rendering
 const [prevItems, setPrevItems] = useState(items);
 if (items !== prevItems) {
   setPrevItems(items);
   setSelection(null);
 }
 // ...
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Storing information from previous renders like this can be hard to understand, but it’s better than updating the same state in an Effect. Although this pattern is more efficient than an Effect, most components shouldn’t need it either. It’s better to check whether we can reset all states with a key or calculate everything during rendering instead.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function List({ items }) {
 const [isReverse, setIsReverse] = useState(false);
 const [selectedId, setSelectedId] = useState(null);
 // ✅ Best: Calculate everything during rendering
 const selection = items.find(item =&amp;gt; item.id === selectedId) ?? null;
 // ...
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sharing logic between event handlers:&lt;br&gt;
Let’s say you have a product page with two buttons (Buy and Checkout) that both let you buy that product. You want to show a notification whenever the user puts the product in the cart. Calling showNotification() in both buttons’ click handlers feels repetitive so you might be tempted to place this logic in an Effect:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function ProductPage({ product, addToCart }) {
 // 🔴 Avoid: Event-specific logic inside an Effect
 useEffect(() =&amp;gt; {
   if (product.isInCart) {
     showNotification(`Added ${product.name} to the shopping cart!`);
   }
 }, [product]);

 function handleBuyClick() {
   addToCart(product);
 }

 function handleCheckoutClick() {
   addToCart(product);
   navigateTo('/checkout');
 }
 // ...
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This Effect is unnecessary. It will also most likely cause bugs. For example, let’s say that your app “remembers” the shopping cart between the page reloads. If you add a product to the cart once and refresh the page, the notification will appear again.&lt;br&gt;
Better we can write event specific methods&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function ProductPage({ product, addToCart }) {
 // ✅ Good: Event-specific logic is called from event handlers
 function buyProduct() {
   addToCart(product);
   showNotification(`Added ${product.name} to the shopping cart!`);
 }

 function handleBuyClick() {
   buyProduct();
 }

 function handleCheckoutClick() {
   buyProduct();
   navigateTo('/checkout');
 }
 // ...
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This both removes the unnecessary Effect and fixes the bug.&lt;/p&gt;

&lt;h3&gt;
  
  
  Chains of computations
&lt;/h3&gt;

&lt;p&gt;This is one of the most common mistakes we make. Sometimes there can be a case where we need to change one state depending on the other state in the component.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function Game() {
 const [card, setCard] = useState(null);
 const [goldCardCount, setGoldCardCount] = useState(0);
 const [round, setRound] = useState(1);
 const [isGameOver, setIsGameOver] = useState(false);

 // 🔴 Avoid: Chains of Effects that adjust the state solely to trigger each other
 useEffect(() =&amp;gt; {
   if (card !== null &amp;amp;&amp;amp; card.gold) {
     setGoldCardCount(c =&amp;gt; c + 1);
   }
 }, [card]);

 useEffect(() =&amp;gt; {
   if (goldCardCount &amp;gt; 3) {
     setRound(r =&amp;gt; r + 1)
     setGoldCardCount(0);
   }
 }, [goldCardCount]);

 useEffect(() =&amp;gt; {
   if (round &amp;gt; 5) {
     setIsGameOver(true);
   }
 }, [round]);

 useEffect(() =&amp;gt; {
   alert('Good game!');
 }, [isGameOver]);

 function handlePlaceCard(nextCard) {
   if (isGameOver) {
     throw Error('Game already ended.');
   } else {
     setCard(nextCard);
   }
 }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;the component (and its children) have to re-render between each set call in the chain. In the example above, in the worst case (setCard → render → setGoldCardCount → render → setRound → render → setIsGameOver → render) there are three unnecessary re-renders of the tree below.&lt;br&gt;
Even if performance is not the case, as our code evolves, it gets harder and harder to maintain and add new requirements to the code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function Game() {
 const [card, setCard] = useState(null);
 const [goldCardCount, setGoldCardCount] = useState(0);
 const [round, setRound] = useState(1);

 // ✅ Calculate what you can during rendering
 const isGameOver = round &amp;gt; 5;

 function handlePlaceCard(nextCard) {
   if (isGameOver) {
     throw Error('Game already ended.');
   }

   // ✅ Calculate all the next state in the event handler
   setCard(nextCard);
   if (nextCard.gold) {
     if (goldCardCount &amp;lt;= 3) {
       setGoldCardCount(goldCardCount + 1);
     } else {
       setGoldCardCount(0);
       setRound(round + 1);
       if (round === 5) {
         alert('Good game!');
       }
     }
   }
 }

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Caching expensive calculations:
&lt;/h3&gt;

&lt;p&gt;They are recommending to use useMemo instead of useEffect. But from React 19, they do not suggest useMemo anymore. Not sure how to solve it another way. No worries, we will see (If you know, please share).&lt;/p&gt;

&lt;p&gt;Notifying parent components about state changes or passing data to the parent:&lt;br&gt;
Passing data to higher order components is the root of all EVIL. So let’s not think about ‘passing data to the parent’ at all. For your own sake use state management libraries.&lt;/p&gt;

&lt;p&gt;Footnote: &lt;/p&gt;

&lt;p&gt;So the elephant in the room, Why follow these approaches? &lt;/p&gt;

&lt;p&gt;In my opinion all the actions, interactions, dependencies, lifecycle, and all possible approaches to solve a particular problem, breaks down to one or another data structure. &lt;/p&gt;

&lt;p&gt;So why is it that some of the data structure is faster and some are slower, why is that? &lt;/p&gt;

&lt;p&gt;Honestly. I don’t know.&lt;/p&gt;

&lt;p&gt;There is something called time space trade off. This problem is as old as computer engineering itself. This is something all programmers have to deal with. So it is important to follow standard norms by understanding the underlying mechanism of our code.&lt;/p&gt;

&lt;p&gt;But we are talking about useEffect here, Aren’t we? We do not think about memories while writing. We don’t manage garbage values, and don't have to think about abstract stuff. React does all the heavy lifting.&lt;/p&gt;

&lt;p&gt;But do you know, React does not even understand “jsx”? 🙂&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>react</category>
      <category>programming</category>
      <category>reactjsdevelopment</category>
    </item>
    <item>
      <title>MongoBleed: A Heartbleed-Class Memory Disclosure in MongoDB</title>
      <dc:creator>Shibly Noman</dc:creator>
      <pubDate>Tue, 30 Dec 2025 07:32:08 +0000</pubDate>
      <link>https://dev.to/shibly_noman_b3dcb93c0227/mongobleed-a-heartbleed-class-memory-disclosure-in-mongodb-4ji3</link>
      <guid>https://dev.to/shibly_noman_b3dcb93c0227/mongobleed-a-heartbleed-class-memory-disclosure-in-mongodb-4ji3</guid>
      <description>&lt;p&gt;MongoBleed is a recently disclosed pre-authentication memory disclosure vulnerability in MongoDB Server, formally tracked as CVE-2025-14847. The flaw resides in the zlib-based network message compression logic, where incorrect handling of client-supplied length metadata can cause the server to return uninitialized heap memory to remote attackers without requiring authentication. This class of defect has been widely compared to the infamous Heartbleed memory leak in OpenSSL- therefore the name "MongoBleed" - because both arise from a mistrust of length/size metadata that leads to silent memory exposure.&lt;/p&gt;

&lt;h2&gt;
  
  
  Background: MongoDB Wire Protocol and Compression:
&lt;/h2&gt;

&lt;p&gt;Modern MongoDB servers communicate with clients using the &lt;strong&gt;OP_MSG&lt;/strong&gt; wire protocol. To reduce bandwidth and latency, MongoDB supports optional message compression using algorithms such as zlib, snappy, zstd.&lt;/p&gt;

&lt;p&gt;MongoDB network flow (simplified):&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%2Fodaduwsqzvmbqfj4xvil.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%2Fodaduwsqzvmbqfj4xvil.png" alt="MongoDb Network Flow Simplified" width="301" height="877"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The bug occurs before authentication, specifically inside message decompression &amp;amp; buffer handling.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Core Bug: Length Trust Violation:
&lt;/h2&gt;

&lt;p&gt;The vulnerability stems from &lt;strong&gt;improper length validation&lt;/strong&gt; within the MongoDB &lt;code&gt;OP_COMPRESSED&lt;/code&gt; handler. When a client sends a compressed message, the server trusts the user-provided &lt;code&gt;uncompressed_size&lt;/code&gt; value and uses it to allocate a memory buffer on the heap.&lt;/p&gt;

&lt;p&gt;The exploit occurs when an attacker specifies an &lt;code&gt;uncompressed_size&lt;/code&gt; that is intentionally much larger than the actual decompressed data. While the decompression process fills the start of the buffer, the remaining "slack space" is left untouched and uninitialized. Because this memory is not zeroed out, it still contains &lt;strong&gt;"stale" data&lt;/strong&gt; from previous heap allocations such as session tokens, credentials, or TLS keys. When the server reflects the full buffer back to the client, it inadvertently leaks this sensitive internal memory.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step-by-Step Memory Timeline
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Step 1: Malicious packet arrives
&lt;/h3&gt;

&lt;p&gt;Attacker sends&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;Compressed&lt;/span&gt; &lt;span class="nx"&gt;Payload&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;Declared&lt;/span&gt; &lt;span class="nx"&gt;uncompressed&lt;/span&gt; &lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;64&lt;/span&gt; &lt;span class="nx"&gt;KB&lt;/span&gt;
&lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;Real&lt;/span&gt; &lt;span class="nx"&gt;decompressed&lt;/span&gt; &lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;120&lt;/span&gt; &lt;span class="nx"&gt;bytes&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 2: Server allocates heap memory
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;char&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;buf&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;malloc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;65536&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// based on uncompressed_size&lt;/span&gt;
&lt;span class="c1"&gt;// ** malloc does NOT zero memory&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Heap may contain&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="nx"&gt;valid&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;leftover&lt;/span&gt; &lt;span class="nx"&gt;heap&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;sensitive&lt;/span&gt; &lt;span class="nx"&gt;fragments&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 3: Decompression happens
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;actual_len&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;inflate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;zlib_stream&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;buf&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;119&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;     &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="nx"&gt;valid&lt;/span&gt; &lt;span class="nx"&gt;decompressed&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;
&lt;span class="nx"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;120&lt;/span&gt;&lt;span class="p"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;65535&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="nx"&gt;untouched&lt;/span&gt; &lt;span class="nx"&gt;memory&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 4: Fatal mistake wrong length used (This is the bug)
&lt;/h3&gt;

&lt;p&gt;Instead of sending:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;actual_len&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The server sends:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;declared_uncompressed_size&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The attacker receives raw heap memory returned by the system, which may include data from other users’ queries, credentials still resident in memory, internal data structures, and occasionally readable secrets that were never intended to be exposed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding BSON in the Context
&lt;/h2&gt;

&lt;p&gt;When a compressed OP_MSG is received, MongoDB first parses the compression header, then invokes the zlib inflate algorithm to expand the payload into a heap buffer sized according to the client-supplied uncompressed length. The BSON parser is subsequently invoked on this buffer and relies on BSON’s self-describing structure to traverse the data. If zlib inflation produces fewer bytes than the declared size, the remaining portion of the buffer contains uninitialized heap memory. Because the parser and subsequent response handling operate on the full allocated buffer rather than the actual number of bytes produced by zlib, adjacent heap data from prior requests may be inadvertently exposed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Is Pre-Authentication
&lt;/h2&gt;

&lt;p&gt;This vulnerability manifests &lt;strong&gt;before authentication&lt;/strong&gt; because MongoDB must process and decompress incoming network messages &lt;em&gt;prior&lt;/em&gt; to understanding their semantic intent. Compression handling occurs ahead of message parsing, meaning the server is required to decompress the payload in order to determine what command the client is attempting to execute, including authentication commands themselves. As a result, the decompression logic is invoked without any prior trust boundary enforcement. Compounding this issue, authentication credentials and related security material may already be present in heap memory from previous connections or internal operations, making them susceptible to exposure when uninitialized heap buffers are inadvertently returned to the client.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why the Server Does Not Crash
&lt;/h2&gt;

&lt;p&gt;MongoBleed does not cause the server to crash because it is &lt;strong&gt;not a memory corruption vulnerability&lt;/strong&gt;, but rather a &lt;strong&gt;buffer over-read&lt;/strong&gt;. Unlike buffer overflows, use-after-free conditions, or double-free bugs, which typically result in process termination or exploitable control-flow corruption, this flaw merely causes the server to read and transmit memory that it should not. Since the accessed memory is still valid heap space and no illegal writes occur, MongoDB continues operating normally. This silent failure mode allows the server to leak sensitive data without triggering crashes, alerts, or obvious instability, significantly complicating detection and incident response.&lt;/p&gt;

&lt;h2&gt;
  
  
  Affected Versions
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Version&lt;/th&gt;
&lt;th&gt;Affected Range&lt;/th&gt;
&lt;th&gt;Fixed Version&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;8.2.x&lt;/td&gt;
&lt;td&gt;8.2.0–8.2.2&lt;/td&gt;
&lt;td&gt;8.2.3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8.0.x&lt;/td&gt;
&lt;td&gt;8.0.0–8.0.16&lt;/td&gt;
&lt;td&gt;8.0.17&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7.0.x&lt;/td&gt;
&lt;td&gt;7.0.0–7.0.27&lt;/td&gt;
&lt;td&gt;7.0.28&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6.0.x&lt;/td&gt;
&lt;td&gt;6.0.0–6.0.26&lt;/td&gt;
&lt;td&gt;6.0.27&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5.0.x&lt;/td&gt;
&lt;td&gt;5.0.0–5.0.31&lt;/td&gt;
&lt;td&gt;5.0.32&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Recommended Actions for Security Teams
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Upgrade immediately&lt;/strong&gt; to a patched MongoDB version: 8.2.3, 8.0.17, 7.0.28, 6.0.27, 5.0.32, or 4.4.30&lt;/li&gt;
&lt;li&gt;If patching is not possible, &lt;strong&gt;disable zlib compression&lt;/strong&gt; and use &lt;code&gt;snappy&lt;/code&gt;, &lt;code&gt;zstd&lt;/code&gt;, or disable compression entirely&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Restrict network exposure&lt;/strong&gt; by removing MongoDB from the public internet and enforcing firewall or private network access&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Monitor MongoDB logs&lt;/strong&gt; for anomalous pre-authentication behavior or suspicious connection patterns&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>news</category>
      <category>mongodb</category>
      <category>cybersecurity</category>
      <category>networking</category>
    </item>
    <item>
      <title>How a Serialization Flaw in React 19 Server Components Led to Remote Code Execution</title>
      <dc:creator>Shibly Noman</dc:creator>
      <pubDate>Wed, 24 Dec 2025 06:12:43 +0000</pubDate>
      <link>https://dev.to/shibly_noman_b3dcb93c0227/how-a-serialization-flaw-in-react-19-server-components-led-to-remote-code-execution-3h0e</link>
      <guid>https://dev.to/shibly_noman_b3dcb93c0227/how-a-serialization-flaw-in-react-19-server-components-led-to-remote-code-execution-3h0e</guid>
      <description>&lt;p&gt;A critical security incident in early December 2025 drew widespread attention when the React ecosystem was found to contain a maximum-severity remote code execution vulnerability, tracked as CVE-2025-55182 and colloquially dubbed “React2Shell.” This flaw, which affects React Server Components (RSC) and frameworks built on top of them, could allow an unauthenticated attacker to execute arbitrary code on vulnerable servers with a single crafted HTTP request.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Was the Vulnerability?
&lt;/h2&gt;

&lt;p&gt;To understand the vulnerability, it is necessary to first examine how &lt;strong&gt;React 19 Server Components&lt;/strong&gt; exchange data between the server and the client.&lt;/p&gt;

&lt;p&gt;React Server Components do not transmit plain JSON. Instead, they rely on a specialized serialization format known as the &lt;strong&gt;Flight protocol&lt;/strong&gt;, which is capable of encoding complex JavaScript constructs such as references, deferred values, and asynchronous boundaries. Within this protocol, a serialized payload can represent unresolved asynchronous data effectively indicating that a particular value is a Promise whose resolution will be provided at a later stage.&lt;/p&gt;

&lt;p&gt;This bidirectional communication model allows the client to send references back to the server to complete the rendering process. While this design enables efficient streaming and incremental rendering, it also introduces significant complexity and expands the attack surface.&lt;/p&gt;

&lt;p&gt;At the core of the vulnerability is the server-side logic responsible for parsing and reconstructing these serialized values. Specifically, the method responsible for parsing model strings within React Server Components defines how incoming Flight payloads are deserialized into executable JavaScript structures on the server. Insufficient validation during this reconstruction process ultimately enabled the exploitation of the serialization pipeline.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function parseModelString(
    response: Response,
    obj: Object,
    key: string,
    value: string,
    reference: void | string,
) : any {
    switch (value[1]) {
        ...
            case 'B': {
                // Blob
                const id = parseInt(value.slice(2), 16);
                const prefix = response._prefix;
                const blobKey = prefix + id;
                // We should have this backingEntry in the store already because we emitted
                // it before referencing it. It should be a Blob.
                const backingEntry: Blob = (response._formData.get(blobKey): any);
                return backingEntry;
            }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  How the Serialization Vulnerability Works
&lt;/h2&gt;

&lt;p&gt;The vulnerability stems from how React Server Components reconstruct complex JavaScript objects from serialized Flight payloads. During deserialization, the server failed to enforce strict validation on property access paths, allowing crafted payloads to reference inherited and magic properties such as &lt;code&gt;constructor&lt;/code&gt;, &lt;code&gt;__proto__&lt;/code&gt;, or &lt;code&gt;prototype&lt;/code&gt;. By injecting a malicious &lt;code&gt;then&lt;/code&gt; property, an attacker could create a &lt;em&gt;thenable&lt;/em&gt; object, which the JavaScript runtime automatically attempts to resolve as a Promise. Through chained references (for example, resolving &lt;code&gt;then&lt;/code&gt; via the prototype chain), the deserialization logic could be coerced into invoking the JavaScript &lt;code&gt;Function&lt;/code&gt; constructor, resulting in arbitrary code execution. This exploit was possible because the server implicitly trusted the payload structure and did not differentiate between own properties and inherited properties during model reconstruction.&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%2Fyp887q83p0zi2n4upbbw.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%2Fyp887q83p0zi2n4upbbw.png" alt="vulnerability_analysis_react_19_ssr" width="286" height="787"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Example of a Crafted Flight Payload (Simplified):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const _payload = {
...
    1 : {
        status: “resolve_model”,
        reason: 0,
        _response: {
            _prefix: “console.log('Hello World!')”,
            _fromData: {
                 get: “$1: then:constructor”,
                }
        },
        then: “$1:then”,
        value:’{”then”: “$B”}’
    },
    2: “$@1”
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why this works (at a high level):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The payload introduces a fake &lt;code&gt;then&lt;/code&gt; property, making the object appear promise-like.&lt;/li&gt;
&lt;li&gt;The de-serializer resolves references without restricting prototype traversal.&lt;/li&gt;
&lt;li&gt;Reference chaining allows access to inherited constructors.&lt;/li&gt;
&lt;li&gt;Implicit Promise resolution triggers execution during model reconstruction.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Mitigation &amp;amp; Fix Overview
&lt;/h2&gt;

&lt;p&gt;Following the disclosure of &lt;strong&gt;CVE-2025-55182&lt;/strong&gt;, the React core team, in coordination with platform and infrastructure providers, implemented a series of layered mitigations to neutralize the immediate exploitation vector and to strengthen the overall security posture of React Server Components.&lt;/p&gt;

&lt;p&gt;These remediation efforts focus on &lt;strong&gt;robust deserialization safeguards&lt;/strong&gt;, &lt;strong&gt;reduced protocol expressiveness&lt;/strong&gt;, and &lt;strong&gt;the removal of implicit execution semantics&lt;/strong&gt; that previously enabled unsafe behavior.&lt;/p&gt;

&lt;p&gt;The key mitigation measures include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Strict Property Validation During Deserialization&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Enforcement of explicit property allow-lists and ownership checks to prevent access to inherited or magic properties during model reconstruction.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Prototype-less Object Reconstruction&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Use of objects without prototype chains to eliminate unintended access to JavaScript runtime primitives and inherited behavior.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Explicit Promise Handling (Elimination of Implicit Thenables)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Removal of reliance on JavaScript’s automatic thenable resolution in favor of explicit and controlled async handling.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Constrained Flight Protocol Grammar&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Reduction of permissible reference paths, indirection depth, and token combinations to limit the protocol’s attack surface.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Defense-in-Depth Runtime Guards&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Introduction of runtime assertions, depth limits, and fail-fast mechanisms to prevent unsafe execution even in the presence of malformed payloads.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Collectively, these measures eliminate the known remote code execution vector and significantly raise the barrier for similar classes of deserialization-based vulnerabilities in future releases.&lt;/p&gt;

&lt;h3&gt;
  
  
  Guidance for Application Developers
&lt;/h3&gt;

&lt;p&gt;While the vulnerability was in React itself, developers should still adopt the following best practices:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Keep React and framework dependencies fully up to date&lt;/li&gt;
&lt;li&gt;Avoid exposing Server Component endpoints to untrusted clients&lt;/li&gt;
&lt;li&gt;Apply authentication and CSRF protections to RSC routes&lt;/li&gt;
&lt;li&gt;Monitor for abnormal payload sizes or resolution patterns&lt;/li&gt;
&lt;li&gt;Treat framework serialization as untrusted input&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>react</category>
      <category>security</category>
      <category>nextjs</category>
      <category>typescript</category>
    </item>
  </channel>
</rss>
