Threats affecting pkg:npm/js-toml
3 threats
Most recently published first
| Severity | CVSS | Signals | Threat | Source | Published | Score and star |
|---|---|---|---|---|---|---|
| Medium | 5.3 | EPSS 0.4% | CVE-2026-63386sunnyadn js-toml · Uncontrolled Recursion Medium5.3EPSS 0.4%CVE Database V5CVE-2026-63386 js-toml is a TOML parser for JavaScript. Prior to 1.1.3, load() does not bound nesting or dotted-key depth in the recursive parser at src/load/parser.ts or the interpreter at src/load/interpreter.ts, so deeply nested arrays, deeply nested inline tables, or long dotted keys can exhaust the V8 call stack and throw a raw RangeError instead of the documented SyntaxParseError. Applications that parse attacker-controlled TOML and handle only SyntaxParseError can rethrow the unexpected exception, which can terminate a worker or process and cause denial of service. The exception is synchronous and catchable by consumers that handle all exceptions, and the issue does not affect confidentiality or integrity. This issue is fixed in version 1.1.3. | CVE Database V5 | ||
| Medium | 5.3 | EPSS 0.4% | Medium5.3EPSS 0.4%GCVE Database ### Summary `js-toml`'s interpreter checks whether a key already exists in a parser-built container with `if (object[key])` instead of `if (key in object)`. When the prior value is a falsy primitive — `false`, `0`, `0n`, `0.0`, `-0`, or `""` — the duplicate-key branch is skipped and the value is silently overwritten by a later sub-table, dotted-key sub-table, or array-of-tables sharing the same name. Per the TOML 1.0.0 spec ("Defining a key multiple times is invalid"; "You cannot define any key or table more than once"), this should be a parse error. The result is **structural type confusion of attacker-named keys** in the value returned by `load()`. A boolean-typed `false` (or numeric `0`) becomes a truthy object. Host applications that gate behavior on `if (config.flag)`, `if (!user.banned)`, `if (config.allowDelete)`, or `if (config.publicMode)` will silently take the truthy branch. This is **distinct** from [GHSA-65fc-cr5f-v7r2](https://github.com/sunnyadn/js-toml/security/advisories/GHSA-65fc-cr5f-v7r2) (the 1.0.2 prototype-pollution fix). `Object.prototype` is **not** polluted. The `Object.create(null)` mitigation from 1.0.2 is intact; the bug here is in the duplicate-key state machine, not in container construction. ### Details Two truthy checks are wrong: `src/load/interpreter.ts:214` — `Interpreter.tryCreatingObject` ```js if (object[key]) { // falsy primitives slip through // duplicate-key logic } else { object[key] = createSafeObject(); // silently overwrites the prior falsy value ... } ``` `src/load/interpreter.ts:278` — `Interpreter.getOrCreateArray` ```js if (object[first] && !Array.isArray(object[first])) { // same flaw throw new DuplicateKeyError(); } object[first] = object[first] || []; // overwrites the prior falsy value ``` Both should use the `in` operator. Containers are created via `Object.create(null)`, so `in` is unambiguous (no inherited keys to worry about). The bug is reachable through every parent-walking interpreter path: - `assignValue` — dotted keys in `key = value` - `createTable` — `[stdTable]` headers - `getOrCreateArray` — `[[arrayOfTables]]` headers ### PoC ```toml isAdmin = false [isAdmin] forced = "yes" ``` ```js import { load } from 'js-toml'; const config = load(` isAdmin = false [isAdmin] forced = "yes" `); console.log(JSON.stringify(config)); // {"isAdmin":{"forced":"yes"}} console.log(config.isAdmin ? 'BYPASS' : 'safe'); // BYPASS if (config.isAdmin) { // attacker reaches admin-only code } ``` ### Impact Spec-violating input acceptance leading to structural type confusion. (CWE-697) ### Suggested fix in `src/load/interpreter.ts` ```diff export class Interpreter extends BaseCstVisitor { ignoreImplicitDeclared, ignoreExplicitDeclared ) { - if (object[key]) { + if (key in object) { if ( !isPlainObject(object[key]) || (!ignoreExplicitDeclared && ``` ```diff export class Interpreter extends BaseCstVisitor { return this.getOrCreateArray(keys, object[first], idx + 1); } - if (object[first] && !Array.isArray(object[first])) { + if (first in object && !Array.isArray(object[first])) { throw new DuplicateKeyError(); } object[first] = object[first] || []; ``` | GCVE Database | ||
| High | 7.5 | EPSS 0.6% | CVE-2026-49293sunnyadn js-toml · Uncontrolled Resource Consumption High7.5EPSS 0.6%CVE Database V5CVE-2026-49293 js-toml is a TOML parser for JavaScript, fully compliant with the TOML 1.0.0 Spec. 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. Version 1.1.1 fixes the issue. | CVE Database V5 |
Page 1 of 1