Files
Devour/devour_data/docs/security.json
T
Tomas Dvorak 898a3c303f update
2026-02-24 10:33:59 +01:00

17 lines
8.7 KiB
JSON

{
"id": "5d9475b44290500a74225e16",
"source": "solid:signals",
"type": "github-document",
"title": "security",
"content": "---\ntitle: Security\nuse_cases: \u003e-\n production apps, user input handling, authentication, public apis, preventing\n attacks, secure deployments, compliance\ntags:\n - security\n - xss\n - csrf\n - cors\n - csp\n - middleware\n - protection\nversion: '1.0'\ndescription: \u003e-\n Secure your SolidStart apps against XSS, CSRF attacks. Configure CSP headers,\n CORS policies, and implement security best practices.\n---\n\n## XSS (Cross Site Scripting)\n\nSolid automatically escape values passed to JSX expressions to reduce the risk of XSS attacks.\nHowever, this protection does not apply when using [`innerHTML`](/reference/jsx-attributes/innerhtml).\n\nTo protect your application from XSS attacks:\n\n- Set a [Content Security Policy (CSP)](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP).\n- Validate and sanitize user inputs, especially form inputs on the server and client.\n- Avoid using `innerHTML` when possible.\n If necessary, make sure to sanitize user-supplied data with libraries such as [DOMPurify](https://github.com/cure53/DOMPurify).\n- Sanitize attributes containing user-supplied data within `\u003cnoscript\u003e` elements.\n This includes both the attributes of the `\u003cnoscript\u003e` element itself and its children.\n- When URLs are provided or constructed via user input validate its `origin` and `protocol` (to avoid evaluating code via `javascript:` URLs) using the [URL](https://developer.mozilla.org/en-US/docs/Web/API/URL) API.\n\nIt is highly recommended to read the [Cross Site Scripting Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html) for further guidance.\n\n## Content Security Policy (CSP)\n\nTo configure the `Content-Security-Policy` HTTP header, a [middleware](/solid-start/advanced/middleware) can be used.\n\n### With nonce (recommended)\n\nIf you want to use a [strict CSP](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP#strict_csp) with nonces:\n\n1. Create a middleware that configures the CSP header.\nIt must then be registered using the [`onRequest`](/solid-start/advanced/middleware#onrequest) event.\n2. Create a nonce using a cryptographic random value generator, such as the [`randomBytes`](https://nodejs.org/api/crypto.html#cryptorandombytessize-callback) function from the `crypto` module.\n3. Store the nonce in the [`locals`](/solid-start/advanced/middleware#locals) object.\n4. Configure SolidStart to use the nonce in your [`entry-server.tsx`](/solid-start/reference/entrypoints/entry-server) file.\n\n```tsx tab title=\"Middleware\"\nimport { createMiddleware } from \"@solidjs/start/middleware\";\nimport { randomBytes } from \"crypto\";\n\nexport default createMiddleware({\n\tonRequest: (event) =\u003e {\n\t\tconst nonce = randomBytes(16).toString(\"base64\");\n\n\t\tevent.locals.nonce = nonce;\n\n\t\tconst csp = `\n default-src 'self';\n script-src 'nonce-${nonce}' 'strict-dynamic' 'unsafe-eval';\n object-src 'none';\n base-uri 'none';\n frame-ancestors 'none';\n form-action 'self';\n `.replace(/\\s+/g, \" \");\n\n\t\tevent.response.headers.set(\"Content-Security-Policy\", csp);\n\t},\n});\n```\n\n```tsx tab title=\"entry-server.tsx\" {7}\n// src/entry-server.tsx\n// @refresh reload\nimport { createHandler, StartServer } from \"@solidjs/start/server\";\n\nexport default createHandler(\n\t() =\u003e \u003cStartServer /* ... */ /\u003e,\n\t(event) =\u003e ({ nonce: event.locals.nonce })\n);\n```\n\n### Without nonce\n\nTo configure CSP without a nonce, a middleware that sets the CSP header is required, and it should be registered to run during the [`onBeforeResponse`](/solid-start/advanced/middleware#onbeforeresponse) event:\n\n```tsx\nimport { createMiddleware } from \"@solidjs/start/middleware\";\n\nexport default createMiddleware({\n\tonBeforeResponse: (event) =\u003e {\n\t\tconst csp = `\n default-src 'self';\n font-src 'self' ;\n object-src 'none';\n base-uri 'none';\n frame-ancestors 'none';\n form-action 'self';\n `.replace(/\\s+/g, \" \");\n\n\t\tevent.response.headers.set(\"Content-Security-Policy\", csp);\n\t},\n});\n```\n\n## CORS (Cross-Origin Resource Sharing)\n\nWhen other applications need access to API endpoints, a middleware that configures the CORS headers is needed:\n\n```tsx\nimport { createMiddleware } from \"@solidjs/start/middleware\";\nimport { json } from \"@solidjs/router\";\n\nconst TRUSTED_ORIGINS = [\"https://my-app.com\", \"https://another-app.com\"];\n\nexport default createMiddleware({\n\tonBeforeResponse: (event) =\u003e {\n\t\tconst { request, response } = event;\n\n\t\tresponse.headers.append(\"Vary\", \"Origin, Access-Control-Request-Method\");\n\n\t\tconst origin = request.headers.get(\"Origin\");\n\t\tconst requestUrl = new URL(request.url);\n\t\tconst isApiRequest = requestUrl \u0026\u0026 requestUrl.pathname.startsWith(\"/api\");\n\n\t\tif (isApiRequest \u0026\u0026 origin \u0026\u0026 TRUSTED_ORIGINS.includes(origin)) {\n\t\t\t// Handle preflight requests.\n\t\t\tif (\n\t\t\t\trequest.method === \"OPTIONS\" \u0026\u0026\n\t\t\t\trequest.headers.get(\"Access-Control-Request-Method\")\n\t\t\t) {\n\t\t\t\t// Preflight requests are standalone, so we immediately send a response.\n\t\t\t\treturn json(null, {\n\t\t\t\t\theaders: {\n\t\t\t\t\t\t\"Access-Control-Allow-Origin\": origin,\n\t\t\t\t\t\t\"Access-Control-Allow-Methods\": \"OPTIONS, POST, PUT, PATCH, DELETE\",\n\t\t\t\t\t\t\"Access-Control-Allow-Headers\": \"Authorization, Content-Type\",\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t// Handle normal requests.\n\t\t\tresponse.headers.set(\"Access-Control-Allow-Origin\", origin);\n\t\t}\n\t},\n});\n```\n\n## CSRF (Cross-Site Request Forgery)\n\nTo prevent basic CSRF attacks, a middleware can be used to block untrusted requests:\n\n```tsx\nimport { createMiddleware } from \"@solidjs/start/middleware\";\nimport { json } from \"@solidjs/router\";\n\nconst SAFE_METHODS = [\"GET\", \"HEAD\", \"OPTIONS\", \"TRACE\"];\nconst TRUSTED_ORIGINS = [\"https://another-app.com\"];\n\nexport default createMiddleware({\n\tonRequest: (event) =\u003e {\n\t\tconst { request } = event;\n\n\t\tif (!SAFE_METHODS.includes(request.method)) {\n\t\t\tconst requestUrl = new URL(request.url);\n\t\t\tconst origin = request.headers.get(\"Origin\");\n\n\t\t\t// If we have an Origin header, check it against our allowlist.\n\t\t\tif (origin) {\n\t\t\t\tconst parsedOrigin = new URL(origin);\n\n\t\t\t\tif (\n\t\t\t\t\tparsedOrigin.origin !== requestUrl.origin \u0026\u0026\n\t\t\t\t\t!TRUSTED_ORIGINS.includes(parsedOrigin.host)\n\t\t\t\t) {\n\t\t\t\t\treturn json({ error: \"origin invalid\" }, { status: 403 });\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// If we are serving via TLS and have no Origin header, prevent against\n\t\t\t// CSRF via HTTP man-in-the-middle attacks by enforcing strict Referer\n\t\t\t// origin checks.\n\t\t\tif (!origin \u0026\u0026 requestUrl.protocol === \"https:\") {\n\t\t\t\tconst referer = request.headers.get(\"Referer\");\n\n\t\t\t\tif (!referer) {\n\t\t\t\t\treturn json({ error: \"referer not supplied\" }, { status: 403 });\n\t\t\t\t}\n\n\t\t\t\tconst parsedReferer = new URL(referer);\n\n\t\t\t\tif (parsedReferer.protocol !== \"https:\") {\n\t\t\t\t\treturn json({ error: \"referer invalid\" }, { status: 403 });\n\t\t\t\t}\n\n\t\t\t\tif (\n\t\t\t\t\tparsedReferer.host !== requestUrl.host \u0026\u0026\n\t\t\t\t\t!TRUSTED_ORIGINS.includes(parsedReferer.host)\n\t\t\t\t) {\n\t\t\t\t\treturn json({ error: \"referer invalid\" }, { status: 403 });\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n});\n```\n\nThis example demonstrates a basic CSRF protection that verifies the `Origin` and `Referer` headers, blocking requests from untrusted origins.\n**Please note both of these headers can be forged.**\nAdditionally, consider implementing a more robust CSRF protection mechanism, such as the [Double-Submit Cookie Pattern](https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html#alternative-using-a-double-submit-cookie-pattern).\n\nFor further guidance, you can look at the [Cross-Site Request Forgery Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html).",
"url": "https://github.com/solidjs/solid-docs/blob/HEAD/src/routes/solid-start/guides/security.mdx",
"metadata": {
"path": "src/routes/solid-start/guides/security.mdx",
"repo": "solidjs/solid-docs",
"repo_url": "https://github.com/solidjs/solid-docs.git",
"size": 7641,
"source_type": "github"
},
"hash": "dc458ea9c3cc0e953403c33a0a533131956e83944136d11af3b46900bd213ee8",
"timestamp": "2026-02-23T11:43:00.19429217+01:00"
}