{"id":10693,"library":"csrf-sync","title":"CSRF Sync","description":"CSRF Sync is a utility package designed to provide robust stateful Cross-Site Request Forgery (CSRF) protection for Express applications, utilizing the Synchroniser Token Pattern. Developed in response to the deprecation of `csurf` and the perceived complexity or limited scope of alternative solutions, `csrf-sync` (current stable version 4.2.1) aims for a targeted and simplified implementation. It requires a server-side session management middleware like `express-session` to store tokens. The library focuses on providing the essential components for CSRF protection without imposing a full solution, allowing developers to integrate it flexibly. It is actively maintained with regular updates and follows a clear versioning strategy, with significant changes typically highlighted in major version bumps.","status":"active","version":"4.2.1","language":"javascript","source_language":"en","source_url":"https://github.com/Psifi-Solutions/csrf-sync","tags":["javascript","csrf","middleware","express","tokens","typescript"],"install":[{"cmd":"npm install csrf-sync","lang":"bash","label":"npm"},{"cmd":"yarn add csrf-sync","lang":"bash","label":"yarn"},{"cmd":"pnpm add csrf-sync","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"Required for stateful session management to store CSRF tokens in `req.session`.","package":"express-session","optional":false}],"imports":[{"note":"Since v3, `csrfSync` is a named export. It's the factory function that returns an object of utilities, and should be imported as such for both ESM and CommonJS.","wrong":"const csrfSync = require('csrf-sync');","symbol":"csrfSync","correct":"import { csrfSync } from 'csrf-sync';"},{"note":"This is a middleware function returned by calling the `csrfSync()` factory function, not a direct named export from the package root. It must be destructured from the `csrfSync()` return value.","wrong":"import { csrfSynchronisedProtection } from 'csrf-sync';","symbol":"csrfSynchronisedProtection","correct":"const { csrfSynchronisedProtection } = csrfSync();"},{"note":"This utility function, used to create and store CSRF tokens in the session and retrieve them for client-side inclusion, is destructured from the object returned by `csrfSync()`.","wrong":"import { generateToken } from 'csrf-sync';","symbol":"generateToken","correct":"const { generateToken } = csrfSync();"}],"quickstart":{"code":"import express from 'express';\nimport session from 'express-session';\nimport { csrfSync } from 'csrf-sync';\n\nconst app = express();\nconst port = 3000;\n\n// Configure express-session middleware\napp.use(session({\n  secret: process.env.SESSION_SECRET ?? 'super-secret-key-please-change-me',\n  resave: false,\n  saveUninitialized: true,\n  cookie: { httpOnly: true, secure: process.env.NODE_ENV === 'production' }\n}));\n\n// Initialize csrf-sync and get the protection middleware and token generator\nconst { csrfSynchronisedProtection, generateToken } = csrfSync();\n\n// Apply CSRF protection to all routes (or specific ones)\napp.use(csrfSynchronisedProtection);\n\n// Middleware to parse URL-encoded bodies for form submissions\napp.use(express.urlencoded({ extended: false }));\n\n// Route to display a form with a CSRF token\napp.get('/', (req, res) => {\n  const token = generateToken(req);\n  res.send(`\n    <!DOCTYPE html>\n    <html>\n    <head><title>CSRF Test</title></head>\n    <body>\n      <h1>Submit Form</h1>\n      <form action=\"/submit\" method=\"POST\">\n        <input type=\"hidden\" name=\"_csrf\" value=\"${token}\">\n        <input type=\"text\" name=\"data\" placeholder=\"Enter data\">\n        <button type=\"submit\">Submit</button>\n      </form>\n    </body>\n    </html>\n  `);\n});\n\n// Protected route to handle form submission\napp.post('/submit', (req, res) => {\n  res.send(`Data received: ${req.body.data} (CSRF protected)`);\n});\n\n// Error handling for CSRF issues (optional but recommended)\napp.use((err, req, res, next) => {\n  if (err.code === 'EBADCSRFTOKEN') {\n    res.status(403).send('Invalid CSRF token - potential attack!');\n  } else {\n    next(err);\n  } \n});\n\napp.listen(port, () => {\n  console.log(`Server listening at http://localhost:${port}`);\n  if (!process.env.SESSION_SECRET) {\n    console.warn('WARNING: SESSION_SECRET is not set. Using a default, which is insecure for production.');\n  }\n});","lang":"typescript","description":"This quickstart demonstrates setting up an Express application with `express-session` and `csrf-sync` to protect a form submission route. It shows how to initialize the CSRF protection, generate a token, include it in an HTML form, and handle POST requests with CSRF validation, including basic error handling for invalid tokens."},"warnings":[{"fix":"Ensure `express-session` and `@types/express-session` are installed: `npm install express-session @types/express-session`.","message":"Starting with v4.0.0, `csrf-sync` no longer bundles TypeScript types for `express-session`. Users must explicitly install `express-session` and its types (`@types/express-session`) for TypeScript projects.","severity":"breaking","affected_versions":">=4.0.0"},{"fix":"Update import statements to use named exports for CommonJS or `import { csrfSync } from 'csrf-sync';` for ESM.","message":"Version 3.0.0 transitioned `csrf-sync` to an ESM-first package. This changed the CommonJS import pattern from attempting a default import to a named import `const { csrfSync } = require('csrf-sync');`.","severity":"breaking","affected_versions":">=3.0.0"},{"fix":"Always ensure `express-session` or a compatible session middleware is initialized and used prior to `csrfSynchronisedProtection` middleware.","message":"`csrf-sync` fundamentally relies on a stateful session middleware (e.g., `express-session`) that populates `req.session`. Without this middleware correctly configured and placed before `csrfSynchronisedProtection`, the library will fail to store and validate tokens.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Follow OWASP guidelines for secure session management. Use a strong, securely stored `session.secret`, set `httpOnly` and `secure` flags appropriately for cookies, and avoid common session hijacking vectors.","message":"Improper configuration of the underlying session middleware (e.g., weak session secret, insecure cookie flags) can compromise the effectiveness of CSRF protection provided by `csrf-sync`. The library itself cannot mitigate underlying session vulnerabilities.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Evaluate your application's architecture; choose `csrf-sync` for stateful web applications and consider alternatives for stateless APIs.","message":"`csrf-sync` implements the Synchronizer Token Pattern, which requires server-side state. It is not suitable for purely stateless APIs. For stateless scenarios, consider the Double-Submit Cookie Pattern (e.g., using `csrf-csrf`).","severity":"gotcha","affected_versions":">=1.0.0"}],"env_vars":null,"search_vec":"'4.2.1':53 'activ':101 'aim':54 'allow':93 'altern':45 'applic':23 'bump':120 'chang':114 'clear':109 'complex':40 'compon':84 'cross':15 'cross-sit':14 'csrf':1,3,19,48,86,122 'csrf-sync':47 'csurf':36 'current':50 'deprec':34 'design':9 'develop':29,94 'essenti':83 'express':22,72,124 'express-sess':71 'flexibl':98 'focus':79 'follow':107 'forgeri':18 'full':91 'highlight':116 'implement':60 'impos':89 'integr':96 'javascript':121 'librari':78 'like':70 'limit':42 'maintain':102 'major':118 'manag':68 'middlewar':69,123 'packag':8 'pattern':28 'perceiv':39 'protect':20,87 'provid':11,81 'regular':104 'request':17 'requir':62 'respons':31 'robust':12 'scope':43 'server':65 'server-sid':64 'session':67,73 'side':66 'signific':113 'simplifi':59 'site':16 'solut':46,92 'stabl':51 'state':13 'store':75 'strategi':111 'sync':2,4,49 'synchronis':26 'target':57 'token':27,76,125 'typescript':126 'typic':115 'updat':105 'util':7,24 'version':52,110,119 'without':88","created_at":"2026-04-19T13:34:08.597174+00:00","updated_at":"2026-04-19T13:34:08.597174+00:00","problems":[{"fix":"Ensure `app.use(session(...))` is called *before* `app.use(csrfSynchronisedProtection)` in your Express application setup.","cause":"The `express-session` middleware (or equivalent) has not been configured or is not placed correctly before the `csrf-sync` middleware.","error":"TypeError: Cannot read properties of undefined (reading 'session')"},{"fix":"Verify that the client-side code correctly retrieves the token using `generateToken(req)` and includes it in all state-changing requests (e.g., POST, PUT, DELETE). On the server, ensure `csrfSynchronisedProtection` is applied to the routes that require protection.","cause":"The CSRF token submitted in the request (e.g., via `_csrf` form field or header) does not match the token stored in the user's session, or no token was provided.","error":"Error: Invalid CSRF Token"},{"fix":"For ESM, use `import { csrfSync } from 'csrf-sync';`. For CommonJS, use `const { csrfSync } = require('csrf-sync');`.","cause":"Incorrect import statement for `csrfSync`. This often happens when treating it as a default export or using an outdated CommonJS pattern after v3.","error":"TypeError: csrfSync is not a function"}],"ecosystem":"npm","meta_description":null,"install_score":null,"quickstart_score":null,"quickstart_tag":null,"pypi_latest":null,"cli_name":"","cli_version":null,"type":"library","homepage":null,"github":"https://github.com/Psifi-Solutions/csrf-sync","docs":null,"changelog":null,"pypi":null,"npm":"https://www.npmjs.com/package/csrf-sync","openapi_spec":null,"status_page":null,"smithery":null,"categories":["auth-security"],"base_url":null,"auth_type":null,"provenance":{"verified_status":null,"verified_at":null,"last_verified":"2026-06-17","next_check":"2026-07-18","install_tag":null}}