CVE-2026-49293
CPU exhaustion via O(n^2) BigInt construction on radix-prefixed integer literals
js-toml is a TOML parser for JavaScript, fully compliant with the TOML 1.0.0 Spec. Versions up to and including 1.1.1 parse hexadecimal / octal / binary integer literals via a hand-written parseBigInt loop that multiplies a BigInt accumulator by the radix once per input digit. Each iteration performs a BigInt * BigInt operation on an accumulator that grows linearly with the number of digits already consumed, so the whole loop is O(n²) in the literal length. The lexer regex places no upper bound on the literal length, so a single TOML document containing one ~500 kB hex literal pins one CPU core for ~40 seconds on a modern laptop (Apple M-series, Node v22). Memory amplification is bounded but CPU amplification is severe and grows quadratically: doubling the literal length quadruples the work. A caller that invokes load() on attacker-controlled TOML (configuration upload endpoints, CI/CD systems ingesting third-party *.toml, IDE plugins, build tools) is exposed to a single-request CPU exhaustion DoS. Version 1.1.2 fixes the issue.
Attack profile
How easy it is to exploit
- Attack vector
- Network
- Complexity
- Low
- Privileges needed
- None
- User interaction
- None
What an attacker can affect
- Confidentiality
- None
- Integrity
- None
- Availability
- High
Exploit likelihood
What each source reports
CVE List Score used
7.5
CPU exhaustion via O(n^2) BigInt construction on radix-prefixed integer literals
js-toml is a TOML parser for JavaScript, fully compliant with the TOML 1.0.0 Spec. Versions up to and including 1.1.1 parse hexadecimal / octal / binary integer literals via a hand-written parseBigInt loop that multiplies a BigInt accumulator by the radix once per input digit. Each iteration performs a BigInt * BigInt operation on an accumulator that grows linearly with the number of digits already consumed, so the whole loop is O(n²) in the literal length. The lexer regex places no upper bound on the literal length, so a single TOML document containing one ~500 kB hex literal pins one CPU core for ~40 seconds on a modern laptop (Apple M-series, Node v22). Memory amplification is bounded but CPU amplification is severe and grows quadratically: doubling the literal length quadruples the work. A caller that invokes load() on attacker-controlled TOML (configuration upload endpoints, CI/CD systems ingesting third-party *.toml, IDE plugins, build tools) is exposed to a single-request CPU exhaustion DoS. Version 1.1.2 fixes the issue.
- Record
CVE-2026-49293- CVSS 3.1
- 7.5 High
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H - Weakness
- CWE-400, CWE-407, CWE-1333
- Updated
- 2026-11-04
EUVDEUVD-2026-38060
7.5
js-toml is a TOML parser for JavaScript, fully compliant with the TOML 1.0.0 Spec. Versions up to and including 1.1.1 parse hexadecimal / octal / binary integer literals via a hand-written parseBigInt loop that multiplies a BigInt accumulator by the radix once per input digit. Each iteration performs a BigInt * BigInt operation on an accumulator that grows linearly with the number of digits already consumed, so the whole loop is O(n²) in the literal length. The lexer regex places no upper bound on the literal length, so a single TOML document containing one ~500 kB hex literal pins one CPU core for ~40 seconds on a modern laptop (Apple M-series, Node v22). Memory amplification is bounded but CPU amplification is severe and grows quadratically: doubling the literal length quadruples the work. A caller that invokes load() on attacker-controlled TOML (configuration upload endpoints, CI/CD systems ingesting third-party *.toml, IDE plugins, build tools) is exposed to a single-request CPU exhaustion DoS. Version 1.1.2 fixes the issue.
- Record
EUVD-2026-38060- CVSS 3.1
- 7.5 High
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H - Updated
- 2026-11-04
GitHub AdvisoriesGHSA-wp3c-266w-4qfq
7.5
js-toml vulnerable to CPU exhaustion via O(n^2) BigInt construction on radix-prefixed integer literals
Summary
js-toml versions up to and including 1.1.0 parse hexadecimal / octal / binary integer literals via a hand-written parseBigInt loop that multiplies a BigInt accumulator by the radix once per input digit. Each iteration performs a BigInt * BigInt operation on an accumulator that grows linearly with the number of digits already consumed, so the whole loop is O(n²) in the literal length. The lexer regex places no upper bound on the literal length, so a single TOML document containing one ~500 kB hex literal pins one CPU core for ~40 seconds on a modern laptop (Apple M-series, Node v22). Memory amplification is bounded but CPU amplification is severe and grows quadratically: doubling the literal length quadruples the work.
A caller that invokes load() on attacker-controlled TOML (configuration upload endpoints, CI/CD systems ingesting third-party *.toml, IDE plugins, build tools) is exposed to a single-request CPU exhaustion DoS.
CWE-1333 (Inefficient Regular Expression Complexity → here, inefficient parser complexity), CWE-400 (Uncontrolled Resource Consumption), CWE-407 (Inefficient Algorithmic Complexity).
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H = 7.5 (HIGH) when the parser is invoked on attacker-controllable input; LOW when the calling application restricts TOML input size to small documents (< 1 kB).
Affected
- Package:
js-toml(npm) - Versions:
>= 0.0.0, <= 1.1.0(all released versions up to and including the current1.1.0) - Affected entry point:
load()exported from the package root
Vulnerable code
src/load/tokens/NonDecimalInteger.ts lines 54-84 at SHA-pinned 2470ebf2e9009096aa4cbd1a15e574c54cc36b1a:
const parseBigInt = (string: string, radix: number): bigint => {
let result = BigInt(0);
for (let i = 0; i < string.length; i++) {
const char = string[i];
const digit = parseInt(char, radix);
result = result * BigInt(radix) + BigInt(digit);
}
return result;
};
and the interpreter that dispatches to it at lines 72-84:
registerTokenInterpreter(NonDecimalInteger, (raw: string) => {
const intString = raw.replace(/_/g, '');
const digits = intString.slice(2);
const radix = getRadix(raw);
const int = parseInt(digits, radix);
if (Number.isSafeInteger(int)) {
return int;
}
return parseBigInt(digits, radix);
});
Two compounding problems:
-
Algorithmic: the loop performs
result * BigInt(radix) + BigInt(digit)once per input digit. AfteriiterationsresulthasO(i)limbs, so the multiply costsO(i). Summed overndigits the total cost isO(n²). -
No length guard: the lexer regex at
src/load/tokens/NonDecimalInteger.ts#L14-L46is0x<hexDigit>(<hexDigit>|_<hexDigit>)*(likewise for0o/0b). The literal length is bounded only by the input document size. There is nomaxNumberLength/maxLiteralLengthoption, nochevrotain-level cutoff, and no validation at the interpreter callsite.
By contrast, the DecimalInteger token interpreter at src/load/tokens/DecimalInteger.ts#L12-L19 uses the V8 native BigInt(intString) constructor, which is O(n) and runs in single-digit milliseconds for inputs that take 40 seconds via the hand-written radix loop.
Impact
A single attacker-supplied TOML document containing one ~500 kB radix-prefixed integer literal pins one CPU core for ~40 seconds on a modern laptop. Doubling the literal length quadruples the work. With 8 MB of input the parse would block the event loop for many minutes of CPU. In a typical Node.js single-thread process…
- Record
GHSA-wp3c-266w-4qfq- CVSS 3.1
- 7.5 High
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H - Weakness
- CWE-400, CWE-407, CWE-1333
- Updated
- 2026-11-04
NVD
7.5
js-toml is a TOML parser for JavaScript, fully compliant with the TOML 1.0.0 Spec. Versions up to and including 1.1.1 parse hexadecimal / octal / binary integer literals via a hand-written parseBigInt loop that multiplies a BigInt accumulator by the radix once per input digit. Each iteration performs a BigInt * BigInt operation on an accumulator that grows linearly with the number of digits already consumed, so the whole loop is O(n²) in the literal length. The lexer regex places no upper bound on the literal length, so a single TOML document containing one ~500 kB hex literal pins one CPU core for ~40 seconds on a modern laptop (Apple M-series, Node v22). Memory amplification is bounded but CPU amplification is severe and grows quadratically: doubling the literal length quadruples the work. A caller that invokes load() on attacker-controlled TOML (configuration upload endpoints, CI/CD systems ingesting third-party *.toml, IDE plugins, build tools) is exposed to a single-request CPU exhaustion DoS. Version 1.1.2 fixes the issue.
- Record
CVE-2026-49293- CVSS 3.1
- 7.5 High
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H - Weakness
- CWE-400, CWE-407, CWE-1333
- Updated
- 2026-11-04
OSV
7.5
CPU exhaustion via O(n^2) BigInt construction on radix-prefixed integer literals
js-toml is a TOML parser for JavaScript, fully compliant with the TOML 1.0.0 Spec. Versions up to and including 1.1.1 parse hexadecimal / octal / binary integer literals via a hand-written parseBigInt loop that multiplies a BigInt accumulator by the radix once per input digit. Each iteration performs a BigInt * BigInt operation on an accumulator that grows linearly with the number of digits already consumed, so the whole loop is O(n²) in the literal length. The lexer regex places no upper bound on the literal length, so a single TOML document containing one ~500 kB hex literal pins one CPU core for ~40 seconds on a modern laptop (Apple M-series, Node v22). Memory amplification is bounded but CPU amplification is severe and grows quadratically: doubling the literal length quadruples the work. A caller that invokes load() on attacker-controlled TOML (configuration upload endpoints, CI/CD systems ingesting third-party *.toml, IDE plugins, build tools) is exposed to a single-request CPU exhaustion DoS. Version 1.1.2 fixes the issue.
- Record
CVE-2026-49293- CVSS 3.1
- 7.5 High
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H - Weakness
- CWE-1333, CWE-400, CWE-407
- Updated
- 2026-11-05
OSVGHSA-wp3c-266w-4qfq
7.5
js-toml vulnerable to CPU exhaustion via O(n^2) BigInt construction on radix-prefixed integer literals
Summary
js-toml versions up to and including 1.1.0 parse hexadecimal / octal / binary integer literals via a hand-written parseBigInt loop that multiplies a BigInt accumulator by the radix once per input digit. Each iteration performs a BigInt * BigInt operation on an accumulator that grows linearly with the number of digits already consumed, so the whole loop is O(n²) in the literal length. The lexer regex places no upper bound on the literal length, so a single TOML document containing one ~500 kB hex literal pins one CPU core for ~40 seconds on a modern laptop (Apple M-series, Node v22). Memory amplification is bounded but CPU amplification is severe and grows quadratically: doubling the literal length quadruples the work.
A caller that invokes load() on attacker-controlled TOML (configuration upload endpoints, CI/CD systems ingesting third-party *.toml, IDE plugins, build tools) is exposed to a single-request CPU exhaustion DoS.
CWE-1333 (Inefficient Regular Expression Complexity → here, inefficient parser complexity), CWE-400 (Uncontrolled Resource Consumption), CWE-407 (Inefficient Algorithmic Complexity).
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H = 7.5 (HIGH) when the parser is invoked on attacker-controllable input; LOW when the calling application restricts TOML input size to small documents (< 1 kB).
Affected
- Package:
js-toml(npm) - Versions:
>= 0.0.0, <= 1.1.0(all released versions up to and including the current1.1.0) - Affected entry point:
load()exported from the package root
Vulnerable code
src/load/tokens/NonDecimalInteger.ts lines 54-84 at SHA-pinned 2470ebf2e9009096aa4cbd1a15e574c54cc36b1a:
const parseBigInt = (string: string, radix: number): bigint => {
let result = BigInt(0);
for (let i = 0; i < string.length; i++) {
const char = string[i];
const digit = parseInt(char, radix);
result = result * BigInt(radix) + BigInt(digit);
}
return result;
};
and the interpreter that dispatches to it at lines 72-84:
registerTokenInterpreter(NonDecimalInteger, (raw: string) => {
const intString = raw.replace(/_/g, '');
const digits = intString.slice(2);
const radix = getRadix(raw);
const int = parseInt(digits, radix);
if (Number.isSafeInteger(int)) {
return int;
}
return parseBigInt(digits, radix);
});
Two compounding problems:
-
Algorithmic: the loop performs
result * BigInt(radix) + BigInt(digit)once per input digit. AfteriiterationsresulthasO(i)limbs, so the multiply costsO(i). Summed overndigits the total cost isO(n²). -
No length guard: the lexer regex at
src/load/tokens/NonDecimalInteger.ts#L14-L46is0x<hexDigit>(<hexDigit>|_<hexDigit>)*(likewise for0o/0b). The literal length is bounded only by the input document size. There is nomaxNumberLength/maxLiteralLengthoption, nochevrotain-level cutoff, and no validation at the interpreter callsite.
By contrast, the DecimalInteger token interpreter at src/load/tokens/DecimalInteger.ts#L12-L19 uses the V8 native BigInt(intString) constructor, which is O(n) and runs in single-digit milliseconds for inputs that take 40 seconds via the hand-written radix loop.
Impact
A single attacker-supplied TOML document containing one ~500 kB radix-prefixed integer literal pins one CPU core for ~40 seconds on a modern laptop. Doubling the literal length quadruples the work. With 8 MB of input the parse would block the event loop for many minutes of CPU. In a typical Node.js single-thread process…
- Record
GHSA-wp3c-266w-4qfq- CVSS 3.1
- 7.5 High
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H - Weakness
- CWE-1333, CWE-400, CWE-407
- Updated
- 2026-11-04
Affected products
Affected packages
History
| Recorded | Changed | Sources |
|---|---|---|
| references | OSV | |
| references | NVD | |
| references | EUVD | |
| description, references | CVE List | |
| affected, references | OSV | |
| affected, facts, references | GitHub Advisories | |
| aliases, published | EUVD | |
| first indexed | CVE List, GitHub Advisories, NVD, OSV |
Dates are when Every CVE recorded each change. Upstream dates may differ.
In short
CVE-2026-49293 is a high vulnerability (CVSS 7.5) in Sunnyadn Js-toml, published June 19, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.64%, the 51st percentile. Fixed in js-toml 1.1.2.
References
github.com/sunnyadn/js-toml/security/advisories/GHSA-wp3c-266w-4qfq
github.com/sunnyadn/js-toml/commit/1e45ca56ba12e98508f8aae3e31c4aff7603d711
github.com/sunnyadn/js-toml/releases/tag/v1.1.2
nvd.nist.gov/vuln/detail/CVE-2026-49293
github.com/advisories/GHSA-wp3c-266w-4qfq
github.com/CVEProject/cvelistV5/tree/main/cves/2026/49xxx/CVE-2026-49293.json
github.com/sunnyadn/js-toml
Left out here: the rest of 2 source descriptions. The JSON record has them.