{"id":13107,"library":"egg-security","title":"Egg.js Security Plugin","description":"The `@eggjs/security` (formerly `egg-security`) package is a robust security plugin specifically designed for the Egg.js framework. It provides comprehensive protection against common web vulnerabilities, including Cross-Site Request Forgery (CSRF), Cross-Site Scripting (XSS), Server-Side Request Forgery (SSRF), SQL injection, and more. The current stable version is 4.0.1 (under the `@eggjs/security` namespace), with the 3.x branch (`egg-security`) also receiving maintenance updates, with `3.8.0` being the latest for that line. The project maintains an active release cadence, frequently publishing minor and patch versions to introduce new features, improve existing protections, and address bug fixes. A significant update to version 4.0.0 migrated the codebase to TypeScript and dropped support for Node.js versions older than 18.19.0. Its key differentiator lies in its deep integration with the Egg.js ecosystem, offering out-of-the-box security measures that are easily configurable within the framework's convention-over-configuration paradigm, simplifying the implementation of robust security practices for developers building Egg.js applications.","status":"active","version":"3.7.0","language":"javascript","source_language":"en","source_url":"https://github.com/eggjs/egg-security","tags":["javascript","egg","eggPlugin","egg-plugin","security"],"install":[{"cmd":"npm install egg-security","lang":"bash","label":"npm"},{"cmd":"yarn add egg-security","lang":"bash","label":"yarn"},{"cmd":"pnpm add egg-security","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"Peer dependency as an Egg.js framework plugin.","package":"egg","optional":false},{"reason":"Internal IP utility for security checks, replaced `ip` package in v3.3.1.","package":"@eggjs/ip","optional":false}],"imports":[{"note":"For Egg.js plugins, you enable them in `config/plugin.ts` (or `.js`) by specifying the package name. Note the package name change to `@eggjs/security` since v4.0.0.","wrong":"import { Security } from 'egg-security'; // Plugins are enabled via config, not direct import","symbol":"Enable Plugin","correct":"// config/plugin.ts\nexport default {\n  security: {\n    enable: true,\n    package: '@eggjs/security'\n  }\n};"},{"note":"Security configurations are typically defined in `config/config.default.ts` (or `.js`) within the `config.security` object.","wrong":"const securityConfig = require('egg-security').config; // Incorrect module access and CJS for TS project","symbol":"Configure Security","correct":"// config/config.default.ts\nimport { EggAppConfig } from 'egg';\n\nexport default (appInfo: EggAppInfo) => {\n  const config = {} as Partial<EggAppConfig>;\n  config.security = {\n    csrf: {\n      enable: true,\n      headerName: 'x-csrf-token',\n    },\n    xframe: {\n      enable: true,\n      value: 'SAMEORIGIN',\n    },\n  };\n  return config;\n};"},{"note":"The CSRF token is exposed via `ctx.csrf` on the `Context` object, which should be included in non-GET requests.","wrong":"import { csrf } from '@eggjs/security'; // CSRF token is context-bound, not a direct import.","symbol":"Access CSRF Token (Context)","correct":"// app/controller/home.ts\nimport { Controller } from 'egg';\n\nclass HomeController extends Controller {\n  public async showForm() {\n    const { ctx } = this;\n    ctx.body = `\n      <html>\n        <body>\n          <form method=\"POST\" action=\"/submit\">\n            <input type=\"hidden\" name=\"_csrf\" value=\"${ctx.csrf}\" />\n            <input type=\"text\" name=\"data\" />\n            <button type=\"submit\">Submit</button>\n          </form>\n        </body>\n      </html>\n    `;\n  }\n}"}],"quickstart":{"code":"import { Application, Controller } from 'egg';\n\n// 1. Create a minimal Egg.js application (e.g., in a directory named 'my-egg-app')\n//    Install dependencies: npm init egg --type=ts && npm i @eggjs/security\n\n// 2. config/plugin.ts (enable the security plugin)\n//    Note the package name change to @eggjs/security for v4+\nexport default {\n  static: { enable: true }, // Built-in plugin\n  security: {\n    enable: true,\n    package: '@eggjs/security',\n  },\n};\n\n// 3. config/config.default.ts (configure security options)\nimport { EggAppConfig, EggAppInfo } from 'egg';\n\nexport default (appInfo: EggAppInfo) => {\n  const config = {} as Partial<EggAppConfig>;\n\n  // For security reasons, you should change your own keys.\n  config.keys = appInfo.name + '_123456';\n\n  config.security = {\n    csrf: {\n      enable: true,\n      headerName: 'x-csrf-token', // Common header for AJAX requests\n      // rotateWhenInvalid: true, // Example of another CSRF option\n    },\n    xframe: {\n      enable: true,\n      value: 'SAMEORIGIN',\n    },\n    // More security configurations (e.g., xss, ssrf, csp) can be added here\n  };\n\n  return config;\n};\n\n// 4. app/controller/home.ts (example controller using CSRF)\nexport default class HomeController extends Controller {\n  public async showForm() {\n    const { ctx } = this;\n    ctx.body = `\n      <html>\n      <head><title>CSRF Test</title></head>\n      <body>\n        <h1>Submit Data with CSRF</h1>\n        <form method=\"POST\" action=\"/submit\">\n          <input type=\"hidden\" name=\"_csrf\" value=\"${ctx.csrf}\" />\n          <label for=\"data\">Data:</label>\n          <input type=\"text\" id=\"data\" name=\"data\" required />\n          <button type=\"submit\">Submit</button>\n        </form>\n        <p>Your CSRF Token: <code>${ctx.csrf}</code></p>\n      </body>\n      </html>\n    `;\n  }\n\n  public async submitData() {\n    const { ctx } = this;\n    // If CSRF check fails, Egg.js will automatically throw a 403 error\n    ctx.body = `Data received: ${ctx.request.body.data || 'No data'}. Token Validated!`;\n  }\n}\n\n// 5. app/router.ts\nexport default (app: Application) => {\n  const { router, controller } = app;\n  router.get('/', controller.home.showForm);\n  router.post('/submit', controller.home.submitData);\n};\n\n// To run this:\n// 1. mkdir my-egg-app && cd my-egg-app\n// 2. npm init egg --type=ts\n// 3. npm i @eggjs/security\n// 4. Copy the code above into the respective files (plugin.ts, config.default.ts, app/controller/home.ts, app/router.ts)\n// 5. npm run dev\n// 6. Open http://localhost:7001 in your browser.","lang":"typescript","description":"This quickstart demonstrates how to set up a basic Egg.js application, enable the `@eggjs/security` plugin, configure its CSRF protection, and show how to embed and validate a CSRF token in a simple HTML form using TypeScript."},"warnings":[{"fix":"In `package.json`, change `\"egg-security\": \"^3.x.x\"` to `\"@eggjs/security\": \"^4.x.x\"`. In `config/plugin.ts` (or `.js`), update `package: 'egg-security'` to `package: '@eggjs/security'`.","message":"The package name for `egg-security` was officially changed to `@eggjs/security` starting from version 4.0.0. Upgrading from v3.x to v4.x requires updating your `package.json` dependencies and `config/plugin.ts` (or `.js`) to use the new scoped package name.","severity":"breaking","affected_versions":">=4.0.0"},{"fix":"Upgrade your Node.js environment to version 18.19.0 or newer to ensure compatibility.","message":"Version 4.0.0 of `@eggjs/security` drops support for Node.js versions older than 18.19.0. Running the plugin on unsupported Node.js versions will lead to errors.","severity":"breaking","affected_versions":">=4.0.0"},{"fix":"For TypeScript projects, ensure `tsconfig.json` is correctly configured. For JavaScript projects, be aware of potential changes and review the documentation for any new configuration patterns or type-related impacts.","message":"The codebase for `@eggjs/security` was migrated to TypeScript in version 4.0.0. While compiled JavaScript is provided, projects written in plain JavaScript might encounter subtle changes in behavior or require adjustments if relying on specific internal structures that changed during the migration, especially regarding configuration types.","severity":"breaking","affected_versions":">=4.0.0"},{"fix":"For form submissions, include `<input type=\"hidden\" name=\"_csrf\" value=\"${ctx.csrf}\" />`. For AJAX requests, send the token in a header (e.g., `X-CSRF-Token`) or as a body parameter (e.g., `_csrf`). The token can be accessed via `ctx.csrf`.","message":"CSRF protection is enabled by default and requires including the CSRF token in all non-GET requests (POST, PUT, DELETE). Failing to do so will result in a 403 Forbidden error.","severity":"gotcha","affected_versions":"*"},{"fix":"Always use `ctx.safeCurl` (or `app.safeCurl`/`agent.safeCurl`) for making HTTP requests to external or user-provided URLs. Configure `security.ssrf.hostnameExceptionList` for explicitly whitelisting internal hosts if necessary.","message":"Server-Side Request Forgery (SSRF) protection is provided via `ctx.safeCurl`, `app.safeCurl`, and `agent.safeCurl`. Direct use of `ctx.curl` without proper URL validation can expose your application to SSRF vulnerabilities, even with the plugin enabled.","severity":"gotcha","affected_versions":"*"}],"env_vars":null,"last_verified":"2026-04-19T00:00:00.000Z","next_check":"2026-07-18T00:00:00.000Z","problems":[{"fix":"Update your `package.json` to depend on `@eggjs/security` and adjust `config/plugin.ts` (or `.js`) to use `package: '@eggjs/security'`. Then run `npm install`.","cause":"Attempting to use the `egg-security` package name after upgrading to Egg.js v4, where the plugin was renamed to `@eggjs/security`.","error":"Error: Cannot find module 'egg-security'"},{"fix":"Ensure that the CSRF token (obtained from `ctx.csrf`) is included in your form submissions (as a hidden field `_csrf`) or AJAX requests (e.g., in the `X-CSRF-Token` header).","cause":"A non-GET request (e.g., POST, PUT) was made without a valid CSRF token, or the token provided did not match the server-generated one.","error":"Error: CSRF token mismatch"},{"fix":"Verify that `config/plugin.ts` (or `.js`) explicitly enables the security plugin: `security: { enable: true, package: '@eggjs/security' }`. Also ensure Egg.js is initialized correctly.","cause":"Attempting to access `ctx.csrf` when the security plugin is not enabled or not properly configured in `config/plugin.ts`.","error":"TypeError: Cannot read properties of undefined (reading 'csrf')"},{"fix":"Upgrade your Node.js runtime to version 18.19.0 or higher. You can use a Node Version Manager (NVM) to manage multiple Node.js versions.","cause":"Running `@eggjs/security` version 4.0.0 or higher on an unsupported Node.js version (below 18.19.0).","error":"Error: Node.js v16.x is not supported by @eggjs/security@4.x"},{"fix":"If the URL is legitimate, configure `config.security.ssrf.hostnameExceptionList` or `checkAddress` to explicitly allow access to that hostname or IP. Avoid using `ctx.curl` for external or user-provided URLs.","cause":"An HTTP request was made to an internal or blacklisted IP address/domain using `ctx.safeCurl` (or `app.safeCurl`/`agent.safeCurl`) without explicitly whitelisting it.","error":"SecurityWarning: SSRF detected, URL 'http://127.0.0.1:8080/internal' is forbidden"}],"ecosystem":"npm","meta_description":null,"install_score":null,"install_tag":null,"quickstart_score":null,"quickstart_tag":null,"pypi_latest":null,"cli_name":""}