From 6ea1a5a85a4422c91a52a3fa6fa47895b5f00398 Mon Sep 17 00:00:00 2001 From: "Amir H. Hashemi" <87268103+amirhhashemi@users.noreply.github.com> Date: Sun, 8 Jun 2025 11:07:21 +0330 Subject: [PATCH 1/2] Add strict CSP example --- examples/pnpm-lock.yaml | 184 +++++++++++++++--- examples/with-strict-csp/.gitignore | 28 +++ examples/with-strict-csp/README.md | 37 ++++ examples/with-strict-csp/app.config.ts | 5 + examples/with-strict-csp/package.json | 17 ++ examples/with-strict-csp/public/favicon.ico | Bin 0 -> 664 bytes examples/with-strict-csp/src/app.css | 61 ++++++ examples/with-strict-csp/src/app.tsx | 22 +++ examples/with-strict-csp/src/entry-client.tsx | 4 + examples/with-strict-csp/src/entry-server.tsx | 24 +++ examples/with-strict-csp/src/global.d.ts | 1 + examples/with-strict-csp/src/middleware.ts | 31 +++ examples/with-strict-csp/tsconfig.json | 19 ++ 13 files changed, 404 insertions(+), 29 deletions(-) create mode 100644 examples/with-strict-csp/.gitignore create mode 100644 examples/with-strict-csp/README.md create mode 100644 examples/with-strict-csp/app.config.ts create mode 100644 examples/with-strict-csp/package.json create mode 100644 examples/with-strict-csp/public/favicon.ico create mode 100644 examples/with-strict-csp/src/app.css create mode 100644 examples/with-strict-csp/src/app.tsx create mode 100644 examples/with-strict-csp/src/entry-client.tsx create mode 100644 examples/with-strict-csp/src/entry-server.tsx create mode 100644 examples/with-strict-csp/src/global.d.ts create mode 100644 examples/with-strict-csp/src/middleware.ts create mode 100644 examples/with-strict-csp/tsconfig.json diff --git a/examples/pnpm-lock.yaml b/examples/pnpm-lock.yaml index 6e7ab6f95..72a2636b4 100644 --- a/examples/pnpm-lock.yaml +++ b/examples/pnpm-lock.yaml @@ -1,7 +1,7 @@ lockfileVersion: '9.0' settings: - autoInstallPeers: false + autoInstallPeers: true excludeLinksFromLockfile: false importers: @@ -301,7 +301,7 @@ importers: version: 1.2.5 '@kobalte/solidbase': specifier: ^0.2.11 - version: 0.2.11(da30c3334fcbe708cd84cf330fc03c7b) + version: 0.2.11(8f13c4017e62110aa4122b33b52ec975) '@solidjs/meta': specifier: ^0.29.4 version: 0.29.4(solid-js@1.9.7) @@ -318,6 +318,18 @@ importers: specifier: ^0.5.6 version: 0.5.6(@types/node@20.17.50)(better-sqlite3@11.10.0)(db0@0.3.2(better-sqlite3@11.10.0)(drizzle-orm@0.31.4(@prisma/client@5.22.0(prisma@5.22.0))(@types/better-sqlite3@7.6.13)(better-sqlite3@11.10.0)(prisma@5.22.0)))(drizzle-orm@0.31.4(@prisma/client@5.22.0(prisma@5.22.0))(@types/better-sqlite3@7.6.13)(better-sqlite3@11.10.0)(prisma@5.22.0))(ioredis@5.6.1)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.8.0) + with-strict-csp: + dependencies: + '@solidjs/start': + specifier: ^1.1.0 + version: 1.1.4(@testing-library/jest-dom@6.6.3)(@types/node@20.17.50)(jiti@2.4.2)(lightningcss@1.30.1)(solid-js@1.9.7)(terser@5.39.2)(tsx@4.19.4)(vinxi@0.5.6(@types/node@20.17.50)(better-sqlite3@11.10.0)(db0@0.3.2(better-sqlite3@11.10.0)(drizzle-orm@0.31.4(@prisma/client@5.22.0(prisma@5.22.0))(@types/better-sqlite3@7.6.13)(better-sqlite3@11.10.0)(prisma@5.22.0)))(drizzle-orm@0.31.4(@prisma/client@5.22.0(prisma@5.22.0))(@types/better-sqlite3@7.6.13)(better-sqlite3@11.10.0)(prisma@5.22.0))(ioredis@5.6.1)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.8.0))(vite@6.3.5(@types/node@20.17.50)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.8.0))(yaml@2.8.0) + solid-js: + specifier: ^1.9.5 + version: 1.9.7 + vinxi: + specifier: ^0.5.3 + version: 0.5.6(@types/node@20.17.50)(better-sqlite3@11.10.0)(db0@0.3.2(better-sqlite3@11.10.0)(drizzle-orm@0.31.4(@prisma/client@5.22.0(prisma@5.22.0))(@types/better-sqlite3@7.6.13)(better-sqlite3@11.10.0)(prisma@5.22.0)))(drizzle-orm@0.31.4(@prisma/client@5.22.0(prisma@5.22.0))(@types/better-sqlite3@7.6.13)(better-sqlite3@11.10.0)(prisma@5.22.0))(ioredis@5.6.1)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.8.0) + with-tailwindcss: dependencies: '@solidjs/router': @@ -407,7 +419,7 @@ importers: version: 1.9.7 unocss: specifier: ^0.65.1 - version: 0.65.4(rollup@4.41.1)(vite@6.3.5(@types/node@20.17.50)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.8.0)) + version: 0.65.4(postcss@8.5.3)(rollup@4.41.1)(vite@6.3.5(@types/node@20.17.50)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.8.0))(vue@3.5.16(typescript@5.8.3)) vinxi: specifier: ^0.5.3 version: 0.5.6(@types/node@20.17.50)(better-sqlite3@11.10.0)(db0@0.3.2(better-sqlite3@11.10.0)(drizzle-orm@0.31.4(@prisma/client@5.22.0(prisma@5.22.0))(@types/better-sqlite3@7.6.13)(better-sqlite3@11.10.0)(prisma@5.22.0)))(drizzle-orm@0.31.4(@prisma/client@5.22.0(prisma@5.22.0))(@types/better-sqlite3@7.6.13)(better-sqlite3@11.10.0)(prisma@5.22.0))(ioredis@5.6.1)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.8.0) @@ -2579,6 +2591,8 @@ packages: '@unocss/postcss@0.65.4': resolution: {integrity: sha512-8peDRo0+rNQsnKh/H2uZEVy67sV2cC16rAeSLpgbVJUMNfZlmF0rC2DNGsOV17uconUXSwz7+mGcHKNiv+8YlQ==} engines: {node: '>=14'} + peerDependencies: + postcss: ^8.4.21 '@unocss/preset-attributify@0.65.4': resolution: {integrity: sha512-zxE9hJJ5b37phjdzDdZsxX559ZlmH9rFlY5LVEcQySTnsfY0znviHxPbD2iRpCBCRd+YC5HfFd2jb3XlnTKMJQ==} @@ -2692,18 +2706,47 @@ packages: '@vue/compiler-core@3.5.14': resolution: {integrity: sha512-k7qMHMbKvoCXIxPhquKQVw3Twid3Kg4s7+oYURxLGRd56LiuHJVrvFKI4fm2AM3c8apqODPfVJGoh8nePbXMRA==} + '@vue/compiler-core@3.5.16': + resolution: {integrity: sha512-AOQS2eaQOaaZQoL1u+2rCJIKDruNXVBZSiUD3chnUrsoX5ZTQMaCvXlWNIfxBJuU15r1o7+mpo5223KVtIhAgQ==} + '@vue/compiler-dom@3.5.14': resolution: {integrity: sha512-1aOCSqxGOea5I80U2hQJvXYpPm/aXo95xL/m/mMhgyPUsKe9jhjwWpziNAw7tYRnbz1I61rd9Mld4W9KmmRoug==} + '@vue/compiler-dom@3.5.16': + resolution: {integrity: sha512-SSJIhBr/teipXiXjmWOVWLnxjNGo65Oj/8wTEQz0nqwQeP75jWZ0n4sF24Zxoht1cuJoWopwj0J0exYwCJ0dCQ==} + '@vue/compiler-sfc@3.5.14': resolution: {integrity: sha512-9T6m/9mMr81Lj58JpzsiSIjBgv2LiVoWjIVa7kuXHICUi8LiDSIotMpPRXYJsXKqyARrzjT24NAwttrMnMaCXA==} + '@vue/compiler-sfc@3.5.16': + resolution: {integrity: sha512-rQR6VSFNpiinDy/DVUE0vHoIDUF++6p910cgcZoaAUm3POxgNOOdS/xgoll3rNdKYTYPnnbARDCZOyZ+QSe6Pw==} + '@vue/compiler-ssr@3.5.14': resolution: {integrity: sha512-Y0G7PcBxr1yllnHuS/NxNCSPWnRGH4Ogrp0tsLA5QemDZuJLs99YjAKQ7KqkHE0vCg4QTKlQzXLKCMF7WPSl7Q==} + '@vue/compiler-ssr@3.5.16': + resolution: {integrity: sha512-d2V7kfxbdsjrDSGlJE7my1ZzCXViEcqN6w14DOsDrUCHEA6vbnVCpRFfrc4ryCP/lCKzX2eS1YtnLE/BuC9f/A==} + + '@vue/reactivity@3.5.16': + resolution: {integrity: sha512-FG5Q5ee/kxhIm1p2bykPpPwqiUBV3kFySsHEQha5BJvjXdZTUfmya7wP7zC39dFuZAcf/PD5S4Lni55vGLMhvA==} + + '@vue/runtime-core@3.5.16': + resolution: {integrity: sha512-bw5Ykq6+JFHYxrQa7Tjr+VSzw7Dj4ldR/udyBZbq73fCdJmyy5MPIFR9IX/M5Qs+TtTjuyUTCnmK3lWWwpAcFQ==} + + '@vue/runtime-dom@3.5.16': + resolution: {integrity: sha512-T1qqYJsG2xMGhImRUV9y/RseB9d0eCYZQ4CWca9ztCuiPj/XWNNN+lkNBuzVbia5z4/cgxdL28NoQCvC0Xcfww==} + + '@vue/server-renderer@3.5.16': + resolution: {integrity: sha512-BrX0qLiv/WugguGsnQUJiYOE0Fe5mZTwi6b7X/ybGB0vfrPH9z0gD/Y6WOR1sGCgX4gc25L1RYS5eYQKDMoNIg==} + peerDependencies: + vue: 3.5.16 + '@vue/shared@3.5.14': resolution: {integrity: sha512-oXTwNxVfc9EtP1zzXAlSlgARLXNC84frFYkS0HHz0h3E4WZSP9sywqjqzGCP9Y34M8ipNmd380pVgmMuwELDyQ==} + '@vue/shared@3.5.16': + resolution: {integrity: sha512-c/0fWy3Jw6Z8L9FmTyYfkpM5zklnqqa9+a6dz3DvONRKW2NEbh46BP0FHuLFSWi2TnQEtp91Z6zOWNrU6QiyPg==} + '@whatwg-node/disposablestack@0.0.6': resolution: {integrity: sha512-LOtTn+JgJvX8WfBVJtF08TGrdjuFzGJc4mkP8EdDI8ADbvO7kiexYep1o8dwnt0okb0jYclCDXF13xU7Ge4zSw==} engines: {node: '>=18.0.0'} @@ -5702,6 +5745,9 @@ packages: scule@1.3.0: resolution: {integrity: sha512-6FtHJEvt+pVMIB9IBY+IcCJ6Z5f1iQnytgyfKMhDKgmzYG+TeH/wx1y3l27rshSbLiSanrR9ffZDrEsmjlQF2g==} + search-insights@2.17.3: + resolution: {integrity: sha512-RQPdCYTa8A68uM2jwxoY842xDhvx3E5LFL1LxvxCNMev4o5mLuokczhzjAgGwUZBAmOKZknArSxLKmXtIi2AxQ==} + section-matter@1.0.0: resolution: {integrity: sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==} engines: {node: '>=4'} @@ -6672,6 +6718,14 @@ packages: peerDependencies: vue: ^3.4.37 + vue@3.5.16: + resolution: {integrity: sha512-rjOV2ecxMd5SiAmof2xzh2WxntRcigkX/He4YFJ6WdRvVUrbt6DxC1Iujh10XLl8xCDRDtGKMeO3D+pRQ1PP9w==} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + w3c-xmlserializer@5.0.0: resolution: {integrity: sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==} engines: {node: '>=18'} @@ -6834,18 +6888,19 @@ snapshots: '@adobe/css-tools@4.4.3': {} - '@algolia/autocomplete-core@1.17.9(@algolia/client-search@5.25.0)(algoliasearch@5.25.0)': + '@algolia/autocomplete-core@1.17.9(@algolia/client-search@5.25.0)(algoliasearch@5.25.0)(search-insights@2.17.3)': dependencies: - '@algolia/autocomplete-plugin-algolia-insights': 1.17.9(@algolia/client-search@5.25.0)(algoliasearch@5.25.0) + '@algolia/autocomplete-plugin-algolia-insights': 1.17.9(@algolia/client-search@5.25.0)(algoliasearch@5.25.0)(search-insights@2.17.3) '@algolia/autocomplete-shared': 1.17.9(@algolia/client-search@5.25.0)(algoliasearch@5.25.0) transitivePeerDependencies: - '@algolia/client-search' - algoliasearch - search-insights - '@algolia/autocomplete-plugin-algolia-insights@1.17.9(@algolia/client-search@5.25.0)(algoliasearch@5.25.0)': + '@algolia/autocomplete-plugin-algolia-insights@1.17.9(@algolia/client-search@5.25.0)(algoliasearch@5.25.0)(search-insights@2.17.3)': dependencies: '@algolia/autocomplete-shared': 1.17.9(@algolia/client-search@5.25.0)(algoliasearch@5.25.0) + search-insights: 2.17.3 transitivePeerDependencies: - '@algolia/client-search' - algoliasearch @@ -7174,9 +7229,9 @@ snapshots: '@docsearch/css@3.9.0': {} - '@docsearch/js@3.9.0(@algolia/client-search@5.25.0)': + '@docsearch/js@3.9.0(@algolia/client-search@5.25.0)(search-insights@2.17.3)': dependencies: - '@docsearch/react': 3.9.0(@algolia/client-search@5.25.0) + '@docsearch/react': 3.9.0(@algolia/client-search@5.25.0)(search-insights@2.17.3) preact: 10.26.7 transitivePeerDependencies: - '@algolia/client-search' @@ -7185,12 +7240,14 @@ snapshots: - react-dom - search-insights - '@docsearch/react@3.9.0(@algolia/client-search@5.25.0)': + '@docsearch/react@3.9.0(@algolia/client-search@5.25.0)(search-insights@2.17.3)': dependencies: - '@algolia/autocomplete-core': 1.17.9(@algolia/client-search@5.25.0)(algoliasearch@5.25.0) + '@algolia/autocomplete-core': 1.17.9(@algolia/client-search@5.25.0)(algoliasearch@5.25.0)(search-insights@2.17.3) '@algolia/autocomplete-preset-algolia': 1.17.9(@algolia/client-search@5.25.0)(algoliasearch@5.25.0) '@docsearch/css': 3.9.0 algoliasearch: 5.25.0 + optionalDependencies: + search-insights: 2.17.3 transitivePeerDependencies: - '@algolia/client-search' @@ -7718,12 +7775,12 @@ snapshots: solid-presence: 0.1.8(solid-js@1.9.7) solid-prevent-scroll: 0.1.10(solid-js@1.9.7) - '@kobalte/solidbase@0.2.11(da30c3334fcbe708cd84cf330fc03c7b)': + '@kobalte/solidbase@0.2.11(8f13c4017e62110aa4122b33b52ec975)': dependencies: '@alloc/quick-lru': 5.2.0 '@bprogress/core': 1.3.4 '@docsearch/css': 3.9.0 - '@docsearch/js': 3.9.0(@algolia/client-search@5.25.0) + '@docsearch/js': 3.9.0(@algolia/client-search@5.25.0)(search-insights@2.17.3) '@expressive-code/core': 0.40.2 '@expressive-code/plugin-collapsible-sections': 0.40.2 '@expressive-code/plugin-frames': 0.40.2 @@ -7769,7 +7826,7 @@ snapshots: unist-builder: 4.0.0 unist-util-visit: 5.0.0 unplugin-auto-import: 19.2.0 - unplugin-icons: 22.1.0(@vue/compiler-sfc@3.5.14) + unplugin-icons: 22.1.0(@vue/compiler-sfc@3.5.16) vinxi: 0.5.6(@types/node@20.17.50)(better-sqlite3@11.10.0)(db0@0.3.2(better-sqlite3@11.10.0)(drizzle-orm@0.31.4(@prisma/client@5.22.0(prisma@5.22.0))(@types/better-sqlite3@7.6.13)(better-sqlite3@11.10.0)(prisma@5.22.0)))(drizzle-orm@0.31.4(@prisma/client@5.22.0(prisma@5.22.0))(@types/better-sqlite3@7.6.13)(better-sqlite3@11.10.0)(prisma@5.22.0))(ioredis@5.6.1)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.8.0) vite: 6.3.5(@types/node@20.17.50)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.8.0) transitivePeerDependencies: @@ -8947,11 +9004,11 @@ snapshots: '@ungap/structured-clone@1.3.0': {} - '@unocss/astro@0.65.4(rollup@4.41.1)(vite@6.3.5(@types/node@20.17.50)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.8.0))': + '@unocss/astro@0.65.4(rollup@4.41.1)(vite@6.3.5(@types/node@20.17.50)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.8.0))(vue@3.5.16(typescript@5.8.3))': dependencies: '@unocss/core': 0.65.4 '@unocss/reset': 0.65.4 - '@unocss/vite': 0.65.4(rollup@4.41.1)(vite@6.3.5(@types/node@20.17.50)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.8.0)) + '@unocss/vite': 0.65.4(rollup@4.41.1)(vite@6.3.5(@types/node@20.17.50)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.8.0))(vue@3.5.16(typescript@5.8.3)) optionalDependencies: vite: 6.3.5(@types/node@20.17.50)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.8.0) transitivePeerDependencies: @@ -8991,18 +9048,18 @@ snapshots: dependencies: '@unocss/core': 0.65.4 - '@unocss/inspector@0.65.4': + '@unocss/inspector@0.65.4(vue@3.5.16(typescript@5.8.3))': dependencies: '@unocss/core': 0.65.4 '@unocss/rule-utils': 0.65.4 colorette: 2.0.20 gzip-size: 6.0.0 sirv: 3.0.1 - vue-flow-layout: 0.1.1 + vue-flow-layout: 0.1.1(vue@3.5.16(typescript@5.8.3)) transitivePeerDependencies: - vue - '@unocss/postcss@0.65.4': + '@unocss/postcss@0.65.4(postcss@8.5.3)': dependencies: '@unocss/config': 0.65.4 '@unocss/core': 0.65.4 @@ -9083,13 +9140,13 @@ snapshots: dependencies: '@unocss/core': 0.65.4 - '@unocss/vite@0.65.4(rollup@4.41.1)(vite@6.3.5(@types/node@20.17.50)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.8.0))': + '@unocss/vite@0.65.4(rollup@4.41.1)(vite@6.3.5(@types/node@20.17.50)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.8.0))(vue@3.5.16(typescript@5.8.3))': dependencies: '@ampproject/remapping': 2.3.0 '@rollup/pluginutils': 5.1.4(rollup@4.41.1) '@unocss/config': 0.65.4 '@unocss/core': 0.65.4 - '@unocss/inspector': 0.65.4 + '@unocss/inspector': 0.65.4(vue@3.5.16(typescript@5.8.3)) chokidar: 3.6.0 magic-string: 0.30.17 tinyglobby: 0.2.13 @@ -9127,7 +9184,7 @@ snapshots: consola: 3.4.2 defu: 6.1.4 get-port-please: 3.1.2 - h3: 1.15.2 + h3: 1.15.3 http-shutdown: 1.2.2 jiti: 1.21.7 mlly: 1.7.4 @@ -9234,11 +9291,24 @@ snapshots: estree-walker: 2.0.2 source-map-js: 1.2.1 + '@vue/compiler-core@3.5.16': + dependencies: + '@babel/parser': 7.27.2 + '@vue/shared': 3.5.16 + entities: 4.5.0 + estree-walker: 2.0.2 + source-map-js: 1.2.1 + '@vue/compiler-dom@3.5.14': dependencies: '@vue/compiler-core': 3.5.14 '@vue/shared': 3.5.14 + '@vue/compiler-dom@3.5.16': + dependencies: + '@vue/compiler-core': 3.5.16 + '@vue/shared': 3.5.16 + '@vue/compiler-sfc@3.5.14': dependencies: '@babel/parser': 7.27.2 @@ -9251,13 +9321,54 @@ snapshots: postcss: 8.5.3 source-map-js: 1.2.1 + '@vue/compiler-sfc@3.5.16': + dependencies: + '@babel/parser': 7.27.2 + '@vue/compiler-core': 3.5.16 + '@vue/compiler-dom': 3.5.16 + '@vue/compiler-ssr': 3.5.16 + '@vue/shared': 3.5.16 + estree-walker: 2.0.2 + magic-string: 0.30.17 + postcss: 8.5.3 + source-map-js: 1.2.1 + '@vue/compiler-ssr@3.5.14': dependencies: '@vue/compiler-dom': 3.5.14 '@vue/shared': 3.5.14 + '@vue/compiler-ssr@3.5.16': + dependencies: + '@vue/compiler-dom': 3.5.16 + '@vue/shared': 3.5.16 + + '@vue/reactivity@3.5.16': + dependencies: + '@vue/shared': 3.5.16 + + '@vue/runtime-core@3.5.16': + dependencies: + '@vue/reactivity': 3.5.16 + '@vue/shared': 3.5.16 + + '@vue/runtime-dom@3.5.16': + dependencies: + '@vue/reactivity': 3.5.16 + '@vue/runtime-core': 3.5.16 + '@vue/shared': 3.5.16 + csstype: 3.1.3 + + '@vue/server-renderer@3.5.16(vue@3.5.16(typescript@5.8.3))': + dependencies: + '@vue/compiler-ssr': 3.5.16 + '@vue/shared': 3.5.16 + vue: 3.5.16(typescript@5.8.3) + '@vue/shared@3.5.14': {} + '@vue/shared@3.5.16': {} + '@whatwg-node/disposablestack@0.0.6': dependencies: '@whatwg-node/promise-helpers': 1.3.2 @@ -13035,6 +13146,8 @@ snapshots: scule@1.3.0: {} + search-insights@2.17.3: {} + section-matter@1.0.0: dependencies: extend-shallow: 2.0.1 @@ -13763,12 +13876,12 @@ snapshots: dependencies: normalize-path: 2.1.1 - unocss@0.65.4(rollup@4.41.1)(vite@6.3.5(@types/node@20.17.50)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.8.0)): + unocss@0.65.4(postcss@8.5.3)(rollup@4.41.1)(vite@6.3.5(@types/node@20.17.50)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.8.0))(vue@3.5.16(typescript@5.8.3)): dependencies: - '@unocss/astro': 0.65.4(rollup@4.41.1)(vite@6.3.5(@types/node@20.17.50)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.8.0)) + '@unocss/astro': 0.65.4(rollup@4.41.1)(vite@6.3.5(@types/node@20.17.50)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.8.0))(vue@3.5.16(typescript@5.8.3)) '@unocss/cli': 0.65.4(rollup@4.41.1) '@unocss/core': 0.65.4 - '@unocss/postcss': 0.65.4 + '@unocss/postcss': 0.65.4(postcss@8.5.3) '@unocss/preset-attributify': 0.65.4 '@unocss/preset-icons': 0.65.4 '@unocss/preset-mini': 0.65.4 @@ -13781,10 +13894,11 @@ snapshots: '@unocss/transformer-compile-class': 0.65.4 '@unocss/transformer-directives': 0.65.4 '@unocss/transformer-variant-group': 0.65.4 - '@unocss/vite': 0.65.4(rollup@4.41.1)(vite@6.3.5(@types/node@20.17.50)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.8.0)) + '@unocss/vite': 0.65.4(rollup@4.41.1)(vite@6.3.5(@types/node@20.17.50)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.8.0))(vue@3.5.16(typescript@5.8.3)) optionalDependencies: vite: 6.3.5(@types/node@20.17.50)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.8.0) transitivePeerDependencies: + - postcss - rollup - supports-color - vue @@ -13798,7 +13912,7 @@ snapshots: unplugin: 2.3.4 unplugin-utils: 0.2.4 - unplugin-icons@22.1.0(@vue/compiler-sfc@3.5.14): + unplugin-icons@22.1.0(@vue/compiler-sfc@3.5.16): dependencies: '@antfu/install-pkg': 1.1.0 '@iconify/utils': 2.3.0 @@ -13806,7 +13920,7 @@ snapshots: local-pkg: 1.1.1 unplugin: 2.3.4 optionalDependencies: - '@vue/compiler-sfc': 3.5.14 + '@vue/compiler-sfc': 3.5.16 transitivePeerDependencies: - supports-color @@ -13856,7 +13970,7 @@ snapshots: anymatch: 3.1.3 chokidar: 4.0.3 destr: 2.0.5 - h3: 1.15.2 + h3: 1.15.3 lru-cache: 10.4.3 node-fetch-native: 1.6.6 ofetch: 1.4.1 @@ -14153,7 +14267,19 @@ snapshots: - tsx - yaml - vue-flow-layout@0.1.1: {} + vue-flow-layout@0.1.1(vue@3.5.16(typescript@5.8.3)): + dependencies: + vue: 3.5.16(typescript@5.8.3) + + vue@3.5.16(typescript@5.8.3): + dependencies: + '@vue/compiler-dom': 3.5.16 + '@vue/compiler-sfc': 3.5.16 + '@vue/runtime-dom': 3.5.16 + '@vue/server-renderer': 3.5.16(vue@3.5.16(typescript@5.8.3)) + '@vue/shared': 3.5.16 + optionalDependencies: + typescript: 5.8.3 w3c-xmlserializer@5.0.0: dependencies: diff --git a/examples/with-strict-csp/.gitignore b/examples/with-strict-csp/.gitignore new file mode 100644 index 000000000..751513ce1 --- /dev/null +++ b/examples/with-strict-csp/.gitignore @@ -0,0 +1,28 @@ +dist +.wrangler +.output +.vercel +.netlify +.vinxi +app.config.timestamp_*.js + +# Environment +.env +.env*.local + +# dependencies +/node_modules + +# IDEs and editors +/.idea +.project +.classpath +*.launch +.settings/ + +# Temp +gitignore + +# System Files +.DS_Store +Thumbs.db diff --git a/examples/with-strict-csp/README.md b/examples/with-strict-csp/README.md new file mode 100644 index 000000000..80ffc20d3 --- /dev/null +++ b/examples/with-strict-csp/README.md @@ -0,0 +1,37 @@ +# Content Security Policy with Nonce + +This example demonstrates how to implement a strict Content Security Policy (CSP) with a nonce in a SolidStart application. + +## How to Use + +You can use the Solid CLI to bootstrap the example with one of the following commands based on your package manager preference: + +**npm:** + +```bash +npm init solid@latest --solidstart --ts --template with-strict-csp my-app-with-strict-csp +``` + +**pnpm:** + +```bash +pnpm create solid --solidstart --ts --template with-strict-csp my-app-with-strict-csp +``` + +**yarn:** + +```bash +yarn create solid@latest --solidstart --ts --template with-strict-csp my-app-with-strict-csp +``` + +**bun:** + +```bash +bun create solid@latest --solidstart --ts --template with-strict-csp my-app-with-strict-csp +``` + +**deno:** + +```bash +deno init --npm solid@latest --solidstart --ts --template with-strict-csp my-app-with-strict-csp +``` diff --git a/examples/with-strict-csp/app.config.ts b/examples/with-strict-csp/app.config.ts new file mode 100644 index 000000000..ba31e7c7e --- /dev/null +++ b/examples/with-strict-csp/app.config.ts @@ -0,0 +1,5 @@ +import { defineConfig } from "@solidjs/start/config"; + +export default defineConfig({ + middleware: "src/middleware.ts" +}); diff --git a/examples/with-strict-csp/package.json b/examples/with-strict-csp/package.json new file mode 100644 index 000000000..7d2f6f75f --- /dev/null +++ b/examples/with-strict-csp/package.json @@ -0,0 +1,17 @@ +{ + "name": "example-bare", + "type": "module", + "scripts": { + "dev": "vinxi dev", + "build": "vinxi build", + "start": "vinxi start" + }, + "dependencies": { + "@solidjs/start": "^1.1.0", + "solid-js": "^1.9.5", + "vinxi": "^0.5.3" + }, + "engines": { + "node": ">=22" + } +} diff --git a/examples/with-strict-csp/public/favicon.ico b/examples/with-strict-csp/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..fb282da0719ef6ab4c1732df93be6216b0d85520 GIT binary patch literal 664 zcmV;J0%!e+P)m9ebk1R zejT~~6f_`?;`cEd!+`7(hw@%%2;?RN8gX-L?z6cM( zKoG@&w+0}f@Pfvwc+deid)qgE!L$ENKYjViZC_Zcr>L(`2oXUT8f0mRQ(6-=HN_Ai zeBBEz3WP+1Cw`m!49Wf!MnZzp5bH8VkR~BcJ1s-j90TAS2Yo4j!J|KodxYR%3Numw zA?gq6e`5@!W~F$_De3yt&uspo&2yLb$(NwcPPI-4LGc!}HdY%jfq@AFs8LiZ4k(p} zZ!c9o+qbWYs-Mg zgdyTALzJX&7QXHdI_DPTFL33;w}88{e6Zk)MX0kN{3DX9uz#O_L58&XRH$Nvvu;fO zf&)7@?C~$z1K<>j0ga$$MIg+5xN;eQ?1-CA=`^Y169@Ab6!vcaNP=hxfKN%@Ly^R* zK1iv*s1Yl6_dVyz8>ZqYhz6J4|3fQ@2LQeX@^%W(B~8>=MoEmBEGGD1;gHXlpX>!W ym)!leA2L@`cpb^hy)P75=I!`pBYxP7<2VfQ3j76qLgzIA0000 +

