Skip to content

v1.2.2 — ReDoS fix in multi-line basic strings (GHSA-j4cp-cc36-jxwg)

Choose a tag to compare

@sunnyadn sunnyadn released this 05 Aug 00:17
· 28 commits to main since this release

Security release. All versions up to and including 1.2.1 are affected.

Exponential backtracking in the multi-line basic string grammar

GHSA-j4cp-cc36-jxwg, CWE-1333.

The escaped-newline rule ended in (whiteSpaceChar | newline)*, which is ambiguous with the enclosing content loop over the same characters, so an unterminated multi-line basic string made the lexer enumerate every composition of the whitespace run. Cost doubled roughly every three bytes: a 97-byte document blocked the event loop for about nine seconds, and around 160 bytes for over a year. Unlike a size-proportional CPU bug, request-size limits give no protection here.

The trailing group is redundant, since unescapeString performs line-ending-backslash trimming at interpretation time, so removing it leaves the accepted language unchanged.

Decimal integer literals are now capped at 1000 digits

CWE-400, no advisory published. NonDecimalInteger enforced MAX_RADIX_LITERAL_LENGTH while DecimalInteger passed the whole literal to BigInt() unbounded. There is no amplification to exploit: BigInt() on a decimal string measures at roughly O(n^1.28) on every supported Node, 18 through 24 each parsing a million digits in about 41 ms, and a megabyte of digits costs less to parse than a megabyte of ordinary key/value pairs. It is fixed as a consistency guard rather than as a vulnerability.

Literals longer than 1000 digits now raise SyntaxParseError instead of loading as a bigint. TOML's 64-bit integer range needs at most 20 digits, so this affects only documents that deliberately carry oversized integers.

Reported by @arpitjain099.