Skip to content

fix(astro,tanstack-react-start): Fix XSS via user-controlled JSON#9166

Open
dominic-clerk wants to merge 2 commits into
mainfrom
dc-initial-state-xss
Open

fix(astro,tanstack-react-start): Fix XSS via user-controlled JSON#9166
dominic-clerk wants to merge 2 commits into
mainfrom
dc-initial-state-xss

Conversation

@dominic-clerk

@dominic-clerk dominic-clerk commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

Description

The JSON injected in the page may contain user-controlled data in certain circumstances. This PR introduces a helper that ensures the JSON cannot be broken out of to cause XSS.

Fixes SDK-57
Fixes SDK-58

Checklist

  • pnpm test runs as expected.
  • pnpm build runs as expected.
  • (If applicable) JSDoc comments have been added or updated for any package exports
  • (If applicable) Documentation has been updated

Type of change

  • 🐛 Bug fix
  • 🌟 New feature
  • 🔨 Breaking change
  • 📖 Refactoring / dependency upgrade / documentation
  • other:

Summary by CodeRabbit

  • Security

    • Strengthened server-rendered embedding of authentication state by safely escaping HTML-breaking characters and Unicode line terminators to help prevent script breakouts and stored XSS scenarios.
    • Ensures the serialized payload remains valid and accurately round-trips back to the original values on the client.
  • Bug Fixes

    • Fixed potential stored XSS issues affecting Astro and TanStack React Start authentication state serialization.
  • Tests

    • Added coverage for the HTML-safe JSON serialization behavior, including edge cases and round-tripping.

The JSON injected in the page may contain user-controlled data in
certain circumstances. This PR introduces a helper that ensures the JSON
cannot be broken out of to cause XSS.
@changeset-bot

changeset-bot Bot commented Jul 15, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 7f76f3b

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 23 packages
Name Type
@clerk/tanstack-react-start Patch
@clerk/shared Patch
@clerk/astro Patch
@clerk/backend Patch
@clerk/chrome-extension Patch
@clerk/clerk-js Patch
@clerk/electron Patch
@clerk/expo-passkeys Patch
@clerk/expo Patch
@clerk/express Patch
@clerk/fastify Patch
@clerk/headless Patch
@clerk/hono Patch
@clerk/localizations Patch
@clerk/msw Patch
@clerk/nextjs Patch
@clerk/nuxt Patch
@clerk/react-router Patch
@clerk/react Patch
@clerk/testing Patch
@clerk/ui Patch
@clerk/vue Patch
@clerk/swingset Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@vercel

vercel Bot commented Jul 15, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
clerk-js-sandbox Ready Ready Preview, Comment Jul 15, 2026 11:57am
swingset Ready Ready Preview, Comment Jul 15, 2026 11:57am

Request Review

@coderabbitai

coderabbitai Bot commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Repository UI (inherited)

Review profile: CHILL

Plan: Pro Plus

Run ID: 8c86f708-7519-4a26-a039-399430979db9

📥 Commits

Reviewing files that changed from the base of the PR and between d655a74 and 7f76f3b.

📒 Files selected for processing (1)
  • packages/shared/src/htmlSafeJson.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/shared/src/htmlSafeJson.ts

📝 Walkthrough

Walkthrough

Clerk adds htmlSafeJson to escape HTML-sensitive characters during SSR JSON serialization. Astro and TanStack React Start use it for inline script state, with tests covering breakout sequences, Unicode separators, round-tripping, and undefined values.

Changes

SSR script serialization

Layer / File(s) Summary
HTML-safe JSON helper and validation
packages/shared/src/htmlSafeJson.ts, packages/shared/src/__tests__/htmlSafeJson.spec.ts
Adds escaping for <, >, /, U+2028, and U+2029, with tests confirming safe output and JSON round-tripping.
SSR script embedding integrations
packages/astro/src/server/clerk-middleware.ts, packages/tanstack-react-start/src/client/ClerkProvider.tsx, .changeset/open-buckets-bake.md
Uses htmlSafeJson for Astro auth/environment scripts and TanStack initial state, and records patch releases for affected packages.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Poem

A rabbit hops through JSON bright,
Escaping chevrons left and right.
No script-tag tricks can make it flee,
The state still parses faithfully.
Patch notes rustle—safe and sweet!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects the XSS fix affecting Astro and TanStack React Start.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
packages/shared/src/__tests__/htmlSafeJson.spec.ts (1)

5-37: 📐 Maintainability & Code Quality | 🔵 Trivial | 🏗️ Heavy lift

Add or confirm integration coverage for the SSR script boundaries.

These tests validate htmlSafeJson, but not the generated Astro <script> markup or TanStack ScriptOnce output. Add focused integration tests with </script> and U+2028/U+2029 payloads, or confirm equivalent tests already exist, so either integration cannot regress to raw JSON.stringify.