Hello world!

+ +

+ Visit{" "} + + start.solidjs.com + {" "} + to learn how to build SolidStart apps. +

+ + ); +} diff --git a/examples/with-strict-csp/src/entry-client.tsx b/examples/with-strict-csp/src/entry-client.tsx new file mode 100644 index 000000000..0ca4e3c30 --- /dev/null +++ b/examples/with-strict-csp/src/entry-client.tsx @@ -0,0 +1,4 @@ +// @refresh reload +import { mount, StartClient } from "@solidjs/start/client"; + +mount(() => , document.getElementById("app")!); diff --git a/examples/with-strict-csp/src/entry-server.tsx b/examples/with-strict-csp/src/entry-server.tsx new file mode 100644 index 000000000..ba12e1cdd --- /dev/null +++ b/examples/with-strict-csp/src/entry-server.tsx @@ -0,0 +1,24 @@ +// @refresh reload +import { createHandler, StartServer } from "@solidjs/start/server"; + +export default createHandler( + () => ( + ( + + + + + + {assets} + + +
{children}
+ {scripts} + + + )} + /> + ), + event => ({ nonce: event.locals.nonce }) +); diff --git a/examples/with-strict-csp/src/global.d.ts b/examples/with-strict-csp/src/global.d.ts new file mode 100644 index 000000000..dc6f10c22 --- /dev/null +++ b/examples/with-strict-csp/src/global.d.ts @@ -0,0 +1 @@ +/// diff --git a/examples/with-strict-csp/src/middleware.ts b/examples/with-strict-csp/src/middleware.ts new file mode 100644 index 000000000..bc93af03f --- /dev/null +++ b/examples/with-strict-csp/src/middleware.ts @@ -0,0 +1,31 @@ +import { createMiddleware } from "@solidjs/start/middleware"; +import { randomBytes } from "crypto"; + +const isProd = import.meta.env.PROD; + +export default createMiddleware({ + onRequest: event => { + const nonce = randomBytes(16).toString("base64"); + + event.locals.nonce = nonce; + + // Notes: + // 1. SolidStart uses `eval` for data serialization, which may require you to add 'unsafe-eval' to your CSP. + // For more information, see: https://github.com/solidjs/solid-start/issues/1825 + // 2. In development, Vite inlines small CSS files to enhance performance, so you will need to include 'unsafe-inline' in development mode. + // 3. During the build process, Vite inlines small assets as data URLs. Therefore, it's necessary to add data: to the relevant directives (e.g., img-src, font-src, etc.) + // For more details, see: https://vite.dev/config/build-options.html#build-assetsinlinelimit + const csp = ` + default-src 'self'; + script-src 'nonce-${nonce}' 'strict-dynamic' 'unsafe-eval'; + style-src 'self' ${isProd ? "" : "'unsafe-inline'"}; + img-src 'self' ${isProd ? "" : "data:"}; + object-src 'none'; + base-uri 'none'; + frame-ancestors 'none'; + form-action 'self'; + `.replace(/\s+/g, " "); + + event.response.headers.set("Content-Security-Policy", csp); + } +}); diff --git a/examples/with-strict-csp/tsconfig.json b/examples/with-strict-csp/tsconfig.json new file mode 100644 index 000000000..7d5871a07 --- /dev/null +++ b/examples/with-strict-csp/tsconfig.json @@ -0,0 +1,19 @@ +{ + "compilerOptions": { + "target": "ESNext", + "module": "ESNext", + "moduleResolution": "bundler", + "allowSyntheticDefaultImports": true, + "esModuleInterop": true, + "jsx": "preserve", + "jsxImportSource": "solid-js", + "allowJs": true, + "strict": true, + "noEmit": true, + "types": ["vinxi/types/client"], + "isolatedModules": true, + "paths": { + "~/*": ["./src/*"] + } + } +} From 4a33ee6a17932a88a01a10e0f555e2be7aca1154 Mon Sep 17 00:00:00 2001 From: "Amir H. Hashemi" <87268103+amirhhashemi@users.noreply.github.com> Date: Wed, 25 Jun 2025 19:17:01 +0330 Subject: [PATCH 2/2] update --- examples/with-strict-csp/src/middleware.ts | 23 +++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/examples/with-strict-csp/src/middleware.ts b/examples/with-strict-csp/src/middleware.ts index bc93af03f..fa937b47e 100644 --- a/examples/with-strict-csp/src/middleware.ts +++ b/examples/with-strict-csp/src/middleware.ts @@ -7,19 +7,28 @@ export default createMiddleware({ onRequest: event => { const nonce = randomBytes(16).toString("base64"); - event.locals.nonce = nonce; + if (isProd) { + event.locals.nonce = nonce; + } // Notes: - // 1. SolidStart uses `eval` for data serialization, which may require you to add 'unsafe-eval' to your CSP. + // 1. SolidStart uses `eval` for data serialization, which may require you to include the 'unsafe-eval' directive in your CSP. // For more information, see: https://github.com/solidjs/solid-start/issues/1825 - // 2. In development, Vite inlines small CSS files to enhance performance, so you will need to include 'unsafe-inline' in development mode. - // 3. During the build process, Vite inlines small assets as data URLs. Therefore, it's necessary to add data: to the relevant directives (e.g., img-src, font-src, etc.) + // 2. In development, Vite inlines small CSS files to improve performance, so you'll need to include the 'unsafe-inline' directive in development. + // 3. During the build process, Vite inlines small assets as data URLs. + // Therefore, it's necessary to add `data:` to the relevant directives (e.g., img-src, font-src, etc.). // For more details, see: https://vite.dev/config/build-options.html#build-assetsinlinelimit const csp = ` default-src 'self'; - script-src 'nonce-${nonce}' 'strict-dynamic' 'unsafe-eval'; - style-src 'self' ${isProd ? "" : "'unsafe-inline'"}; - img-src 'self' ${isProd ? "" : "data:"}; + script-src ${ + isProd + ? // Note: The `https:` and `'unsafe-inline'` directives do not reduce the effectiveness of the CSP. + // They are only fallbacks for older browsers that don't support `'strict-dynamic'`. + `'nonce-${nonce}' 'strict-dynamic' 'unsafe-eval' https: 'unsafe-inline'` + : "'self' 'unsafe-inline' 'unsafe-eval' https: http:" + }; + style-src ${isProd ? `'nonce-${nonce}'` : "'self' 'unsafe-inline'"}; + img-src 'self' data:; object-src 'none'; base-uri 'none'; frame-ancestors 'none';