-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
fix: make nonce accessible in headers #6359
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
added csp e2e test for react
📝 WalkthroughWalkthroughAdds CSP nonce support and end-to-end CSP test apps (React and Solid). Threads SSR nonce through router core and asset contexts, generates nonces server-side, injects nonce into CSP headers and asset tags, and adds Playwright tests and project scaffolding for verification. Changes
Sequence Diagram(s)sequenceDiagram
participant Server
participant Router as Router Core
participant AssetCtx as Asset Context
participant Head as Head/Scripts
participant Client as Client Hydration
Server->>Router: initialize router with ssr options
Router->>Router: generate nonce (crypto.getRandomValues)
Router->>AssetCtx: include ssr.nonce in assetContext
Router->>Head: run headers/head with assetContext
Head->>Server: emit HTML with CSP header and nonce attributes
Server-->>Client: send CSP-protected HTML
Client->>AssetCtx: construct assetContext (includes router.options.ssr)
Client->>Head: execute head/scripts during hydration
Head->>Client: apply nonce to inline/external assets and complete hydration
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~30 minutes Possibly related PRs
Suggested labels
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
Comment |
|
View your CI Pipeline Execution ↗ for commit d199d7c
☁️ Nx Cloud last updated this comment at |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
packages/router-core/src/route.ts (1)
1315-1329:headers()now returningundefined: ensure callers normalize before iterating/merging.
Type change is fine, but any code that doesObject.entries(await headers)/ spreads / merges needs a?? {}guard.#!/bin/bash set -euo pipefail # Locate headers() invocations and inspect how the return is used. rg -n --hidden --glob '!**/node_modules/**' "\.options\.headers\?\.\s*\(" packages/router-core/src -S rg -n --hidden --glob '!**/node_modules/**' "\bheaders\?\.\s*\(" packages/router-core/src -S
🧹 Nitpick comments (5)
e2e/react-start/csp/.gitignore (1)
1-4: Consider ignoring Playwright artifacts and narrowing*.txt.It’s common to also ignore
playwright-report/andtest-results/. Also,*.txtis very broad for a fixture workspace and may hide useful committed files.e2e/react-start/csp/tsconfig.json (1)
1-22: TS config looks fine for a strict Vite/React fixture.Optional: add
"types": ["node", "vite/client"]if you hit missing globals (e.g.process,import.meta.env) during typecheck in this workspace.e2e/react-start/csp/vite.config.ts (1)
1-9: Make dev server port followVITE_SERVER_PORT(fallback to 3000).Proposed change
import { defineConfig } from 'vite' import { tanstackStart } from '@tanstack/react-start/plugin/vite' export default defineConfig({ server: { - port: 3000, + port: Number.parseInt(process.env.VITE_SERVER_PORT ?? '3000', 10), }, plugins: [tanstackStart()], })packages/router-core/src/ssr/ssr-client.ts (1)
189-196: NormalizeassetContext.ssrto the expected “options object” shape (avoid boolean/string leakage).
Ifrouter.options.ssrcan befalse/'data-only'(or similar), passing it through may surprise asset hooks expecting an object withnonce. Consider normalizing toundefinedunless it’s an object.Proposed tweak
- const assetContext = { - ssr: router.options.ssr, + const ssr = + router.options.ssr && typeof router.options.ssr === 'object' + ? router.options.ssr + : undefined + + const assetContext = { + ssr, matches: router.state.matches, match, params: match.params, loaderData: match.loaderData, }e2e/react-start/csp/public/external.js (1)
1-3: Avoid potentialno-undeflint failures forwindowin this standalone JS fixture.
If this directory is linted, add a browser directive (or guardtypeof window !== 'undefined').Possible minimal change
+/* eslint-env browser */ // This script sets a window global when loaded // Using a global avoids race conditions with React and DOM ownership issues window.__EXTERNAL_SCRIPT_LOADED__ = true
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (15)
e2e/react-start/csp/.gitignoree2e/react-start/csp/package.jsone2e/react-start/csp/playwright.config.tse2e/react-start/csp/public/external.csse2e/react-start/csp/public/external.jse2e/react-start/csp/src/routeTree.gen.tse2e/react-start/csp/src/router.tsxe2e/react-start/csp/src/routes/__root.tsxe2e/react-start/csp/src/routes/index.tsxe2e/react-start/csp/tests/csp.spec.tse2e/react-start/csp/tsconfig.jsone2e/react-start/csp/vite.config.tspackages/router-core/src/load-matches.tspackages/router-core/src/route.tspackages/router-core/src/ssr/ssr-client.ts
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Use TypeScript strict mode with extensive type safety for all code
Files:
packages/router-core/src/load-matches.tse2e/react-start/csp/src/router.tsxe2e/react-start/csp/src/routes/__root.tsxe2e/react-start/csp/tests/csp.spec.tse2e/react-start/csp/src/routes/index.tsxpackages/router-core/src/ssr/ssr-client.tse2e/react-start/csp/vite.config.tse2e/react-start/csp/playwright.config.tspackages/router-core/src/route.tse2e/react-start/csp/src/routeTree.gen.ts
**/*.{js,ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Implement ESLint rules for router best practices using the ESLint plugin router
Files:
packages/router-core/src/load-matches.tse2e/react-start/csp/src/router.tsxe2e/react-start/csp/public/external.jse2e/react-start/csp/src/routes/__root.tsxe2e/react-start/csp/tests/csp.spec.tse2e/react-start/csp/src/routes/index.tsxpackages/router-core/src/ssr/ssr-client.tse2e/react-start/csp/vite.config.tse2e/react-start/csp/playwright.config.tspackages/router-core/src/route.tse2e/react-start/csp/src/routeTree.gen.ts
**/package.json
📄 CodeRabbit inference engine (AGENTS.md)
Use workspace protocol
workspace:*for internal dependencies in package.json files
Files:
e2e/react-start/csp/package.json
🧠 Learnings (10)
📚 Learning: 2025-10-01T18:31:35.420Z
Learnt from: schiller-manuel
Repo: TanStack/router PR: 5330
File: e2e/react-start/custom-basepath/src/routeTree.gen.ts:58-61
Timestamp: 2025-10-01T18:31:35.420Z
Learning: Do not review files named `routeTree.gen.ts` in TanStack Router repositories, as these are autogenerated files that should not be manually modified.
Applied to files:
e2e/react-start/csp/.gitignoree2e/react-start/csp/src/router.tsxe2e/react-start/csp/src/routes/__root.tsxe2e/react-start/csp/src/routeTree.gen.ts
📚 Learning: 2025-10-08T08:11:47.088Z
Learnt from: nlynzaad
Repo: TanStack/router PR: 5402
File: packages/router-generator/tests/generator/no-formatted-route-tree/routeTree.nonnested.snapshot.ts:19-21
Timestamp: 2025-10-08T08:11:47.088Z
Learning: Test snapshot files in the router-generator tests directory (e.g., files matching the pattern `packages/router-generator/tests/generator/**/routeTree*.snapshot.ts` or `routeTree*.snapshot.js`) should not be modified or have issues flagged, as they are fixtures used to verify the generator's output and are intentionally preserved as-is.
Applied to files:
e2e/react-start/csp/src/router.tsxe2e/react-start/csp/src/routes/__root.tsxpackages/router-core/src/route.tse2e/react-start/csp/src/routeTree.gen.ts
📚 Learning: 2025-12-17T02:17:55.086Z
Learnt from: schiller-manuel
Repo: TanStack/router PR: 6120
File: packages/router-generator/src/generator.ts:654-657
Timestamp: 2025-12-17T02:17:55.086Z
Learning: In `packages/router-generator/src/generator.ts`, pathless_layout routes must receive a `path` property when they have a `cleanedPath`, even though they are non-path routes. This is necessary because child routes inherit the path from their parent, and without this property, child routes would not have the correct full path at runtime.
Applied to files:
e2e/react-start/csp/src/router.tsxe2e/react-start/csp/src/routes/__root.tsxe2e/react-start/csp/src/routes/index.tsxpackages/router-core/src/route.tse2e/react-start/csp/src/routeTree.gen.ts
📚 Learning: 2025-12-06T15:03:07.223Z
Learnt from: CR
Repo: TanStack/router PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-06T15:03:07.223Z
Learning: Applies to **/*.{js,ts,tsx} : Implement ESLint rules for router best practices using the ESLint plugin router
Applied to files:
e2e/react-start/csp/src/router.tsxe2e/react-start/csp/src/routes/__root.tsxe2e/react-start/csp/src/routes/index.tsxe2e/react-start/csp/tsconfig.jsone2e/react-start/csp/src/routeTree.gen.ts
📚 Learning: 2025-11-02T16:16:24.898Z
Learnt from: nlynzaad
Repo: TanStack/router PR: 5732
File: packages/start-client-core/src/client/hydrateStart.ts:6-9
Timestamp: 2025-11-02T16:16:24.898Z
Learning: In packages/start-client-core/src/client/hydrateStart.ts, the `import/no-duplicates` ESLint disable is necessary for imports from `#tanstack-router-entry` and `#tanstack-start-entry` because both aliases resolve to the same placeholder file (`fake-start-entry.js`) in package.json during static analysis, even though they resolve to different files at runtime.
Applied to files:
e2e/react-start/csp/src/router.tsxpackages/router-core/src/ssr/ssr-client.tse2e/react-start/csp/package.jsone2e/react-start/csp/tsconfig.jsone2e/react-start/csp/src/routeTree.gen.ts
📚 Learning: 2025-12-25T13:04:55.492Z
Learnt from: nlynzaad
Repo: TanStack/router PR: 6215
File: e2e/react-start/custom-basepath/package.json:13-17
Timestamp: 2025-12-25T13:04:55.492Z
Learning: In the TanStack Router repository, e2e test scripts are specifically designed to run in CI (which uses a Unix environment), so Unix-specific commands (like `rm -rf`, `&` for backgrounding, and direct environment variable assignments without `cross-env`) are acceptable in e2e test npm scripts.
Applied to files:
e2e/react-start/csp/playwright.config.tse2e/react-start/csp/package.json
📚 Learning: 2025-10-09T12:59:14.842Z
Learnt from: hokkyss
Repo: TanStack/router PR: 5418
File: e2e/react-start/custom-identifier-prefix/public/site.webmanifest:2-3
Timestamp: 2025-10-09T12:59:14.842Z
Learning: In e2e test fixtures (files under e2e directories), empty or placeholder values in configuration files like site.webmanifest are acceptable and should not be flagged unless the test specifically validates those fields.
Applied to files:
e2e/react-start/csp/playwright.config.ts
📚 Learning: 2025-12-06T15:03:07.223Z
Learnt from: CR
Repo: TanStack/router PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-06T15:03:07.223Z
Learning: Applies to **/*.{ts,tsx} : Use TypeScript strict mode with extensive type safety for all code
Applied to files:
e2e/react-start/csp/tsconfig.json
📚 Learning: 2025-12-21T12:52:35.231Z
Learnt from: Sheraff
Repo: TanStack/router PR: 6171
File: packages/router-core/src/new-process-route-tree.ts:898-898
Timestamp: 2025-12-21T12:52:35.231Z
Learning: In `packages/router-core/src/new-process-route-tree.ts`, the matching logic intentionally allows paths without trailing slashes to match index routes with trailing slashes (e.g., `/a` can match `/a/` route), but not vice-versa (e.g., `/a/` cannot match `/a` layout route). This is implemented via the condition `!pathIsIndex || node.kind === SEGMENT_TYPE_INDEX` and is a deliberate design decision to provide better UX by being permissive with missing trailing slashes.
Applied to files:
e2e/react-start/csp/src/routeTree.gen.ts
📚 Learning: 2025-12-06T15:03:07.223Z
Learnt from: CR
Repo: TanStack/router PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-06T15:03:07.223Z
Learning: Use file-based routing in `src/routes/` directories or code-based routing with route definitions
Applied to files:
e2e/react-start/csp/src/routeTree.gen.ts
🧬 Code graph analysis (1)
e2e/react-start/csp/src/routes/__root.tsx (2)
e2e/react-start/csp/src/routes/index.tsx (1)
Route(4-6)packages/router-core/src/route.ts (1)
Route(586-776)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: Test
- GitHub Check: Preview
🔇 Additional comments (16)
packages/router-core/src/load-matches.ts (1)
540-570: SSR options are now properly available toheaders(),scripts(), andhead()viaassetContext.The
assetContextis correctly typed asAssetFnContextOptions(route.ts:1122), which definesssr?: { nonce?: string }. Route callbacks can now readssr.noncefor CSP nonce injection. The pattern is consistently implemented in both server (ssr-server.ts) and client (ssr-client.ts) paths.e2e/react-start/csp/playwright.config.ts (1)
1-35: This config uses the standard pattern already established in the repo.The pattern of top-level
awaitwith JSON import attributes (with { type: 'json' }) is identical to what's already used ine2e/react-start/basic/playwright.config.ts,e2e/react-start/basic-auth/playwright.config.ts, ande2e/react-start/custom-basepath/playwright.config.ts. The tsconfig.json explicitly enablesresolveJsonModule: true, and @playwright/test ^1.50.1 fully supports both features. The Unix-style environment variables inwebServer.commandare acceptable for this repo's e2e CI setup.Likely an incorrect or invalid review comment.
e2e/react-start/csp/public/external.css (1)
1-4: LGTM for an e2e fixture.packages/router-core/src/route.ts (1)
1122-1136: TheAssetFnContextOptions.ssrtype andSSROptionserve different purposes and should not be aligned.SSROptionis a route-level configuration flag (boolean | 'data-only'), whileAssetFnContextOptions.ssris asset callback context metadata containing a nonce. SinceSSROptionis a union type rather than an extensible object, it cannot "gain more fields" to cause drift. The current separation is correct by design.Likely an incorrect or invalid review comment.
e2e/react-start/csp/src/router.tsx (1)
5-19: No changes needed. ThecreateIsomorphicFn().server()pattern is handled safely by the build system: the server environment receives the crypto-based nonce generation, while the client receives a no-op. SincegetRouter()is only called during server-side SSR (withinrunWithStartContext), andcrypto.getRandomValuesis available in Node.js, the code is correct and safe.e2e/react-start/csp/package.json (1)
1-29: LGTM! Clean e2e test package configuration.The package.json correctly uses the
workspace:*protocol for internal dependencies, includes appropriate React 19 and Vite 7 dependencies, and defines comprehensive test scripts. The Unix-specific commands in the test script are acceptable for CI environments.e2e/react-start/csp/src/routes/index.tsx (1)
1-25: LGTM! Clean test route implementation.The route component follows TanStack Router conventions and uses React 19 hooks correctly. The test IDs are well-structured for the e2e test suite.
e2e/react-start/csp/src/routes/__root.tsx (2)
35-47: LGTM! Standard root component structure.The RootComponent correctly renders the HTML document structure with HeadContent, Outlet, and Scripts components from TanStack Router.
8-33: CSP header implementation is correct.The
headersfunction correctly accessesssr?.nonceand constructs a Content-Security-Policy header with nonce-basedscript-srcandstyle-srcdirectives. The defensivessr?.noncecheck and early return properly handle cases when the nonce is unavailable. Thessr.nonceproperty is properly wired through the router infrastructure:getSSROptions()generates a cryptographically random nonce on the server side, which is passed to the router via thessroption and made available to theheadersfunction through theAssetFnContextOptionstype.e2e/react-start/csp/tests/csp.spec.ts (6)
4-33: LGTM! Comprehensive CSP nonce validation tests.These tests effectively verify that:
- CSP headers are present with nonce directives
- All inline scripts and styles have nonce attributes
- External scripts and stylesheets have nonce attributes
The test structure is clean and assertions are clear.
35-85: Excellent nonce consistency validation.This test uses route interception to access raw HTML before browser processing, which is necessary since browsers strip nonce attributes for security. The regex patterns correctly handle attribute ordering variations (e.g.,
noncebefore or aftersrc/href).The comprehensive checks ensure nonce consistency across:
- CSP header
- Inline scripts
- Inline styles
- External scripts
- External stylesheets
87-111: Smart hydration test with race condition handling.The polling strategy (lines 93-101) elegantly handles the race between test execution and React hydration. This is much more robust than arbitrary timeouts. The follow-up verification (lines 104-110) confirms continued functionality after hydration.
113-137: LGTM! Thorough CSP compliance verification.These tests verify that both inline and external styles/scripts execute correctly under CSP, using computed styles and global flag checks. This confirms the nonces are working as intended.
139-156: Good CSP violation monitoring.The test listens for both console messages and page errors containing "content security policy" to catch violations. The small wait period (line 154) allows async violations to surface. This provides strong assurance that the CSP implementation doesn't block legitimate resources.
158-170: LGTM! Important security validation.Testing that each request gets a unique nonce is crucial for CSP security. Reusing nonces across requests would defeat the purpose of the nonce mechanism. This test ensures proper nonce generation.
e2e/react-start/csp/src/routeTree.gen.ts (1)
1-68: Skipping review - autogenerated file.This is an autogenerated route tree file that should not be manually modified. Based on learnings, these files are not reviewed as they are generated by the TanStack Router tooling.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🤖 Fix all issues with AI agents
In @e2e/solid-start/csp/src/routes/__root.tsx:
- Around line 36-49: The RootComponent is rendering HydrationScript without the
CSP nonce; update the HydrationScript invocation inside RootComponent to pass
the nonce from the route handler (use ssr?.nonce) so it becomes HydrationScript
with a nonce prop (i.e., pass nonce={ssr?.nonce}) ensuring the hydration script
is allowed by the CSP.
In @e2e/solid-start/csp/vite.config.ts:
- Line 1: Upgrade the Vite dependency used by the e2e project to at least
^7.1.11 to remediate CVE-2025-62522: update the "vite" entry in the project's
package.json to ">=7.1.11" (e.g., "^7.1.11"), regenerate the lockfile
(npm/yarn/pnpm install) and rebuild/test the e2e suite; ensure any references to
Vite in build scripts or dev tooling accept the new version.
🧹 Nitpick comments (2)
e2e/solid-start/csp/package.json (1)
14-15: Consider usingworkspace:*for internal dependencies.As per coding guidelines, internal dependencies should use
workspace:*protocol instead ofworkspace:^.Suggested change
"dependencies": { - "@tanstack/solid-router": "workspace:^", - "@tanstack/solid-start": "workspace:^", + "@tanstack/solid-router": "workspace:*", + "@tanstack/solid-start": "workspace:*", "solid-js": "^1.9.10", "vite": "^7.1.7" }, "devDependencies": { "@playwright/test": "^1.50.1", - "@tanstack/router-e2e-utils": "workspace:^", + "@tanstack/router-e2e-utils": "workspace:*",Also applies to: 21-21
e2e/solid-start/csp/tests/csp.spec.ts (1)
153-155: Consider using a more reliable wait strategy.The fixed 100ms timeout may be flaky on slower CI environments. Consider using
page.waitForLoadState('networkidle')or increasing the timeout for more reliable results.♻️ Suggested improvement
// Small wait to ensure any async violations are caught - await page.waitForTimeout(100) + await page.waitForLoadState('networkidle') expect(violations).toEqual([])
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (13)
e2e/solid-start/csp/.gitignoree2e/solid-start/csp/package.jsone2e/solid-start/csp/playwright.config.tse2e/solid-start/csp/public/external.csse2e/solid-start/csp/public/external.jse2e/solid-start/csp/src/routeTree.gen.tse2e/solid-start/csp/src/router.tsxe2e/solid-start/csp/src/routes/__root.tsxe2e/solid-start/csp/src/routes/index.tsxe2e/solid-start/csp/tests/csp.spec.tse2e/solid-start/csp/tsconfig.jsone2e/solid-start/csp/vite.config.tspackages/solid-router/src/Asset.tsx
✅ Files skipped from review due to trivial changes (2)
- e2e/solid-start/csp/.gitignore
- e2e/solid-start/csp/public/external.js
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Use TypeScript strict mode with extensive type safety for all code
Files:
e2e/solid-start/csp/src/router.tsxe2e/solid-start/csp/src/routes/index.tsxe2e/solid-start/csp/tests/csp.spec.tse2e/solid-start/csp/src/routeTree.gen.tse2e/solid-start/csp/src/routes/__root.tsxpackages/solid-router/src/Asset.tsxe2e/solid-start/csp/playwright.config.tse2e/solid-start/csp/vite.config.ts
**/*.{js,ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Implement ESLint rules for router best practices using the ESLint plugin router
Files:
e2e/solid-start/csp/src/router.tsxe2e/solid-start/csp/src/routes/index.tsxe2e/solid-start/csp/tests/csp.spec.tse2e/solid-start/csp/src/routeTree.gen.tse2e/solid-start/csp/src/routes/__root.tsxpackages/solid-router/src/Asset.tsxe2e/solid-start/csp/playwright.config.tse2e/solid-start/csp/vite.config.ts
**/package.json
📄 CodeRabbit inference engine (AGENTS.md)
Use workspace protocol
workspace:*for internal dependencies in package.json files
Files:
e2e/solid-start/csp/package.json
🧠 Learnings (10)
📚 Learning: 2025-10-08T08:11:47.088Z
Learnt from: nlynzaad
Repo: TanStack/router PR: 5402
File: packages/router-generator/tests/generator/no-formatted-route-tree/routeTree.nonnested.snapshot.ts:19-21
Timestamp: 2025-10-08T08:11:47.088Z
Learning: Test snapshot files in the router-generator tests directory (e.g., files matching the pattern `packages/router-generator/tests/generator/**/routeTree*.snapshot.ts` or `routeTree*.snapshot.js`) should not be modified or have issues flagged, as they are fixtures used to verify the generator's output and are intentionally preserved as-is.
Applied to files:
e2e/solid-start/csp/src/router.tsxe2e/solid-start/csp/src/routes/index.tsxe2e/solid-start/csp/src/routeTree.gen.tse2e/solid-start/csp/src/routes/__root.tsx
📚 Learning: 2025-12-06T15:03:07.223Z
Learnt from: CR
Repo: TanStack/router PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-06T15:03:07.223Z
Learning: Applies to **/*.{js,ts,tsx} : Implement ESLint rules for router best practices using the ESLint plugin router
Applied to files:
e2e/solid-start/csp/src/router.tsxe2e/solid-start/csp/src/routes/index.tsxe2e/solid-start/csp/tsconfig.jsone2e/solid-start/csp/src/routeTree.gen.ts
📚 Learning: 2025-12-17T02:17:55.086Z
Learnt from: schiller-manuel
Repo: TanStack/router PR: 6120
File: packages/router-generator/src/generator.ts:654-657
Timestamp: 2025-12-17T02:17:55.086Z
Learning: In `packages/router-generator/src/generator.ts`, pathless_layout routes must receive a `path` property when they have a `cleanedPath`, even though they are non-path routes. This is necessary because child routes inherit the path from their parent, and without this property, child routes would not have the correct full path at runtime.
Applied to files:
e2e/solid-start/csp/src/router.tsxe2e/solid-start/csp/src/routes/index.tsxe2e/solid-start/csp/src/routeTree.gen.tse2e/solid-start/csp/src/routes/__root.tsx
📚 Learning: 2025-10-01T18:31:35.420Z
Learnt from: schiller-manuel
Repo: TanStack/router PR: 5330
File: e2e/react-start/custom-basepath/src/routeTree.gen.ts:58-61
Timestamp: 2025-10-01T18:31:35.420Z
Learning: Do not review files named `routeTree.gen.ts` in TanStack Router repositories, as these are autogenerated files that should not be manually modified.
Applied to files:
e2e/solid-start/csp/src/router.tsxe2e/solid-start/csp/src/routeTree.gen.ts
📚 Learning: 2025-11-02T16:16:24.898Z
Learnt from: nlynzaad
Repo: TanStack/router PR: 5732
File: packages/start-client-core/src/client/hydrateStart.ts:6-9
Timestamp: 2025-11-02T16:16:24.898Z
Learning: In packages/start-client-core/src/client/hydrateStart.ts, the `import/no-duplicates` ESLint disable is necessary for imports from `#tanstack-router-entry` and `#tanstack-start-entry` because both aliases resolve to the same placeholder file (`fake-start-entry.js`) in package.json during static analysis, even though they resolve to different files at runtime.
Applied to files:
e2e/solid-start/csp/src/router.tsxe2e/solid-start/csp/tsconfig.jsone2e/solid-start/csp/src/routeTree.gen.tse2e/solid-start/csp/src/routes/__root.tsxe2e/solid-start/csp/package.json
📚 Learning: 2025-12-21T12:52:35.231Z
Learnt from: Sheraff
Repo: TanStack/router PR: 6171
File: packages/router-core/src/new-process-route-tree.ts:898-898
Timestamp: 2025-12-21T12:52:35.231Z
Learning: In `packages/router-core/src/new-process-route-tree.ts`, the matching logic intentionally allows paths without trailing slashes to match index routes with trailing slashes (e.g., `/a` can match `/a/` route), but not vice-versa (e.g., `/a/` cannot match `/a` layout route). This is implemented via the condition `!pathIsIndex || node.kind === SEGMENT_TYPE_INDEX` and is a deliberate design decision to provide better UX by being permissive with missing trailing slashes.
Applied to files:
e2e/solid-start/csp/src/routes/index.tsxe2e/solid-start/csp/src/routeTree.gen.ts
📚 Learning: 2025-12-06T15:03:07.223Z
Learnt from: CR
Repo: TanStack/router PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-06T15:03:07.223Z
Learning: Use file-based routing in `src/routes/` directories or code-based routing with route definitions
Applied to files:
e2e/solid-start/csp/src/routes/index.tsxe2e/solid-start/csp/src/routeTree.gen.ts
📚 Learning: 2025-12-06T15:03:07.223Z
Learnt from: CR
Repo: TanStack/router PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-06T15:03:07.223Z
Learning: Applies to **/*.{ts,tsx} : Use TypeScript strict mode with extensive type safety for all code
Applied to files:
e2e/solid-start/csp/tsconfig.json
📚 Learning: 2025-12-25T13:04:55.492Z
Learnt from: nlynzaad
Repo: TanStack/router PR: 6215
File: e2e/react-start/custom-basepath/package.json:13-17
Timestamp: 2025-12-25T13:04:55.492Z
Learning: In the TanStack Router repository, e2e test scripts are specifically designed to run in CI (which uses a Unix environment), so Unix-specific commands (like `rm -rf`, `&` for backgrounding, and direct environment variable assignments without `cross-env`) are acceptable in e2e test npm scripts.
Applied to files:
e2e/solid-start/csp/package.jsone2e/solid-start/csp/playwright.config.ts
📚 Learning: 2025-10-09T12:59:14.842Z
Learnt from: hokkyss
Repo: TanStack/router PR: 5418
File: e2e/react-start/custom-identifier-prefix/public/site.webmanifest:2-3
Timestamp: 2025-10-09T12:59:14.842Z
Learning: In e2e test fixtures (files under e2e directories), empty or placeholder values in configuration files like site.webmanifest are acceptable and should not be flagged unless the test specifically validates those fields.
Applied to files:
e2e/solid-start/csp/playwright.config.ts
🧬 Code graph analysis (3)
e2e/solid-start/csp/src/routes/index.tsx (2)
e2e/solid-start/csp/src/routes/__root.tsx (1)
Route(9-34)packages/router-core/src/ssr/tsrScript.ts (1)
p(16-18)
e2e/solid-start/csp/src/routeTree.gen.ts (1)
e2e/solid-start/csp/src/router.tsx (1)
getRouter(14-20)
e2e/solid-start/csp/src/routes/__root.tsx (1)
e2e/solid-start/csp/src/routes/index.tsx (1)
Route(4-6)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: Test
- GitHub Check: Preview
🔇 Additional comments (15)
e2e/solid-start/csp/tsconfig.json (1)
1-23: LGTM! Well-configured TypeScript setup for Solid Start CSP e2e tests.The configuration is comprehensive and follows best practices:
- Strict mode enabled for type safety
- Correct Solid.js JSX settings with
preserveandjsxImportSource- Modern ES2022 target with appropriate DOM libraries for browser testing
- Proper module resolution for bundlers
- Standard path aliasing setup
e2e/solid-start/csp/vite.config.ts (1)
5-10: LGTM! Configuration is appropriate for CSP e2e testing.The Vite configuration correctly sets up Solid Start with SSR enabled, which is essential for CSP nonce injection during server-side rendering. The plugin order (tanstackStart before viteSolid) is appropriate, and the port configuration aligns with the existing React Start CSP test pattern.
packages/solid-router/src/Asset.tsx (1)
19-20: LGTM! UsingStylecomponent for CSP compliance.This change correctly replaces direct innerHTML injection with the
@solidjs/metaStylecomponent, which properly handles nonce propagation for CSP compliance. The attrs (including any nonce attribute) are now correctly forwarded to the component.e2e/solid-start/csp/src/routes/index.tsx (1)
1-25: LGTM! Clean test fixture for CSP validation.The route correctly implements a simple counter component with proper test IDs for e2e testing. The inline-styled and external-styled classes align with the styles defined in
__root.tsxandexternal.cssrespectively.e2e/solid-start/csp/src/routes/__root.tsx (1)
9-34: Well-structured CSP configuration for the test.The CSP header construction correctly uses the SSR-provided nonce for both
script-srcandstyle-srcdirectives. The early return when nonce is undefined is good defensive coding.e2e/solid-start/csp/playwright.config.ts (1)
1-35: LGTM! Standard Playwright configuration.The configuration follows established patterns in the repository, with appropriate use of
getTestServerPortfor dynamic port allocation and correct webServer setup for build and serve.e2e/solid-start/csp/public/external.css (1)
1-4: LGTM!Simple test fixture CSS that complements the inline styles (green) with distinct external styling (blue) for clear CSP validation assertions.
e2e/solid-start/csp/src/router.tsx (2)
5-12: Secure nonce generation implementation.Good use of
crypto.getRandomValuesfor cryptographically secure nonce generation. The 128-bit (16 bytes → 32 hex chars) nonce provides sufficient entropy for CSP security. UsingcreateIsomorphicFn().server()correctly ensures this only executes server-side.
14-20: LGTM! Router factory correctly configured.The
getRouter()function appropriately creates a new router instance per invocation, ensuring each SSR request receives a fresh nonce. The SSR options are correctly wired from the isomorphic function.e2e/solid-start/csp/tests/csp.spec.ts (5)
4-21: LGTM!These initial tests correctly validate CSP header presence and nonce attribute propagation to inline scripts and styles. The locator patterns and assertions are appropriate.
23-33: LGTM!Good coverage for external resources. The
toHaveAttribute('nonce')assertion correctly validates nonce presence without requiring a specific value.
87-111: LGTM!Excellent use of
expect.pollto handle the hydration race condition. This pattern correctly waits for Solid to hydrate before asserting on interactive behavior, making the test resilient to timing variations.
113-137: LGTM!Good validation that CSP doesn't block legitimate resources. Using computed styles and window globals effectively verifies that styles are applied and scripts execute correctly.
158-170: LGTM!Important security test verifying nonce uniqueness per request. Reusing nonces would significantly weaken CSP protection. The same regex format consideration from line 50 applies here.
e2e/solid-start/csp/src/routeTree.gen.ts (1)
1-68: Skipping review of auto-generated file.This file is auto-generated by TanStack Router and should not be manually modified. Based on learnings,
routeTree.gen.tsfiles are excluded from review.
| function RootComponent() { | ||
| return ( | ||
| <html> | ||
| <head> | ||
| <HydrationScript /> | ||
| <HeadContent /> | ||
| </head> | ||
| <body> | ||
| <Outlet /> | ||
| <Scripts /> | ||
| </body> | ||
| </html> | ||
| ) | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
cat -n e2e/solid-start/csp/src/routes/__root.tsx | sed -n '30,55p'Repository: TanStack/router
Length of output: 530
🌐 Web query:
solid-js HydrationScript nonce attribute CSP support
💡 Result:
Yes — Solid's HydrationScript supports a nonce. The API (generateHydrationScript and ) accepts a nonce prop/option so the injected inline hydration script can include nonce="...". [1]
Recommended pattern for CSP with nonces in SolidStart:
- Generate a cryptographically-random nonce per request (middleware).
- Add it to the response CSP header (script-src 'nonce-' …).
- Store the nonce in event.locals and return it from your server entry (entry-server) so your HTML rendering can pass it to HydrationScript (and other inline scripts/styles). SolidStart docs show this middleware + entry-server approach. [2][3]
References
- HydrationScript API (nonce option). [1]
- SolidStart security guide: middleware + nonce flow. [2]
- Example/config notes showing adding nonces to injected scripts/styles. [3]
🏁 Script executed:
rg -n "nonce" e2e/solid-start/csp/src --type ts --type tsxRepository: TanStack/router
Length of output: 86
🏁 Script executed:
grep -r "entry-server" e2e/solid-start/csp/src/ 2>/dev/null | head -20Repository: TanStack/router
Length of output: 41
🏁 Script executed:
rg -i "nonce" e2e/solid-start/csp/Repository: TanStack/router
Length of output: 4626
🏁 Script executed:
find e2e/solid-start/csp -type f -name "*.ts" -o -name "*.tsx" -o -name "*.js" -o -name "*.json" | head -30Repository: TanStack/router
Length of output: 437
🏁 Script executed:
cat -n e2e/solid-start/csp/src/routes/__root.tsxRepository: TanStack/router
Length of output: 1482
Pass the nonce prop to HydrationScript.
The nonce is available via ssr?.nonce in the route handler but is not being passed to the HydrationScript component. Update line 40 to:
<HydrationScript nonce={ssr?.nonce} />Without this, the hydration script will be blocked by the CSP policy, breaking the application.
🤖 Prompt for AI Agents
In @e2e/solid-start/csp/src/routes/__root.tsx around lines 36 - 49, The
RootComponent is rendering HydrationScript without the CSP nonce; update the
HydrationScript invocation inside RootComponent to pass the nonce from the route
handler (use ssr?.nonce) so it becomes HydrationScript with a nonce prop (i.e.,
pass nonce={ssr?.nonce}) ensuring the hydration script is allowed by the CSP.
| @@ -0,0 +1,10 @@ | |||
| import { defineConfig } from 'vite' | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Check if Vite 7.1.7 exists on npm registry
echo "=== Checking Vite 7.1.7 on npm registry ==="
curl -s https://registry.npmjs.org/vite | jq -r '.versions | keys[] | select(. == "7.1.7")'
echo -e "\n=== Checking all Vite 7.x versions ==="
curl -s https://registry.npmjs.org/vite | jq -r '.versions | keys[] | select(startswith("7."))' | sort -V | tail -20
echo -e "\n=== Checking project vite dependency ==="
find . -name "package.json" -type f | head -5 | xargs -I {} sh -c 'echo "File: {}" && cat {} | grep -A 2 -B 2 '"'"'vite'"'"' || true'Repository: TanStack/router
Length of output: 2638
🌐 Web query:
Vite 7.1.7 security vulnerabilities CVE 2024 2025
💡 Result:
Short answer: Vite 7.1.7 is vulnerable to a 2025 path-traversal/fs bypass (CVE-2025-62522) and should be upgraded; earlier 2025 CVEs fixed in 7.1.5 (CVE-2025-58751, CVE-2025-58752) do not affect 7.1.7.
Details and sources:
- CVE-2025-62522 (path traversal allowing server.fs.deny bypass on Windows): affects vite >=2.9.18 through 7.1.10; fixed in 7.1.11 — 7.1.7 is vulnerable. [1][2]
- CVE-2025-58751 and CVE-2025-58752 (public-dir / fs-serving issues): fixed in 7.1.5 — versions ≥7.1.5 (including 7.1.7) include those fixes. [3][4]
Recommendation: upgrade to the latest patched Vite (at least 7.1.11 or whatever the current patched release is) and follow the vendor advisory. [1][2]
Sources:
[1] NVD / CVE-2025-62522 / vendor advisory details.
[2] Wiz / Cybersecurity writeups summarizing CVE-2025-62522.
[3] NVD / CVE-2025-58751 (public-dir symlink bypass) — fixed in 7.1.5.
[4] NVD / CVE-2025-58752 (fs serving regardless of server.fs) — fixed in 7.1.5.
Would you like direct links to the advisories and the minimal upgrade/mitigation steps?
Upgrade Vite to 7.1.11 or later to patch critical path traversal vulnerability.
Vite 7.1.7 is affected by CVE-2025-62522, a critical path traversal/filesystem bypass vulnerability that allows bypassing server.fs.deny restrictions on Windows. The vulnerability is fixed in Vite 7.1.11 and later. Update the vite dependency in the e2e project package.json files to at least ^7.1.11.
🤖 Prompt for AI Agents
In @e2e/solid-start/csp/vite.config.ts at line 1, Upgrade the Vite dependency
used by the e2e project to at least ^7.1.11 to remediate CVE-2025-62522: update
the "vite" entry in the project's package.json to ">=7.1.11" (e.g., "^7.1.11"),
regenerate the lockfile (npm/yarn/pnpm install) and rebuild/test the e2e suite;
ensure any references to Vite in build scripts or dev tooling accept the new
version.
added csp e2e test for react
Summary by CodeRabbit
New Features
Tests
Refactor
✏️ Tip: You can customize this high-level summary in your review settings.