From a65dc80bc19c250c8e9837c802d4a46921ab066c Mon Sep 17 00:00:00 2001 From: Jordan Pittman Date: Mon, 13 Oct 2025 10:24:56 -0400 Subject: [PATCH 1/2] =?UTF-8?q?Don=E2=80=99t=20index=20into=20strings=20wi?= =?UTF-8?q?th=20the=20theme()=20function?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Indexing into a string is only ever going to produce a single character and is almost guaranteed to be a mistake. The legacy keypath notation is meant to traverse objects and arrays — not strings. --- .../tailwindcss/src/compat/config.test.ts | 32 +++++++++++++++++++ .../src/compat/plugin-functions.ts | 5 +++ 2 files changed, 37 insertions(+) diff --git a/packages/tailwindcss/src/compat/config.test.ts b/packages/tailwindcss/src/compat/config.test.ts index 8256f663ca17..d86d5304b3e7 100644 --- a/packages/tailwindcss/src/compat/config.test.ts +++ b/packages/tailwindcss/src/compat/config.test.ts @@ -1687,3 +1687,35 @@ test('handles setting theme keys to null', async () => { " `) }) + +test('The theme() function does not try indexing into strings', async () => { + let compiler = await compile(css` + @theme default { + --color-what-50: #f00; + --color-what-950: #f00; + } + + @theme { + /* + * The value of this theme variable is > 50 chars because colors.what.50 was previously + * indexing the string: "light-dark(theme(colors.what.950), theme(colors.what.50))" + * because the resolved config contained an object with a "what" key that was that string + */ + --color-what: light-dark(theme(colors.what.950), theme(colors.what.50)); + } + + @source inline("text-what"); + + @tailwind utilities; + `) + + expect(compiler.build([])).toMatchInlineSnapshot(` + ":root, :host { + --color-what: light-dark(#f00, #f00); + } + .text-what { + color: var(--color-what); + } + " + `) +}) diff --git a/packages/tailwindcss/src/compat/plugin-functions.ts b/packages/tailwindcss/src/compat/plugin-functions.ts index 339bd11c6ce7..f311ad1e8c43 100644 --- a/packages/tailwindcss/src/compat/plugin-functions.ts +++ b/packages/tailwindcss/src/compat/plugin-functions.ts @@ -233,6 +233,11 @@ function get(obj: any, path: string[]) { continue } + // We never want to index into strings + if (typeof obj === 'string') { + return undefined + } + obj = obj[key] } From b68430e90a7e82d346cd19c79da4dd84e811daea Mon Sep 17 00:00:00 2001 From: Jordan Pittman Date: Mon, 13 Oct 2025 10:25:44 -0400 Subject: [PATCH 2/2] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 375d5079e27e..56d453605f9c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fix resolving theme keys when starting with the name of another theme key in JS configs and plugins ([#19097](https://github.com/tailwindlabs/tailwindcss/pull/19097)) - Allow named groups in combination with `not-*`, `has-*`, and `in-*` ([#19100](https://github.com/tailwindlabs/tailwindcss/pull/19100)) - Prevent important utilities from affecting other utilities ([#19110](https://github.com/tailwindlabs/tailwindcss/pull/19110)) +- Don’t index into strings with the `theme(…)` function ([#19111](https://github.com/tailwindlabs/tailwindcss/pull/19111)) - Upgrade: Canonicalize utilities containing `0` values ([#19095](https://github.com/tailwindlabs/tailwindcss/pull/19095)) ## [4.1.14] - 2025-10-01