As per coding guidelines, new functionality should include integration coverage and edge-case verification.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/shared/src/__tests__/htmlSafeJson.spec.ts` around lines 5 - 37, Add
integration coverage for the SSR script-rendering paths that consume
htmlSafeJson, including Astro-generated script markup and TanStack ScriptOnce
output. Use payloads containing </script> and U+2028/U+2029, assert the rendered
markup remains safely escaped rather than raw JSON.stringify output, and verify
the payload still round-trips when parsed.

Source: Coding guidelines

packages/shared/src/htmlSafeJson.ts (1)

5-13: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Complete the public API JSDoc.

This exported, cross-package helper is missing the required @param, @returns, @throws, and @example tags. Document the "undefined" result and serialization errors; the Docs team should also review the generated reference documentation.

As per coding guidelines, public APIs require complete JSDoc tags. As per path instructions, exported reference-facing APIs may appear in generated Clerk Docs.

Suggested documentation addition
 /**
  * `JSON.stringify` that is safe to embed directly inside an HTML `<script>` element.
+ *
+ * `@param` value - The value to serialize.
+ * `@returns` HTML-safe JSON, or `"undefined"` when serialization produces no value.
+ * `@throws` {TypeError} If the value cannot be serialized.
+ * `@example`
+ * JSON.parse(htmlSafeJson({ html: '</script>' }));
  */
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/shared/src/htmlSafeJson.ts` around lines 5 - 13, Complete the JSDoc
for the exported htmlSafeJson function with `@param`, `@returns`, `@throws`, and
`@example` tags. Document that undefined produces the string "undefined" and that
serialization errors may be thrown, and include a representative safe-HTML
serialization example without changing the implementation.

Sources: Coding guidelines, Path instructions

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@packages/shared/src/__tests__/htmlSafeJson.spec.ts`:
- Around line 5-37: Add integration coverage for the SSR script-rendering paths
that consume htmlSafeJson, including Astro-generated script markup and TanStack
ScriptOnce output. Use payloads containing </script> and U+2028/U+2029, assert
the rendered markup remains safely escaped rather than raw JSON.stringify
output, and verify the payload still round-trips when parsed.

In `@packages/shared/src/htmlSafeJson.ts`:
- Around line 5-13: Complete the JSDoc for the exported htmlSafeJson function
with `@param`, `@returns`, `@throws`, and `@example` tags. Document that undefined
produces the string "undefined" and that serialization errors may be thrown, and
include a representative safe-HTML serialization example without changing the
implementation.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Repository UI (inherited)

Review profile: CHILL

Plan: Pro Plus

Run ID: d69a6635-cccd-4bb5-b0c2-db08ff477183

📥 Commits

Reviewing files that changed from the base of the PR and between 99ac79f and d655a74.

📒 Files selected for processing (5)
  • .changeset/open-buckets-bake.md
  • packages/astro/src/server/clerk-middleware.ts
  • packages/shared/src/__tests__/htmlSafeJson.spec.ts
  • packages/shared/src/htmlSafeJson.ts
  • packages/tanstack-react-start/src/client/ClerkProvider.tsx

@github-actions

github-actions Bot commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

API Changes Report

Generated by Break Check on 2026-07-15T11:58:40.294Z

Summary

Metric Count
Packages analyzed 19
Packages with changes 1
🔴 Breaking changes 0
🟡 Non-breaking changes 0
🟢 Additions 1

@clerk/shared

Current version: 4.25.3
Recommended bump: MINOR → 4.26.0

Subpath ./htmlSafeJson

🟢 Additions (1)

Added: ./htmlSafeJson

New subpath export ./htmlSafeJson (1 exported member)


Report generated by Break Check

Last ran on 7f76f3b.

@pkg-pr-new

pkg-pr-new Bot commented Jul 15, 2026

Copy link
Copy Markdown

Open in StackBlitz

@clerk/astro

npm i https://pkg.pr.new/@clerk/astro@9166

@clerk/backend

npm i https://pkg.pr.new/@clerk/backend@9166

@clerk/chrome-extension

npm i https://pkg.pr.new/@clerk/chrome-extension@9166

@clerk/clerk-js

npm i https://pkg.pr.new/@clerk/clerk-js@9166

@clerk/electron

npm i https://pkg.pr.new/@clerk/electron@9166

@clerk/electron-passkeys

npm i https://pkg.pr.new/@clerk/electron-passkeys@9166

@clerk/eslint-plugin

npm i https://pkg.pr.new/@clerk/eslint-plugin@9166

@clerk/expo

npm i https://pkg.pr.new/@clerk/expo@9166

@clerk/expo-passkeys

npm i https://pkg.pr.new/@clerk/expo-passkeys@9166

@clerk/express

npm i https://pkg.pr.new/@clerk/express@9166

@clerk/fastify

npm i https://pkg.pr.new/@clerk/fastify@9166

@clerk/hono

npm i https://pkg.pr.new/@clerk/hono@9166

@clerk/localizations

npm i https://pkg.pr.new/@clerk/localizations@9166

@clerk/nextjs

npm i https://pkg.pr.new/@clerk/nextjs@9166

@clerk/nuxt

npm i https://pkg.pr.new/@clerk/nuxt@9166

@clerk/react

npm i https://pkg.pr.new/@clerk/react@9166

@clerk/react-router

npm i https://pkg.pr.new/@clerk/react-router@9166

@clerk/shared

npm i https://pkg.pr.new/@clerk/shared@9166

@clerk/tanstack-react-start

npm i https://pkg.pr.new/@clerk/tanstack-react-start@9166

@clerk/testing

npm i https://pkg.pr.new/@clerk/testing@9166

@clerk/ui

npm i https://pkg.pr.new/@clerk/ui@9166

@clerk/upgrade

npm i https://pkg.pr.new/@clerk/upgrade@9166

@clerk/vue

npm i https://pkg.pr.new/@clerk/vue@9166

commit: 7f76f3b

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant