{"id":28088918,"url":"https://github.com/amorey/edge-csrf","last_synced_at":"2025-05-13T12:52:29.506Z","repository":{"id":41464172,"uuid":"509711012","full_name":"amorey/edge-csrf","owner":"amorey","description":"CSRF protection library for JavaScript that runs on the edge runtime (with Next.js, SvelteKit, Express, Node-HTTP integrations)","archived":false,"fork":false,"pushed_at":"2025-05-08T10:03:46.000Z","size":625,"stargazers_count":170,"open_issues_count":11,"forks_count":15,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-05-08T19:48:00.538Z","etag":null,"topics":["csrf","edge","next","nextjs","svelte","sveltekit"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/amorey.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-07-02T09:19:44.000Z","updated_at":"2025-05-08T10:03:50.000Z","dependencies_parsed_at":"2023-02-10T05:46:02.981Z","dependency_job_id":"4117caad-45d6-49c4-bb56-5d87e95aa3f4","html_url":"https://github.com/amorey/edge-csrf","commit_stats":{"total_commits":66,"total_committers":4,"mean_commits":16.5,"dds":"0.045454545454545414","last_synced_commit":"586bce6f94b3c8fa5a3fb5461dc7104a34e7d9b5"},"previous_names":["amorey/csrf-edge","amorey/edge-csrf"],"tags_count":35,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/amorey%2Fedge-csrf","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/amorey%2Fedge-csrf/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/amorey%2Fedge-csrf/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/amorey%2Fedge-csrf/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/amorey","download_url":"https://codeload.github.com/amorey/edge-csrf/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253785007,"owners_count":21963901,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["csrf","edge","next","nextjs","svelte","sveltekit"],"created_at":"2025-05-13T12:52:26.424Z","updated_at":"2025-05-13T12:52:29.492Z","avatar_url":"https://github.com/amorey.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003e [!CAUTION]\n\u003e This library implements the Naive Double-Submit Cookie Pattern which is vulnerable to sub-domain attacks (when an attacker is able to set cookies for the the parent domain or other sub-domains). In order to prevent sub-domain attacks, the CSRF token must be tied to the user session which means it requires a tight integration with the session/authentication library. If your site isn't vulnerable to sub-domain attacks then you can continue to use this library but if it is, then you should consider a CSRF solution that is integrated with your auth system.\n\u003e\n\u003e Longer term, the next step for this library is to provide plugins for authentication libraries and/or to encourge authentication plugin providers to use the library primitives in `packages/core`. Unfortunately I have my hands full at the moment with another project (https://github.com/kubetail-org/kubetail) so I would like to hand this project off to another maintainer. If you're interested please let me know!\n\n\n# Edge-CSRF\n\nEdge-CSRF is a CSRF protection library for JavaScript that runs on the [edge runtime](https://edge-runtime.vercel.app/).\n\nThe Edge-CSRF library helps you to implement the [signed double submit cookie pattern](https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html#signed-double-submit-cookie-recommended) except it only uses edge runtime dependencies so it can be used in both node environments and in edge functions (e.g. [Vercel Edge Functions](https://vercel.com/docs/functions/runtimes/edge-runtime), [Cloudflare Page Functions](https://developers.cloudflare.com/pages/functions/)). The recommended way to use this library is via its drop-in integrations for Next.js and SvelteKit though it also has a lower-level API for more custom implementations.\n\nWe hope you enjoy using this software. Contributions and suggestions are welcome!\n\n## Features\n\n- Runs on both node and edge runtimes\n- Includes integrations for [Next.js](packages/nextjs), [Sveltekit](packages/sveltekit), [Express](packages/express) and [Node-HTTP](packages/node-http)\n- Includes a low-level API for custom integrations ([see here](packages/core))\n- Gets token from HTTP request header (`X-CSRF-Token`) or from request body\n- Handles form-urlencoded, multipart/form-data or json-encoded HTTP request bodies\n- Supports Server Actions via form and non-form submission\n- Customizable cookie and other options\n\n## Integrations\n\n* [Next.js](packages/nextjs)\n* [SvelteKit](packages/sveltekit)\n* [Express](packages/express)\n* [Node-HTTP](packages/node-http)\n* [Core API](packages/core)\n\n## Quickstart (Next.js)\n\nFirst, install Edge-CSRF's Next.js integration library:\n\n```console\nnpm install @edge-csrf/nextjs\n# or\npnpm add @edge-csrf/nextjs\n# or\nyarn add @edge-csrf/nextjs\n```\n\nNext, create a middleware file (`middleware.ts`) for your project and add the Edge-CSRF middleware:\n\n```typescript\n// middleware.ts\n\nimport { createCsrfMiddleware } from '@edge-csrf/nextjs';\n\n// initalize csrf protection middleware\nconst csrfMiddleware = createCsrfMiddleware({\n  cookie: {\n    secure: process.env.NODE_ENV === 'production',\n  },\n});\n\nexport const middleware = csrfMiddleware;\n```\n\nNow, all HTTP submission requests (e.g. POST, PUT, DELETE, PATCH) will be rejected if they do not include a valid CSRF token. To add the CSRF token to your forms, you can fetch it from the `X-CSRF-Token` HTTP response header server-side or client-side. For example:\n\n```typescript\n// app/page.tsx\n\nimport { headers } from 'next/headers';\n\nexport default async function Page() {\n  // NOTE: headers() don't need to be awaited in Next14\n  const h = await headers();\n  const csrfToken = h.get('X-CSRF-Token') || 'missing';\n\n  return (\n    \u003cform action=\"/api/form-handler\" method=\"post\"\u003e\n      \u003cinput type=\"hidden\" name=\"csrf_token\" value={csrfToken}\u003e\n      \u003cinput type=\"text\" name=\"my-input\"\u003e\n      \u003cinput type=\"submit\"\u003e\n    \u003c/form\u003e\n  );\n}\n```\n\n```typescript\n// app/form-handler/route.ts\n\nimport { NextResponse } from 'next/server';\n\nexport async function POST() {\n  return NextResponse.json({ status: 'success' });\n}\n```\n\nFor more Next.js examples see the [package documentation](packages/nextjs).\n\n## Quickstart (SvelteKit)\n\nFirst, install Edge-CSRF's SvelteKit integration library:\n\n```console\nnpm install @edge-csrf/sveltekit\n# or\npnpm add @edge-csrf/sveltekit\n# or\nyarn add @edge-csrf/sveltekit\n```\n\nNext, create a server-side hooks file (`hooks.server.ts`) for your project and add the Edge-CSRF handle:\n\n```typescript\n// src/hooks.server.ts\n\nimport { createCsrfHandle } from '@edge-csrf/sveltekit';\n\n// initalize csrf protection handle\nconst csrfHandle = createCsrfHandle({\n  cookie: {\n    secure: process.env.NODE_ENV === 'production',\n  },\n});\n\nexport const handle = csrfHandle;\n```\n\nNow, all HTTP submission requests (e.g. POST, PUT, DELETE, PATCH) will be rejected if they do not include a valid CSRF token. To add the CSRF token to your forms, you can fetch it from the event's `locals` data object server-side. For example:\n\n```typescript\n// src/routes/+page.server.ts\n\nexport async function load({ locals }) {\n  return {\n    csrfToken: locals.csrfToken,\n  };\n}\n\nexport const actions = {\n  default: async () =\u003e {\n    return { success: true };\n  },\n};\n```\n\n```svelte\n\u003c!-- src/routes/+page.svelte --\u003e\n\n\u003cscript lang=\"ts\"\u003e\n  export let data;\n\n  export let form;\n\u003c/script\u003e\n\n{#if form?.success}\n\u003cspan\u003esuccess\u003c/span\u003e\n{:else}\n\u003cform method=\"post\"\u003e\n  \u003cinput type=\"hidden\" name=\"csrf_token\" value={data.csrfToken}\u003e\n  \u003cinput type=\"text\" name=\"my-input\"\u003e\n  \u003cinput type=\"submit\"\u003e\n\u003c/form\u003e\n{/if}\n```\n\nFinally, to make typescript aware of the new `locals` attributes you can add Edge-CSRF types to your app's types:\n\n```typescript\n// src/app.d.ts\n\nimport type { CsrfLocals } from '@edge-csrf/sveltekit';\n\ndeclare global {\n  namespace App {\n    // ...\n    interface Locals extends CsrfLocals {}\n    // ...\n  }\n}\n\nexport {};\n```\n\n## Quickstart (Express)\n\nFirst, install Edge-CSRF's Express integration library:\n\n```console\nnpm install @edge-csrf/express\n# or\npnpm add @edge-csrf/express\n# or\nyarn add @edge-csrf/express\n```\n\nNext, add the Edge-CSRF middleware to your app:\n\n```javascript\n// app.js\n\nimport { createCsrfMiddleware } from '@edge-csrf/express';\nimport express from 'express';\n\n// initalize csrf protection middleware\nconst csrfMiddleware = createCsrfMiddleware({\n  cookie: {\n    secure: process.env.NODE_ENV === 'production',\n  },\n});\n\n// init app\nconst app = express();\nconst port = 3000;\n\n// add csrf middleware\napp.use(csrfMiddleware);\n\n// define handlers\napp.get('/', (req, res) =\u003e {\n  const csrfToken = res.getHeader('X-CSRF-Token') || 'missing';\n  res.send(`\n    \u003c!doctype html\u003e\n    \u003chtml\u003e\n      \u003cbody\u003e\n        \u003cp\u003eCSRF token value: ${csrfToken}\u003c/p\u003e\n        \u003cform action=\"/\" method=\"post\"\u003e\n          \u003clegend\u003eForm with CSRF (should succeed):\u003c/legend\u003e\n          \u003cinput type=\"hidden\" name=\"csrf_token\" value=\"${csrfToken}\" /\u003e\n          \u003cinput type=\"text\" name=\"input1\" /\u003e\n          \u003cbutton type=\"submit\"\u003eSubmit\u003c/button\u003e\n        \u003c/form\u003e\n      \u003c/body\u003e\n    \u003c/html\u003e\n  `);\n});\n\napp.post('/', (req, res) =\u003e {\n  res.send('success');\n});\n\n// start server\napp.listen(port, () =\u003e {\n  console.log(`Example app listening on port ${port}`)\n});\n```\n\nWith the middleware installed, all HTTP submission requests (e.g. POST, PUT, DELETE, PATCH) will be rejected if they do not include a valid CSRF token.\n\n## Quickstart (Node-HTTP)\n\nFirst, install Edge-CSRF's Node-HTTP integration library:\n\n```console\nnpm install @edge-csrf/node-http\n# or\npnpm add @edge-csrf/node-http\n# or\nyarn add @edge-csrf/node-http\n```\n\nNext, add the Edge-CSRF CSRF protection function to your request handlers:\n\n```javascript\n// server.js\n\nimport { createServer } from 'http';\n\nimport { createCsrfProtect } from '@edge-csrf/node-http';\n\n// initalize csrf protection middleware\nconst csrfProtect = createCsrfProtect({\n  cookie: {\n    secure: process.env.NODE_ENV === 'production',\n  },\n});\n\n// init server\nconst server = createServer(async (req, res) =\u003e {\n  // apply csrf protection\n  try {\n    await csrfProtect(req, res);\n  } catch (err) {\n    if (err instanceof CsrfError) {\n      res.writeHead(403);\n      res.end('invalid csrf token');\n      return;\n    }\n    throw err;\n  }\n\n  // add handler\n  if (req.url === '/') {\n    if (req.method === 'GET') {\n      const csrfToken = res.getHeader('X-CSRF-Token') || 'missing';\n      res.writeHead(200, { 'Content-Type': 'text/html' });\n      res.end(`\n        \u003c!doctype html\u003e\n        \u003chtml\u003e\n          \u003cbody\u003e\n            \u003cform action=\"/\" method=\"post\"\u003e\n              \u003clegend\u003eForm with CSRF (should succeed):\u003c/legend\u003e\n              \u003cinput type=\"hidden\" name=\"csrf_token\" value=\"${csrfToken}\" /\u003e\n              \u003cinput type=\"text\" name=\"input1\" /\u003e\n              \u003cbutton type=\"submit\"\u003eSubmit\u003c/button\u003e\n            \u003c/form\u003e\n          \u003c/body\u003e\n        \u003c/html\u003e\n      `);\n      return;\n    }\n\n    if (req.method === 'POST') {\n      res.writeHead(200, { 'Content-Type': 'text/plain' });\n      res.end('success');\n      return;\n    }\n  }\n\n  res.writeHead(404);\n  res.end('not found');\n});\n\n// start server\nserver.listen(3000, () =\u003e {\n  console.log('Server is listening on port 3000');\n});\n```\n\nWith the CSRF protection method, all HTTP submission requests (e.g. POST, PUT, DELETE, PATCH) will be rejected if they do not include a valid CSRF token.\n\n## Development\n\n### Get the code\n\nTo develop edge-csrf, first clone the repository then install the dependencies:\n\n```console\ngit clone git@github.com:kubetail-org/edge-csrf.git\ncd edge-csrf\npnpm install\n```\n\n### Run the unit tests\n\nEdge-CSRF uses jest for testing (via vitest). To run the tests in node, edge and miniflare environments, use the `test-all` command:\n\n```console\npnpm test-all\n```\n\nThe test files are colocated with the source code in each package's `src/` directory, with the filename format `{name}.test.ts`.\n\n### Build for production\n\nTo build Edge-CSRF for production, run the `build` command:\n\n```console\npnpm build\n```\n\nThe build artifacts will be located in the `dist/` directory of each package.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Famorey%2Fedge-csrf","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Famorey%2Fedge-csrf","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Famorey%2Fedge-csrf/lists"}