GHSA-5jh3-w3fj-6758: 
JavaScript Análise e mitigação de vulnerabilidades

Filed here at the maintainer's request, in reply to our email of 2026-10-21: one GitHub report per issue. This is one of four separate reports split out of that email, and it stands alone. Found with AploSec, our security scanner, and confirmed by execution.

Summary

The SVG header parser rewrite that fixed GHSA-gjj5-9665-rwrc (CVE-2026-104861) introduced a different quadratic regex, in the doctype alternative. An SVG that opens a doctype internal subset and never closes it costs about 120 ms of event-loop time per probe at the 10 KiB input cap, against under 1 ms for a normal SVG.

Affected versions

  • probe-image-size 7.4.0 (npm latest, published 2026-08-15). Default-branch HEAD 64565c3c ("7.4.0 released") is identical to the release, and it is still the latest commit and version as of 2026-10-22.
  • 7.3.0 does not have this pattern (it had the parent issue instead). This is a regression introduced by the 7.4.0 fix.

Details

lib/common/svg_header.js:32. The doctype alternative of PROLOG_RE is <![A-Za-z][^[>]*(?:\[[\s\S]*?\][^>]*)?>. On <!a[ followed by many ] and no >, the lazy [\s\S]*?\] stops at each ] in turn, and [^>]* then rescans the rest of the input before failing, so the match is O(n^2). The other prolog constructs (processing instructions, comments, CDATA, root attributes, whitespace) are linear in the same test. Reachable through probe.sync (lib/parse_sync/svg.js) and probe(stream) / probe(url) (lib/parse_stream/svg.js). Both cap the input at MAX_DATA_LENGTH = 10240, which bounds the cost per call. Attacker model: remote and unauthenticated. The attacker supplies an SVG (bytes or URL) to a service that calls probe-image-size.

Proof of concept

const probe = require('probe-image-size')
const hdr = require('probe-image-size/lib/common/svg_header')
const ms = f => { const s = process.hrtime.bigint(); try { f() } catch (e) {} return (Number(process.hrtime.bigint() - s) / 1e6).toFixed(1) }
const attack = n => '<!a[' + ']'.repeat(n - 4)        // unterminated doctype internal subset, no '>'
const control = n => '<!a[' + ']'.repeat(n - 4) + '>'  // same bytes, terminated
for (const n of [2500, 5000, 10000, 20000, 40000])
  console.log('svg_header.parse', n, 'attack', ms(() => hdr.parse(attack(n))), 'ms, control', ms(() => hdr.parse(control(n))), 'ms')
for (const n of [2500, 5000, 10000, 10240, 50000])
  console.log('probe.sync', n, 'attack', ms(() => probe.sync(Buffer.from(attack(n), 'latin1'))), 'ms')

Test environment: Docker node:22-slim (Node 22.23.4), npm i probe-image-size@7.4.0 (and 7.3.0 in ./old where noted), runs with docker run --rm --network none. Controls:

  • The same bytes with a closing > parse in 0.0 to 0.1 ms at every size.
  • The parent payload '<a'.repeat(n / 2) takes 1,794 ms at 50 KB on 7.3.0 and 0 to 1 ms on 7.4.0, so the parent fix works and the harness can detect slowness. Results (7.4.0):
svg_header.parse  n=2500 7.2 ms | 5000 28.2 ms | 10000 115.5 ms | 20000 453.4 ms | 40000 1816.3 ms   (4x per doubling)
probe.sync        2500 B 8 ms | 5000 B 30 ms | 10000 B 121 ms | 10240 B 123 ms | 50000 B 124 ms (plateau at the cap)
5 sequential probe.sync calls on the 10240 B payload: 611 ms
probe(stream), single 10240 B chunk: 129 ms

A rerun of the exact script above on 2026-10-22, on a faster host (Docker on Apple Silicon), gave the same quadratic growth: 3.2 / 12.9 / 42.6 / 215.7 / 623.3 ms for svg_header.parse, and 41 ms for probe.sync at the 10240 B cap. Feeding the stream parser one > per chunk does not multiply the cost: a > right after the first ] ends the doctype, so only short, linear re-parses happen (137 ms at 10 KiB with 1-byte chunks).

Impact

Low. The 10 KiB cap limits each probe to about 120 ms of blocked event loop, roughly 1000x a normal parse. It matters for services that probe many untrusted SVGs, where a sustained request rate turns it into a denial of service.

Suggested fix

Make the internal subset scan linear, for example (?:\[[^\]]*\][^>]*)? in place of (?:\[[\s\S]*?\][^>]*)?, or scan the doctype with indexOf instead of a regex. Zachariah Mithani (zachariah@aplosai.com) AploSec (aplosec.si) Credit: Zachariah Mithani (@zachariah-mithani, AploSec)


Origem: NVD

Relacionado JavaScript Vulnerabilidades:

CVE ID

Gravidade

Pontuação

Tecnologias

Nome do componente

Exploit CISA KEV

Tem correção

Data de publicação

CVE-2026-59179HIGH8.3
  • JavaScript logoJavaScript
  • @openhop/server
NãoSimOct 28, 2026
CVE-2026-59176HIGH7.8
  • JavaScript logoJavaScript
  • functype-mcp-server
NãoSimOct 28, 2026
GHSA-3pfx-gxff-vg76HIGH7.5
  • JavaScript logoJavaScript
  • seroval
NãoSimOct 28, 2026
GHSA-fvxq-xq4h-rqgmMEDIUMN/A
  • JavaScript logoJavaScript
  • @sentry/nextjs
NãoSimOct 28, 2026
GHSA-3fgc-wc43-9q2fHIGHN/A
  • JavaScript logoJavaScript
  • taskgraph-ai
NãoSimOct 28, 2026

Avaliação Gratuita de Vulnerabilidades

Avalie a sua postura de segurança na nuvem

Avalie suas práticas de segurança em nuvem em 9 domínios de segurança para avaliar seu nível de risco e identificar lacunas em suas defesas.

Avaliação de solicitação

Recursos adicionais da Wiz

Marque uma demonstração personalizada

Pronto para ver a Wiz em ação?

"A melhor experiência do usuário que eu já vi, fornece visibilidade total para cargas de trabalho na nuvem."
David EstlickCISO
"A Wiz fornece um único painel de vidro para ver o que está acontecendo em nossos ambientes de nuvem."
Adam FletcherDiretor de Segurança
"Sabemos que se a Wiz identifica algo como crítico, na verdade é."
Greg PoniatowskiChefe de Gerenciamento de Ameaças e Vulnerabilidades