CVE-2026-49293 is a high-severity uncontrolled resource consumption vulnerability in js-toml (npm), affecting versions <= 1.1.0. It is fixed in 1.1.1.
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 current 1.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: and the interpreter that dispatches to it at lines 72-84: Two compounding problems: Algorithmic: the loop performs result BigInt(radix) + BigInt(digit) once per input digit. After i iterations result has O(i) limbs, so the multiply costs O(i). Summed over n digits the total cost is O(n²). No length guard: the lexer regex at src/load/tokens/NonDecimalInteger.ts#L14-L46 is 0x<hexDigit>(<hexDigit>|<hexDigit>) (likewise for 0o / 0b). The literal length is bounded only by the input document size. There is no maxNumberLength / maxLiteralLength option, no chevrotain-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 this blocks all concurrent request handling for the duration. The defect is exploitable on any code path that calls load() (the only documented entry point) on attacker-controlled or third-party TOML. Reachability The vulnerable path is the default code path for load(). No options or configuration are required to trigger it. Any caller that exposes load() to attacker-controlled or third-party TOML input reaches it on the first hex / octal / binary literal whose value exceeds Number.MAXSAFEINTEGER (i.e. more than 13 hex digits, 18 octal digits, or 53 binary digits). Realistic exposure surfaces: Web service that accepts a user-supplied TOML configuration (settings import, theme upload, deployment manifest). CI / CD or build tool that runs js-toml on TOML in third-party repositories or pull requests. IDE / language-server plugin that re-parses a TOML buffer on every keystroke. Multi-tenant SaaS that lets one tenant submit TOML processed by a shared worker. PoC (End-to-end reproduction) Environment Node.js v22.x (tested on v22.0.0 and Node v26.0.0) macOS arm64 / Linux x8664 (CPU exhaustion is hardware-independent; absolute timings will scale by CPU clock) Install pocfulle2e.mjs Captured run output (unpatched [email protected], Node v26.0.0, Apple M-series) Confirmation points: Quadratic curve: 10k → 20k digits is ~2x time (15ms → 30ms); 100k → 200k is ~4.7x time (693ms → 3239ms); 200k → 500k (2.5x) is ~12x time (3.2s → 40s). Matches the predicted O(n²). Single ~500 kB document blocks the event loop for ~40 s of CPU time. Octal and binary literals trigger the same path through parseBigInt(digits, 8) and parseBigInt(digits, 2). The negative control (@iarna/toml, which calls the V8 native BigInt(value) constructor) parses the same inputs in 2-10 ms. The defect is in js-toml's hand-written radix conversion, not in V8 BigInt semantics or in the input size itself. Patched-build verification After applying the fix (replace parseBigInt(digits, radix) with BigInt('0' + raw[1] + digits) and add a maxLiteralLength guard at the interpreter callsite), the same PoC produces: (Linear scaling, sub-10 ms even on inputs five orders of magnitude larger than any realistic literal.) With a 1000-digit cap applied at the interpreter callsite, literals beyond the cap raise SyntaxParseError instead of being parsed at all, matching the maxNumberLength convention used by jackson-core StreamReadConstraints and gson NumberLimits. Suggested fix Two changes, both in src/load/tokens/NonDecimalInteger.ts: Replace the hand-written parseBigInt loop with the V8 native BigInt(prefixedString) constructor. BigInt natively accepts the 0x / 0o / 0b prefix and parses in O(n): ts registerTokenInterpreter(NonDecimalInteger, (raw: string) => { const intString = raw.replace(//g, ''); const digits = intString.slice(2); const radix = getRadix(raw); // Optional but recommended: cap the literal length to avoid degenerate inputs const MAXRADIXLITERALLENGTH = 1000; if (digits.length > MAXRADIXLITERALLENGTH) { throw new SyntaxParseError( Radix-prefixed integer literal exceeds ${MAXRADIXLITERALLENGTH} digits ); } const int = parseInt(digits, radix); if (Number.isSafeInteger(int)) { return int; } // BigInt accepts '0x'/'0o'/'0b' prefix natively return BigInt(intString); }); Delete the parseBigInt helper. The native constructor handles all three radices. Either change alone fixes the worst-case wall-clock. The combination matches the constraint posture of jackson-core (StreamReadConstraints.validateIntegerLength) and gson (NumberLimits.checkNumberStringLength). Fix PR link https://github.com/sunnyadn/js-toml/commit/1abcb31dc7b1fa88e4c848a8d108891cfbb96fa2 Credit Reported by tonghuaroot.
Crafted input forces the application to consume excessive CPU, memory, or other resources, degrading or denying service. Typical impact: denial of service.
CVE-2026-49293 has a CVSS score of 7.5 (High). The vector is network-reachable, no privileges required, and no user interaction. A CVSS score reflects the worst-case severity of the vulnerability, not your specific exposure. Whether this affects your application depends on whether the vulnerable code is present and reachable in your environment.
A fixed version is available (1.1.1). Upgrading removes the vulnerable code path.
npm
js-toml (<= 1.1.0)js-toml → 1.1.1 (npm)Severity tells you how bad this could be in the worst case. It does not tell you whether you are exposed. Exploitability and impact are functions of runtime truth: whether the vulnerable code is present, reachable, and actually executes in your application. A vulnerable package can sit in your dependency tree and never run.
Kodem, an Intelligent Application Security platform, uses runtime intelligence to reveal which vulnerabilities actually execute in production, so teams prioritize the ones that genuinely matter instead of chasing every advisory.
Kodem's runtime-powered SCA identifies whether CVE-2026-49293 is reachable in your applications. Explore open-source security for your team.
See if CVE-2026-49293 is reachable in your applications. Get a demo
Already deployed Kodem? See CVE-2026-49293 in your environment →Upgrade js-toml to 1.1.1 or later to resolve this vulnerability.
Kodem Kai can prioritize this vulnerability in your dependency tree and generate a fix recommendation.
CVE-2026-49293 is a high-severity uncontrolled resource consumption vulnerability in js-toml (npm), affecting versions <= 1.1.0. It is fixed in 1.1.1. Crafted input forces the application to consume excessive CPU, memory, or other resources, degrading or denying service.
CVE-2026-49293 has a CVSS score of 7.5 (High). This score reflects the worst-case severity of the vulnerability, not your specific exposure. Whether it represents real risk in your environment depends on whether the vulnerable code is present and reachable.
js-toml (npm) versions <= 1.1.0 is affected.
Yes. CVE-2026-49293 is fixed in 1.1.1. Upgrade to this version or later.
Whether CVE-2026-49293 is exploitable in your environment depends on whether the vulnerable code is present and reachable. A CVSS score is a worst-case rating; it does not account for your specific deployment, configuration, or usage patterns. Kodem, an Intelligent Application Security platform, uses runtime intelligence to show which vulnerabilities actually execute in production, so you can focus on the ones that represent real risk. Get a demo
Exploitability and impact are not fixed properties of a CVE. They depend on runtime truth: whether the vulnerable code is present, reachable, and actually executes in your application. A high CVSS score on a dependency that never runs is not the same as real risk. Kodem, an Intelligent Application Security platform, uses runtime intelligence to reveal which vulnerabilities actually execute in production, so teams prioritize the ones that genuinely matter.
Upgrade js-toml to 1.1.1 or later.