Skip to content

GHSA-r4xh-jqrq-34v2

smol-toml: Quadratic-time parse() from parseKey rescanning to end of document on each key line

Medium npm
Severity
5.3 / 10
Medium · CVSS 3.1
Exploit chance (EPSS)
—
No score published
Known exploited
No
Not in CISA's catalog
Weakness
CWE-407 Inefficient Algorithmic Complexity
Fix
1.9.0
Upgrade smol-toml to this version or later

Description

Summary

parse() has a quadratic-time path in parseKey, reachable on default options with ordinary valid input. For every key line and table-header line, parseKey (dist/struct.js, lines 58 and 86) finds the dotted-key separator with ctx.s.indexOf('.', ctx.p), where ctx.s is the whole document. When a key has no . ahead of it, that search runs all the way to the end of the input, and the result is then clamped back to the line terminator endPtr - so everything scanned past the current line is wasted. parseKey runs once per line, so a document of N dot-free keys costs O(n^2).

The most ordinary TOML shape triggers it: a flat list of key = value lines, or a repeated [[a]] table. No dotted keys, no special options, valid input throughout.

Proof of concept

import { parse } from 'smol-toml'

let doc = ''
for (let i = 0; i < 256000; i++) doc += 'k' + i + ' = 1\n'

console.time('parse')
parse(doc) // ~2.8 MB of valid TOML, default options
console.timeEnd('parse')

Doubling the line count roughly quadruples the time:

lines size parse()
32k 0.3 MB 0.3 s
64k 0.7 MB 1.0 s
128k 1.4 MB 3.5 s
256k 2.8 MB 14 s

Impact

Any service that runs parse() on attacker-supplied TOML can be stalled. The work is synchronous, so it blocks the whole event loop, and the quadratic is unbounded: a ~7 MB body pins a core for about a minute, larger bodies for several.

Patches

Version 1.9.0 uses a different implementation for parsing keys which is strictly linear.

Workarounds

Limit the maximum document size accepted when parsing arbitrary documents.

Affected versions

npm

PackageVulnerableFixed in
smol-toml
<= 1.8.0
No fix yet
smol-toml
< 1.9.0
1.9.0

How to fix

Move to the fixed version or later with your package manager, update the lockfile, and run your tests. If the package only arrives through another dependency, upgrade that dependency first. If none of its releases pulls a fixed version yet, force the version with your package manager's override.

smol-toml npm → 1.9.0

npm
npm install smol-toml@1.9.0
yarn
yarn add smol-toml@1.9.0
pnpm
pnpm add smol-toml@1.9.0

Severity breakdown

CVSS 3.1 5.3

CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L

Attack vector
Network
Attack complexity
Low
Privileges required
None
User interaction
None
Scope
Unchanged
Confidentiality
None
Integrity
None
Availability
Low

Weakness

CWE-407: Inefficient Algorithmic Complexity

An algorithm in a product has an inefficient worst-case computational complexity that may be detrimental to system performance and can be triggered by an attacker, typically using crafted manipulations that ensure that the worst case is being reached.

References

Timeline

  1. Published
  2. Last updated by the source
AdvisorySeverityWhy it's related
GHSA-7w5x-hrqm-74c2
smol-toml: Denial of Service via malformed TOML documents
High Also affects smol-toml
GHSA-v3rj-xjv7-4jmq
smol-toml: Denial of Service via TOML documents containing thousands of consecutive commented lines
Medium Also affects smol-toml
GHSA-pqhp-25j4-6hq9
smol-toml has a Denial of Service via malicious TOML document using deeply nested inline tables
Medium Also affects smol-toml
GHSA-2qm8-x737-gmw5
pyasn1 has quadratic CPU consumption in constructed BIT STRING decoding
High Same weakness, CWE-407
GHSA-mm57-4v3p-rchx
pyasn1 has quadratic-complexity denial of service in binary REAL decoding
High Same weakness, CWE-407
GHSA-9m75-vc3g-4x39
pyasn1 has quadratic-time denial of service in constructed string and indefinite-length ANY decoding
High Same weakness, CWE-407
GHSA-fm9c-5rcf-2q5p
pyasn1 has quadratic CPU use in schemaless BER/CER/DER container decoding
High Same weakness, CWE-407
GHSA-mgcc-cww5-fp2q
Go JOSE: DoS when parsing JWKs that contain RSA keys
High Same weakness, CWE-407

Credits: NotAFlightRisk

Is this in your code?

MergeHarbor checks every repository's dependencies against this database, ranks what matters by exploitability and reachability, routes it to the owning team and opens the fix pull request.

Check your repos with MergeHarbor