From 5f50d8c8fed093391b88f7e5d4f9aad4e7679173 Mon Sep 17 00:00:00 2001 From: Aadharsh Pannirselvam <19518661+oddharsh@users.noreply.github.com> Date: Thu, 24 Sep 2026 10:57:05 -0400 Subject: [PATCH 1/4] [wrangler] Update smol-toml to 1.9.0 1.9.0 fixes GHSA-r4xh-jqrq-34v2, which covers every version through 1.8.0. Parsed tables now have a null prototype, so the parseTOML tests compare with toEqual, and one TOML error snapshot now points at the bad character. --- .changeset/smol-toml-1-9.md | 10 ++++++++++ packages/workers-utils/tests/parse.test.ts | 8 +++++--- .../__tests__/pages/pages-build-env.test.ts | 8 ++++---- pnpm-lock.yaml | 18 +++++++++--------- pnpm-workspace.yaml | 2 +- 5 files changed, 29 insertions(+), 17 deletions(-) create mode 100644 .changeset/smol-toml-1-9.md diff --git a/.changeset/smol-toml-1-9.md b/.changeset/smol-toml-1-9.md new file mode 100644 index 00000000000..9843279c59f --- /dev/null +++ b/.changeset/smol-toml-1-9.md @@ -0,0 +1,10 @@ +--- +"wrangler": patch +"create-cloudflare": patch +"@cloudflare/workers-utils": patch +"@cloudflare/workers-auth": patch +--- + +Update `smol-toml` to 1.9.0 + +This updates the bundled TOML parser that reads `wrangler.toml` to a version that addresses `GHSA-r4xh-jqrq-34v2`, which affects every version up to and including 1.8.0: parse time grew quadratically with the number of key lines, so a 40,000-line document took 259 ms on 1.8.0 and takes 17 ms on 1.9.0. Some TOML syntax errors now point at the offending character; for example, `INVALID "FILE` is reported as `illegal character in key` at column 8 instead of `incomplete key-value` at column 0. diff --git a/packages/workers-utils/tests/parse.test.ts b/packages/workers-utils/tests/parse.test.ts index a8e57202c6b..8aad2bb5329 100644 --- a/packages/workers-utils/tests/parse.test.ts +++ b/packages/workers-utils/tests/parse.test.ts @@ -10,8 +10,10 @@ import { } from "../src/parse"; describe("parseTOML", () => { + // smol-toml 1.9 returns null-prototype objects, so these compare structure with + // `toEqual`; `toStrictEqual` would also compare prototypes against `{}`. it("should parse toml that is empty", ({ expect }) => { - expect(parseTOML("")).toStrictEqual({}); + expect(parseTOML("")).toEqual({}); }); it("should parse toml with basic values", ({ expect }) => { @@ -20,7 +22,7 @@ describe("parseTOML", () => { name = "basic" version = 1 `) - ).toStrictEqual({ + ).toEqual({ name: "basic", version: 1, }); @@ -37,7 +39,7 @@ describe("parseTOML", () => { [owner.dog] exists = true `) - ).toStrictEqual({ + ).toEqual({ name: "complex", owner: { alive: true, diff --git a/packages/wrangler/src/__tests__/pages/pages-build-env.test.ts b/packages/wrangler/src/__tests__/pages/pages-build-env.test.ts index 1be3dd069df..20175adb9c7 100644 --- a/packages/wrangler/src/__tests__/pages/pages-build-env.test.ts +++ b/packages/wrangler/src/__tests__/pages/pages-build-env.test.ts @@ -138,11 +138,11 @@ describe("pages build env", () => { expect(process.exitCode).toEqual(EXIT_CODE_INVALID_PAGES_CONFIG); expect(std.err).toMatchInlineSnapshot(` - "X [ERROR] Invalid TOML document: incomplete key-value: cannot find end of key + "X [ERROR] Invalid TOML document: illegal character in key - /wrangler.toml:1:0: -  1 │ INVALID "FILE - ╵ ^ + /wrangler.toml:1:8: +  1 │ INVALID "FILE + ╵ ^ " `); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f02c9565ab6..157c87df978 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -64,8 +64,8 @@ catalogs: specifier: 4.1.0 version: 4.1.0 smol-toml: - specifier: 1.8.0 - version: 1.8.0 + specifier: 1.9.0 + version: 1.9.0 tinyglobby: specifier: 0.2.16 version: 0.2.16 @@ -2011,7 +2011,7 @@ importers: version: 7.7.1 smol-toml: specifier: catalog:default - version: 1.8.0 + version: 1.9.0 tinyglobby: specifier: catalog:default version: 0.2.16 @@ -4251,7 +4251,7 @@ importers: version: 2.14.6(@types/node@22.15.17)(typescript@5.8.3) smol-toml: specifier: catalog:default - version: 1.8.0 + version: 1.9.0 ts-dedent: specifier: ^2.2.0 version: 2.2.0 @@ -4523,7 +4523,7 @@ importers: version: 4.1.0 smol-toml: specifier: catalog:default - version: 1.8.0 + version: 1.9.0 ts-dedent: specifier: ^2.2.0 version: 2.2.0 @@ -4861,7 +4861,7 @@ importers: version: 4.1.0 smol-toml: specifier: catalog:default - version: 1.8.0 + version: 1.9.0 supports-color: specifier: ^9.2.2 version: 9.2.2 @@ -15534,8 +15534,8 @@ packages: resolution: {integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==} engines: {node: '>= 6.0.0', npm: '>= 3.0.0'} - smol-toml@1.8.0: - resolution: {integrity: sha512-kCZr2V3ch9i00x8zXRhjUNVcjG9ijES5dDudkXvUVCT5QlJNQWElSJdZqyPemffHoLNUYwOcou0Fy+ojN0uHSQ==} + smol-toml@1.9.0: + resolution: {integrity: sha512-hpd+HLON7HdZXqYchMM/+LaTTbdK0AU3NngIJ4KVyWbY9bfQqdL9cD+4yf6dUoU2Ap4VsU0JkQi6FxAI1B2mXQ==} engines: {node: '>= 18'} snake-case@3.0.4: @@ -28308,7 +28308,7 @@ snapshots: smart-buffer@4.2.0: {} - smol-toml@1.8.0: {} + smol-toml@1.9.0: {} snake-case@3.0.4: dependencies: diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 4ac4994f78e..cfe12e54b79 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -132,7 +132,7 @@ catalog: "@cloudflare/workers-types": "^5.20260923.1" workerd: "1.20260923.1" jsonc-parser: "3.2.0" - smol-toml: "1.8.0" + smol-toml: "1.9.0" msw: "2.14.6" tinyglobby: "0.2.16" "tree-kill": "1.2.2" From 07c08c23aa68c57dbd02ff7195df5fedd1dfe316 Mon Sep 17 00:00:00 2001 From: Aadharsh Pannirselvam <19518661+oddharsh@users.noreply.github.com> Date: Thu, 24 Sep 2026 11:18:05 -0400 Subject: [PATCH 2/4] Import smol-toml as a namespace 1.9.0 deprecates the default export, and check:lint runs with --deny-warnings --type-aware, so all twelve default imports failed the Checks job. TomlError is now read off the namespace in parse.ts. --- packages/create-cloudflare/src/deploy.ts | 2 +- packages/create-cloudflare/src/helpers/files.ts | 2 +- packages/create-cloudflare/src/workers.ts | 2 +- packages/create-cloudflare/src/wrangler/config.ts | 2 +- packages/workers-auth/src/core/file-format.ts | 2 +- packages/workers-utils/src/config/index.ts | 2 +- packages/workers-utils/src/config/patch-config.ts | 2 +- packages/workers-utils/src/parse.ts | 4 ++-- .../config/validation/normalize-and-validate-config.test.ts | 2 +- packages/wrangler/src/__tests__/pages/deploy.test.ts | 2 +- packages/wrangler/src/deployments.ts | 2 +- packages/wrangler/src/pages/download-config.ts | 2 +- 12 files changed, 13 insertions(+), 13 deletions(-) diff --git a/packages/create-cloudflare/src/deploy.ts b/packages/create-cloudflare/src/deploy.ts index b69cc3e9951..ce2327e03ed 100644 --- a/packages/create-cloudflare/src/deploy.ts +++ b/packages/create-cloudflare/src/deploy.ts @@ -12,7 +12,7 @@ import { C3_DEFAULTS, openInBrowser } from "helpers/cli"; import { readFile } from "helpers/files"; import { detectPackageManager } from "helpers/packageManagers"; import { poll } from "helpers/poll"; -import TOML from "smol-toml"; +import * as TOML from "smol-toml"; import { isInsideGitRepo } from "./git"; import { chooseAccount, wranglerLogin } from "./wrangler/accounts"; import { diff --git a/packages/create-cloudflare/src/helpers/files.ts b/packages/create-cloudflare/src/helpers/files.ts index 3a3c34d02c5..b7bc75f072e 100644 --- a/packages/create-cloudflare/src/helpers/files.ts +++ b/packages/create-cloudflare/src/helpers/files.ts @@ -1,7 +1,7 @@ import fs, { existsSync, statSync } from "node:fs"; import { join } from "node:path"; import { parse, stringify } from "comment-json"; -import TOML from "smol-toml"; +import * as TOML from "smol-toml"; import type { C3Context, PackageJson } from "types"; export const copyFile = (path: string, dest: string) => { diff --git a/packages/create-cloudflare/src/workers.ts b/packages/create-cloudflare/src/workers.ts index 26f04a482c2..a4006419ff0 100644 --- a/packages/create-cloudflare/src/workers.ts +++ b/packages/create-cloudflare/src/workers.ts @@ -9,7 +9,7 @@ import { readFile, readJSON, usesTypescript, writeFile } from "helpers/files"; import { detectPackageManager } from "helpers/packageManagers"; import { installPackages } from "helpers/packages"; import * as jsonc from "jsonc-parser"; -import TOML from "smol-toml"; +import * as TOML from "smol-toml"; import { readWranglerJsonOrJsonc, readWranglerToml, diff --git a/packages/create-cloudflare/src/wrangler/config.ts b/packages/create-cloudflare/src/wrangler/config.ts index 3c62e8a1d83..01dda8e8044 100644 --- a/packages/create-cloudflare/src/wrangler/config.ts +++ b/packages/create-cloudflare/src/wrangler/config.ts @@ -13,7 +13,7 @@ import { readJSONWithComments, writeJSONWithComments, } from "helpers/json"; -import TOML from "smol-toml"; +import * as TOML from "smol-toml"; import type { CommentObject, Reviver } from "comment-json"; import type { TomlTable } from "smol-toml"; import type { C3Context } from "types"; diff --git a/packages/workers-auth/src/core/file-format.ts b/packages/workers-auth/src/core/file-format.ts index 21faebcf9f5..4af453e2c47 100644 --- a/packages/workers-auth/src/core/file-format.ts +++ b/packages/workers-auth/src/core/file-format.ts @@ -1,5 +1,5 @@ import { parseTOML } from "@cloudflare/workers-utils"; -import TOML from "smol-toml"; +import * as TOML from "smol-toml"; /** * On-disk serialization format for a CLI's config/credential files. diff --git a/packages/workers-utils/src/config/index.ts b/packages/workers-utils/src/config/index.ts index f5dfcbab8b0..d664cd72818 100644 --- a/packages/workers-utils/src/config/index.ts +++ b/packages/workers-utils/src/config/index.ts @@ -1,4 +1,4 @@ -import TOML from "smol-toml"; +import * as TOML from "smol-toml"; import { parseJSONC, parseTOML, readFileSync } from "../parse"; import { resolveWranglerConfigPath } from "./config-helpers"; import type { Config, RawConfig } from "./config"; diff --git a/packages/workers-utils/src/config/patch-config.ts b/packages/workers-utils/src/config/patch-config.ts index 6c4ae76f87f..0cb5da8ee62 100644 --- a/packages/workers-utils/src/config/patch-config.ts +++ b/packages/workers-utils/src/config/patch-config.ts @@ -1,6 +1,6 @@ import { writeFileSync } from "node:fs"; import { applyEdits, format, modify } from "jsonc-parser"; -import TOML from "smol-toml"; +import * as TOML from "smol-toml"; import { parseJSONC, parseTOML, readFileSync } from "../parse"; import type { RawConfig } from "./config"; import type { JSONPath } from "jsonc-parser"; diff --git a/packages/workers-utils/src/parse.ts b/packages/workers-utils/src/parse.ts index d50c7b48a27..4ba8b276f88 100644 --- a/packages/workers-utils/src/parse.ts +++ b/packages/workers-utils/src/parse.ts @@ -1,7 +1,7 @@ import { readFileSync as fsReadFileSync } from "node:fs"; import { resolve } from "node:path"; import * as jsoncParser from "jsonc-parser"; -import TOML, { TomlError } from "smol-toml"; +import * as TOML from "smol-toml"; import { UserError } from "./errors"; import type { TelemetryMessage } from "./errors"; import type { ParseError as JsoncParseError } from "jsonc-parser"; @@ -117,7 +117,7 @@ export function parseTOML(tomlContent: string, filePath?: string): unknown { try { return TOML.parse(tomlContent); } catch (err) { - if (!(err instanceof TomlError)) { + if (!(err instanceof TOML.TomlError)) { throw err; } diff --git a/packages/workers-utils/tests/config/validation/normalize-and-validate-config.test.ts b/packages/workers-utils/tests/config/validation/normalize-and-validate-config.test.ts index 432fb7ee233..daae75b6127 100644 --- a/packages/workers-utils/tests/config/validation/normalize-and-validate-config.test.ts +++ b/packages/workers-utils/tests/config/validation/normalize-and-validate-config.test.ts @@ -1,5 +1,5 @@ import path from "node:path"; -import TOML from "smol-toml"; +import * as TOML from "smol-toml"; import { assert, describe, it, test, vi } from "vitest"; import { normalizeAndValidateConfig } from "../../../src/config/validation"; import { normalizeString } from "../../../src/test-helpers"; diff --git a/packages/wrangler/src/__tests__/pages/deploy.test.ts b/packages/wrangler/src/__tests__/pages/deploy.test.ts index d330b0376c5..3bc293b20af 100644 --- a/packages/wrangler/src/__tests__/pages/deploy.test.ts +++ b/packages/wrangler/src/__tests__/pages/deploy.test.ts @@ -7,7 +7,7 @@ import { } from "@cloudflare/workers-utils/test-helpers"; import ci from "ci-info"; import { http, HttpResponse } from "msw"; -import TOML from "smol-toml"; +import * as TOML from "smol-toml"; import { x } from "tinyexec"; import dedent from "ts-dedent"; /* eslint-disable-next-line no-restricted-imports -- diff --git a/packages/wrangler/src/deployments.ts b/packages/wrangler/src/deployments.ts index 47ff9d52d6c..9a84b1bdd9a 100644 --- a/packages/wrangler/src/deployments.ts +++ b/packages/wrangler/src/deployments.ts @@ -5,7 +5,7 @@ import { UserError, } from "@cloudflare/workers-utils"; import chalk from "chalk"; -import TOML from "smol-toml"; +import * as TOML from "smol-toml"; import { FormData } from "undici"; import { fetchResult } from "./cfetch"; import { readConfig } from "./config"; diff --git a/packages/wrangler/src/pages/download-config.ts b/packages/wrangler/src/pages/download-config.ts index 171f9d2c06d..5863358adfc 100644 --- a/packages/wrangler/src/pages/download-config.ts +++ b/packages/wrangler/src/pages/download-config.ts @@ -8,7 +8,7 @@ import { UserError, } from "@cloudflare/workers-utils"; import chalk from "chalk"; -import TOML from "smol-toml"; +import * as TOML from "smol-toml"; import { fetchResult } from "../cfetch"; import { getConfigCache } from "../config-cache"; import { createCommand } from "../core/create-command"; From e0b1b460f5241fbd210cb7a34a863afe6507b156 Mon Sep 17 00:00:00 2001 From: Aadharsh Pannirselvam <19518661+oddharsh@users.noreply.github.com> Date: Thu, 24 Sep 2026 11:22:31 -0400 Subject: [PATCH 3/4] Describe the smol-toml bump by its user-facing effects --- .changeset/smol-toml-1-9.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.changeset/smol-toml-1-9.md b/.changeset/smol-toml-1-9.md index 9843279c59f..d59737a3b1d 100644 --- a/.changeset/smol-toml-1-9.md +++ b/.changeset/smol-toml-1-9.md @@ -5,6 +5,8 @@ "@cloudflare/workers-auth": patch --- -Update `smol-toml` to 1.9.0 +Update `smol-toml` to 1.9.0 to fix slow parsing of very large TOML files -This updates the bundled TOML parser that reads `wrangler.toml` to a version that addresses `GHSA-r4xh-jqrq-34v2`, which affects every version up to and including 1.8.0: parse time grew quadratically with the number of key lines, so a 40,000-line document took 259 ms on 1.8.0 and takes 17 ms on 1.9.0. Some TOML syntax errors now point at the offending character; for example, `INVALID "FILE` is reported as `illegal character in key` at column 8 instead of `incomplete key-value` at column 0. +Parse time for TOML config files now grows linearly with their size, instead of with its square: a 40,000-line file that took 259 ms to parse now takes 17 ms, while typical `wrangler.toml` files parse in the same time as before. This addresses the `GHSA-r4xh-jqrq-34v2` advisory against earlier versions of the parser. + +Some TOML syntax errors now point at the character that caused them. For example, a `wrangler.toml` containing `INVALID "FILE` is now reported as `illegal character in key` at the `"`, rather than `incomplete key-value` at the start of the line. From db6ff5f7c130748d4b2ecbd8bc6c0e0040e3e0bc Mon Sep 17 00:00:00 2001 From: Aadharsh Pannirselvam <19518661+oddharsh@users.noreply.github.com> Date: Thu, 24 Sep 2026 11:42:43 -0400 Subject: [PATCH 4/4] Drop the parseTOML test comment --- packages/workers-utils/tests/parse.test.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/workers-utils/tests/parse.test.ts b/packages/workers-utils/tests/parse.test.ts index 8aad2bb5329..928467b3de1 100644 --- a/packages/workers-utils/tests/parse.test.ts +++ b/packages/workers-utils/tests/parse.test.ts @@ -10,8 +10,6 @@ import { } from "../src/parse"; describe("parseTOML", () => { - // smol-toml 1.9 returns null-prototype objects, so these compare structure with - // `toEqual`; `toStrictEqual` would also compare prototypes against `{}`. it("should parse toml that is empty", ({ expect }) => { expect(parseTOML("")).toEqual({}); });