CVE-2026-104861
Executive Summary
CVE-2026-104861 is an uncontrolled resource consumption (CWE-400) vulnerability in the probe-image-size Node.js npm package affecting all versions prior to 7.4.0. An attacker who can influence the image data passed to the library—directly via buffer, via a streaming source, or via a remote URL through the probe.sync(), probe(stream), and probe(url) entry points—can craft input containing many < characters without a closing >, forcing a catastrophic regular-expression scan that pins the Node.js event loop at full CPU. Successful exploitation results in denial of service for the hosting Node.js process and, because the event loop is single-threaded and cooperatively scheduled, all concurrent requests served by that process. The CVSS 3.1 base score is 7.5 (High), driven entirely by an Availability impact of High with no confidentiality or integrity impact.
This record — and 170,000+ others — are available via the ValtersIT API. One endpoint replaces five: NVD + GitHub CVE + CISA KEV + EPSS + Nuclei + Exploit-DB, unified.
No signup required
Technical Analysis
The probe-image-size library is designed to determine the dimensions of an image without downloading the entire file. The vulnerable behavior is concentrated in two files named explicitly in the NVD description: lib/parse_sync/svg.js and lib/parse_stream/svg.js. Both use the searching regular expression:
/<[-_.:a-zA-Z0-9][^>]*>/
The regex attempts to match a tag-like token beginning with <, followed by a name character from the class [-_.:a-zA-Z0-9], followed by any run of non-> characters, terminated by >. When attacker-controlled SVG data contains many < characters but no closing > character, the engine must repeatedly scan to the end of the available input from each successive starting position before concluding no match exists. This produces super-linear (typically quadratic) scanning cost that scales with the size of the crafted region. Because the pattern is a searching expression applied iteratively, every < spawns a fresh scan toward the terminator, and the absence of that terminator prevents early exit.
Two distinct amplification paths arise from this single regex:
Synchronous path (
lib/parse_sync/svg.js). The synchronous parser converts and scans the full supplied buffer without applying an input cap. A single large buffer composed of a long run of<characters (or a benign-looking SVG prefix followed by such a run) is handed straight to the scanning routine. One call toprobe.sync()with such a buffer consumes CPU proportional to the blow-up factor of the scan, blocking the event loop for the entire duration because synchronous JavaScript cannot yield.Streaming path (
lib/parse_stream/svg.js). The streaming parser reparses the complete accumulated SVG prefix for every received chunk. This means the scanning cost is not paid once but re-incurred on each chunk boundary: chunk n rescans bytes 1..n. An attacker who controls chunking—for example, by supplying a slow or adversarially fragmented remote stream viaprobe(stream)orprobe(url)—can drive the number of reparses arbitrarily high and amplify the total CPU cost far beyond the raw input size. The NVD description explicitly notes that "attacker-controlled chunking can amplify the streaming cost."
The attack surface is any application that passes untrusted image data to these entry points. That includes services that accept user-uploaded images, services that fetch images from URLs an attacker can influence (SSRF-adjacent scenarios where the fetched content is attacker-controlled), and pipelines that stream remote or third-party image bytes into the library. The vulnerability is a pure algorithmic-complexity / ReDoS-class resource exhaustion issue: there is no memory corruption, no code execution, and no data disclosure. The security impact is confined to availability, which is reflected in the CVSS vector (C:N/I:N/A:H).
Notably, the fix in 7.4.0 addresses the described behavior, but as of this writing no patch commits, vendor advisories, or OSV package records are tracked, so patch confidence is 0/4 and the vulnerability should be treated as UNPATCHED for planning purposes.
Exploitation Scenarios
No public proof-of-concept, exploit code, or Nuclei template is available for CVE-2026-104861. The attack chain below is inferred from the vulnerability class (CWE-400, catastrophic regex scanning) and the entry points named in the NVD description. No specific hypothetical function names, parameters, or endpoints beyond those explicitly named (probe.sync(), probe(stream), probe(url), lib/parse_sync/svg.js, lib/parse_stream/svg.js) are asserted.
Reconnaissance / target identification. An attacker identifies a Node.js service that uses
probe-image-sizeto inspect untrusted images. This can often be fingerprinted by submitting an SVG image and observing dimension-extraction behavior in responses, image thumbnails, or downstream metadata (width/height fields), or by triggering error messages that reference the library. Targets of interest are services that accept image uploads, fetch remote images on behalf of users, or run image-processing pipelines.Triggering the flaw. The attacker supplies malformed SVG content that contains a long sequence of
<characters without a closing>, reaching one of the three entry points. For the synchronous case, the crafted bytes are delivered as a buffer toprobe.sync(), and the whole buffer is scanned unpaced. For the streaming case, the crafted bytes are delivered throughprobe(stream)orprobe(url), where the parser reparses the accumulated SVG prefix on every chunk.Payload / execution method (vulnerability-class level). There is no code payload; the "payload" is the malformed input itself. The attacker does not execute code—they simply induce the regex engine to perform a pathological scan. The only attacker-controlled variables are (a) the number of
<characters without a terminating>and (b) in the streaming case, the chunk boundaries and delivery pacing. No buffer overflow, injection, or privilege escalation is involved.Amplification via chunking. Against
probe(stream)/probe(url), the attacker fragments the malicious SVG into many small chunks (or controls a remote server that does so). Because the streaming parser reparses the full accumulated prefix per chunk, CPU cost compounds with each chunk, letting the attacker multiply the DoS effect for a fixed byte count.Post-exploitation impact. The Node.js event loop is blocked at full CPU for the duration of the pathological scan. Because Node.js is single-threaded, every other request handled by that process is stalled or dropped for the duration. Repeated or concurrent submissions can sustain the stall, producing a denial of service against the application or its ingress path. There is no confidentiality or integrity impact and no lateral movement enabled by this flaw itself.
Impact Assessment
The CVSS 3.1 base score is 7.5 (High) with vector CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H. This translates into the following impact profile:
- Attack Vector (AV:N — Network): Exploitable remotely; no local access required.
- Attack Complexity (AC:L — Low): No special conditions or race windows are required; malformed SVG content reliably triggers the pathological scan.
- Privileges Required (PR:N — None): No authentication or authorization is needed.
- User Interaction (UI:N — None): No victim must click or otherwise cooperate; the flaw triggers on input processing.
- Scope (S:U — Unchanged): The impact is confined to the vulnerable component.
- Confidentiality (C:N — None) / Integrity (I:N — None): No data exposure or modification.
- Availability (A:H — High): The primary and only impact. Successful exploitation blocks the Node.js event loop, degrading or halting service for all tenants of the affected process.
Business impact. Any web-facing or internal Node.js service that uses probe-image-size on untrusted image data is exposed. Because the entry points accept buffer, stream, and URL inputs, the blast radius includes image-upload endpoints, media proxy/thumbnail services, and any component that fetches and probes remote images. A single crafted submission can stall a shared event loop, and mild concurrency can cause sustained unavailability of the entire process—not merely the offending request. Downstream effects include failed health checks, cascading timeouts, and potential autoscaler thrash. There is no data breach risk from this CVE, so the primary business concern is service availability and the operational cost of mitigation.
Detection Guidance
Sigma Rule
title: Probe-Image-Size SVG Regex DoS - Suspicious Malformed SVG Input
id: 3f9b1d2a-1048-6cve-2026-104861
status: experimental
description: Detects submission of SVG-like content containing long runs of '<' without a closing '>' consistent with CVE-2026-104861 (probe-image-size < 7.4.0)
references:
- https://nvd.nist.gov/vuln/detail/CVE-2026-104861
author: Valters IT Threat Intelligence
date: 2026/01/01
logsource:
category: webserver
product: nodejs
detection:
selection_content:
- body|re: '<{20,}'
- body|re: '<[-_.:a-zA-Z0-9][^>]{200,}$'
selection_svg:
body|contains:
- '<svg'
- 'data:image/svg'
condition: selection_svg and selection_content
fields:
- client_ip
- request_uri
- user_agent
falsepositives:
- Legitimate SVG documents with unusually long unclosed tag fragments (rare)
level: high
YARA Rule
rule CVE_2026_104861_probe_image_size_svg_regex_dos
{
meta:
description = "Detects malformed SVG input crafted to trigger catastrophic regex scan in probe-image-size < 7.4.0 (CVE-2026-104861)"
author = "Valters IT Threat Intelligence"
reference = "https://nvd.nist.gov/vuln/detail/CVE-2026-104861"
date = "2026-01-01"
severity = "high"
strings:
$svg1 = "<svg" ascii nocase
$svg2 = "<?xml" ascii nocase
$unclosed = /<[-_.:a-zA-Z0-9]{0,64}(\s[^>]{0,256}){0,8}$/ ascii
condition:
($svg1 or $svg2) and #unclosed > 0
}
Suricata IDS Rule
alert http any any -> any any (msg:"CVE-2026-104861 probe-image-size SVG Regex DoS Attempt"; flow:established,to_server; http.method; content:"POST"; http.request_body; content:"<svg"; nocase; content:"<"; nocase; pcre:"/<{20,}/R"; threshold:type both, track by_src, count 5, seconds 60; classtype:attempted-dos; sid:2026104861; rev:1; reference:cve,2026-104861;)
Elastic Detection
sequence by source.ip with maxspan=30s
[http where http.request.method == "POST" and
stringContains(http.request.body, "<svg")]
[http where http.request.method == "POST" and
stringContains(http.request.body, "<")]
Splunk SPL Query
index=web sourcetype=access_combined_* OR sourcetype=nodejs
| eval body=coalesce(request_body, form_data, post_data)
| where like(body, "%<svg%") AND match(body, "<{20,}")
| stats count AS malformed_svg_requests,
values(src_ip) AS source_ips,
values(uri) AS target_uris
by src_ip, uri
| where malformed_svg_requests > 3
| sort - malformed_svg_requests
Wazuh OSSEC Rule
<group name="web,nodejs,cve-2026-104861,">
<rule id="1048610" level="10">
<if_sid>31100</if_sid>
<match>probe-image-size</match>
<regex><svg</regex>
<description>CVE-2026-104861: probe-image-size SVG parsing DoS - malformed SVG submitted</description>
<mitre>
<id>T1499</id>
</mitre>
<group>dos,resource_exhaustion,</group>
</rule>
<rule id="1048611" level="12">
<if_sid>1048610</if_sid>
<regex><{20,}</regex>
<description>CVE-2026-104861: Long run of unclosed '<' characters detected in SVG input - likely regex DoS</description>
<group>dos,resource_exhaustion,</group>
</rule>
</group>
Mitigation & Patch Guidance
Patch confidence: 0/4 (UNPATCHED — no patch evidence from any tracked source). No vendor advisory, patch commit, OSV record, or workaround is currently tracked.
Immediate mitigations (assume unpatched).
- Enforce a strict maximum byte size on any image data reaching
probe-image-size. Because the synchronous parser applies no input cap, application-level caps are essential. - Validate and reject SVG inputs that contain unbalanced
<characters, or disallow SVG entirely at the entry point if SVG dimension probing is not a business requirement. - Apply request timeouts, body-size limits, and concurrency caps at the reverse proxy/ingress layer so a single stalled event loop cannot absorb the whole process.
- For
probe(stream)/probe(url)usage, cap total stream bytes and reject streams whose chunking pattern is anomalous (many tiny chunks carrying malformed SVG), and restrict remote-fetch destinations to trusted allowlists to reduce attacker control over chunking. - Move image probing off the main service event loop—e.g., a dedicated worker process or child process with a hard CPU/time budget that can be killed—so a stalled parse cannot take down the primary service.
- Isolate
probe-image-sizeusage from latency-sensitive request handling paths.
- Enforce a strict maximum byte size on any image data reaching
Patch / upgrade steps.
- Upgrade
probe-image-sizeto 7.4.0 or later once the fixed release is available in your registry and validated. 7.4.0 is stated in the NVD description to fix the issue. - Pin the dependency to
>=7.4.0inpackage.jsonand regenerate the lockfile to prevent transitive downgrade. - Rebuild and redeploy all container images and serverless bundles that bundle the package, verifying the resolved version (
npm ls probe-image-size) in each deployed artifact. - Monitor the npm advisory database and OSV for official patch records as they become available; patch confidence will rise once these appear.
- Upgrade
Long-term hardening.
- Replace unbounded per-chunk reparsing of accumulated input with a bounded or streaming tokenizer, and pre-compile/replace regexes with non-catastrophic equivalents (e.g., anchored, non-backtracking patterns using possessive quantifiers or a proper parser).
- Adopt a dependency-vetting policy that evaluates regular expressions in third-party packages for catastrophic backtracking.
- Enforce resource governance (CPU quotas, wall-clock timeouts, dead-letter handling) for all components that parse untrusted input.
- Add regression tests that feed long runs of
<(both synchronous buffers and adversarially chunked streams) to confirm input caps and timeouts hold.
References
- NVD — CVE-2026-104861: https://nvd.nist.gov/vuln/detail/CVE-2026-104861
- probe-image-size npm package: https://www.npmjs.com/package/probe-image-size
- probe-image-size source repository (lib/parse_sync/svg.js, lib/parse_stream/svg.js): https://github.com/nodeca/probe-image-size
- CWE-400 — Uncontrolled Resource Consumption: https://cwe.mitre.org/data/definitions/400.html
- CISA Known Exploited Vulnerabilities Catalog (not listed for this CVE): https://www.cisa.gov/known-exploited-vulnerabilities-catalog
No public proof-of-concept, exploit code, or Nuclei template is currently available for CVE-2026-104861. No evidence of in-the-wild exploitation or attribution to a specific threat actor or campaign has been observed. The vulnerability is not present in the CISA KEV catalog. No EPSS score has been assigned by FIRST.org at the time of writing.
What is this? Security researchers use these exact search queries on Shodan.io (a search engine for internet-connected devices) to find vulnerable systems globally. You can copy these dorks to see if your organization's IP space is exposed.
💣 PoC CODE AVAILABLE
Exploit code for this CVE is tracked in our database.
Access poc_code via API Pro.