[
  {
    "id": "a04_mass_assign_mongo_update",
    "title": "OWASP A04:2021 (Insecure Design): Mass Assignment — findByIdAndUpdate with req.body",
    "description": "The entire request body is passed directly to findByIdAndUpdate(). An attacker can inject arbitrary fields such as isAdmin, role, or balance, gaining unintended access or elevated privileges.",
    "pattern": "findByIdAndUpdate\\s*\\([^)]*req\\.body",
    "file_globs": ["**/*.js", "**/*.ts", "**/*.mjs", "**/*.cjs"],
    "severity": "high",
    "confidence": "high",
    "owasp": "A04",
    "cwe": "CWE-915",
    "recommendation": "Use an allowlist of permitted fields instead of spreading the full body:\n  const allowed = { name, email, phone };\n  await User.findByIdAndUpdate(id, allowed, { new: true });\nNever pass req.body or req.query directly to a database operation.",
    "references": ["https://owasp.org/Top10/A04_2021-Insecure_Design/"]
  },
  {
    "id": "a04_mass_assign_mongo_update_one",
    "title": "OWASP A04:2021 (Insecure Design): Mass Assignment — findOneAndUpdate with req.body",
    "description": "The entire request body is passed directly to findOneAndUpdate(). An attacker can inject arbitrary fields to escalate privileges or corrupt data.",
    "pattern": "findOneAndUpdate\\s*\\([^)]*req\\.body",
    "file_globs": ["**/*.js", "**/*.ts", "**/*.mjs", "**/*.cjs"],
    "severity": "high",
    "confidence": "high",
    "owasp": "A04",
    "cwe": "CWE-915",
    "recommendation": "Extract and validate only the fields you expect before passing to the database:\n  const { name, email } = req.body;\n  await User.findOneAndUpdate(filter, { name, email });\nConsider using a validation library like Zod or Joi.",
    "references": ["https://owasp.org/Top10/A04_2021-Insecure_Design/"]
  },
  {
    "id": "a04_mass_assign_mongo_create",
    "title": "OWASP A04:2021 (Insecure Design): Mass Assignment — Model.create() with req.body",
    "description": "The full request body is passed to Model.create(). An attacker can set any field defined on the model, including sensitive fields like isAdmin, role, or verified.",
    "pattern": "\\.create\\s*\\(\\s*req\\.body",
    "file_globs": ["**/*.js", "**/*.ts", "**/*.mjs", "**/*.cjs"],
    "severity": "high",
    "confidence": "high",
    "owasp": "A04",
    "cwe": "CWE-915",
    "recommendation": "Destructure only the expected fields:\n  const { name, email, password } = req.body;\n  await User.create({ name, email, password });\nNever spread or forward req.body directly to database operations.",
    "references": ["https://owasp.org/Top10/A04_2021-Insecure_Design/"]
  },
  {
    "id": "a04_mass_assign_update_many",
    "title": "OWASP A04:2021 (Insecure Design): Mass Assignment — updateOne/updateMany with req.body",
    "description": "The full request body is passed to updateOne() or updateMany(). Attackers can inject MongoDB operators or unintended fields.",
    "pattern": "\\.update(?:One|Many)\\s*\\([^,)]+,\\s*req\\.body",
    "file_globs": ["**/*.js", "**/*.ts", "**/*.mjs", "**/*.cjs"],
    "severity": "high",
    "confidence": "high",
    "owasp": "A04",
    "cwe": "CWE-915",
    "recommendation": "Only update specific, validated fields. Never pass req.body directly as the update document.",
    "references": ["https://owasp.org/Top10/A04_2021-Insecure_Design/"]
  },
  {
    "id": "a04_mass_assign_sequelize",
    "title": "OWASP A04:2021 (Insecure Design): Mass Assignment — Sequelize create/update with req.body",
    "description": "The full request body is passed to a Sequelize create() or update() call. Attackers can set model fields that should be server-controlled (e.g., role, isAdmin, createdAt).",
    "pattern": "\\.(?:create|update|build|upsert)\\s*\\(\\s*req\\.body",
    "file_globs": ["**/*.js", "**/*.ts", "**/*.mjs", "**/*.cjs"],
    "severity": "high",
    "confidence": "medium",
    "owasp": "A04",
    "cwe": "CWE-915",
    "recommendation": "Use explicit field extraction or Sequelize's fields option:\n  await User.create({ name, email }, { fields: ['name', 'email'] });",
    "references": ["https://owasp.org/Top10/A04_2021-Insecure_Design/"]
  },
  {
    "id": "a07_logout_via_get",
    "title": "OWASP A07:2021 (Identification and Authentication Failures): State-Changing Operation via HTTP GET",
    "description": "A logout, delete, or sign-out route is registered as a GET handler. GET requests must be idempotent and side-effect-free. Using GET for state-changing operations enables CSRF attacks via simple image tags or link prefetching.",
    "pattern": "(?:router|app)\\.get\\s*\\(\\s*['\"`][^'\"`,]*(?:logout|signout|sign-out|sign_out|delete|remove|destroy|deactivate|ban|kick|revoke)[^'\"`,]*['\"`]",
    "file_globs": ["**/*.js", "**/*.ts", "**/*.mjs", "**/*.cjs"],
    "ignore_case": true,
    "severity": "medium",
    "confidence": "high",
    "owasp": "A07",
    "cwe": "CWE-352",
    "recommendation": "Use POST (or DELETE) for all state-changing operations, and protect them with CSRF tokens or SameSite cookies:\n  router.post('/logout', csrfProtection, logoutHandler);\nGET must never cause server-side state changes.",
    "references": [
      "https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html"
    ]
  },
  {
    "id": "a02_localstorage_token",
    "title": "OWASP A02:2021 (Cryptographic Failures): Sensitive Data Stored in localStorage",
    "description": "A token, password, or credential is being written to localStorage. localStorage is accessible to any JavaScript running on the page — a single XSS vulnerability allows an attacker to exfiltrate all stored tokens.",
    "pattern": "localStorage\\.setItem\\s*\\(\\s*['\"`][^'\"`,]*(?:token|password|passwd|secret|auth|session|credential|apikey|api_key|jwt|access_key)[^'\"`,]*['\"`]",
    "file_globs": ["**/*.js", "**/*.ts", "**/*.jsx", "**/*.tsx", "**/*.mjs", "**/*.vue", "**/*.svelte"],
    "ignore_case": true,
    "severity": "high",
    "confidence": "high",
    "owasp": "A02",
    "cwe": "CWE-312",
    "recommendation": "Store authentication tokens in HttpOnly, Secure, SameSite=Strict cookies instead of localStorage:\n  - Cookies with HttpOnly prevent JavaScript access entirely.\n  - If client-side access is required, use sessionStorage with short expiry.\n  - Never store long-lived tokens in any Web Storage API.",
    "references": [
      "https://cheatsheetseries.owasp.org/cheatsheets/HTML5_Security_Cheat_Sheet.html#local-storage"
    ]
  },
  {
    "id": "a02_sessionstorage_token",
    "title": "OWASP A02:2021 (Cryptographic Failures): Sensitive Data Stored in sessionStorage",
    "description": "A token or credential is being written to sessionStorage. While sessionStorage is scoped to the tab, it is still accessible to any JavaScript on the page and vulnerable to XSS exfiltration.",
    "pattern": "sessionStorage\\.setItem\\s*\\(\\s*['\"`][^'\"`,]*(?:token|password|passwd|secret|auth|credential|apikey|jwt|access_key)[^'\"`,]*['\"`]",
    "file_globs": ["**/*.js", "**/*.ts", "**/*.jsx", "**/*.tsx", "**/*.mjs", "**/*.vue", "**/*.svelte"],
    "ignore_case": true,
    "severity": "medium",
    "confidence": "high",
    "owasp": "A02",
    "cwe": "CWE-312",
    "recommendation": "Prefer HttpOnly Secure cookies for auth tokens. If sessionStorage must be used, ensure the application has a strong CSP and no XSS vectors.",
    "references": [
      "https://cheatsheetseries.owasp.org/cheatsheets/HTML5_Security_Cheat_Sheet.html#session-storage"
    ]
  },
  {
    "id": "a09_error_message_leaked",
    "title": "OWASP A09:2021 (Security Logging and Monitoring Failures): Internal Error Message Leaked to Client",
    "description": "An internal error message (err.message or error.message) is included directly in the HTTP response. This reveals stack traces, database schemas, file paths, or internal logic to attackers, aiding reconnaissance.",
    "pattern": "(?:message|error|err)\\s*:\\s*(?:err|error|e)\\.message",
    "file_globs": ["**/*.js", "**/*.ts", "**/*.mjs", "**/*.cjs"],
    "severity": "medium",
    "confidence": "high",
    "owasp": "A09",
    "cwe": "CWE-209",
    "recommendation": "Return a generic error message to clients and log the real error server-side:\n  // Bad\n  res.status(500).json({ message: err.message });\n  // Good\n  console.error(err);\n  res.status(500).json({ message: 'An internal error occurred.' });",
    "references": [
      "https://cheatsheetseries.owasp.org/cheatsheets/Error_Handling_Cheat_Sheet.html"
    ]
  },
  {
    "id": "a03_eval_js",
    "title": "OWASP A03:2021 (Injection): eval() Usage — Potential Code Injection",
    "description": "eval() executes an arbitrary string as JavaScript code. If any part of the evaluated string is derived from user input, this is a code injection vulnerability. Even without direct user input, eval() is unpredictable and obscures code logic.",
    "pattern": "\\beval\\s*\\(",
    "file_globs": ["**/*.js", "**/*.ts", "**/*.jsx", "**/*.tsx", "**/*.mjs", "**/*.cjs"],
    "skip_if_line_matches": "//.*eval|/\\*.*eval|evalua|evaluate|evaluating",
    "severity": "high",
    "confidence": "medium",
    "owasp": "A03",
    "cwe": "CWE-95",
    "recommendation": "Replace eval() with safer alternatives:\n  - JSON.parse() for parsing JSON strings\n  - Function constructors for dynamic logic (with extreme caution)\n  - Refactor to eliminate the need for dynamic code execution entirely",
    "references": [
      "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval#never_use_eval!"
    ]
  },
  {
    "id": "a03_innerhtml_assignment",
    "title": "OWASP A03:2021 (Injection): innerHTML Assignment with Dynamic Content — XSS Risk",
    "description": "innerHTML is being assigned a value that is not a string literal. If the assigned value contains any user-controlled input, this is a stored or reflected XSS vulnerability. Browsers will parse and execute any script tags in the assigned HTML.",
    "pattern": "\\.innerHTML\\s*=\\s*(?!['\"`])",
    "file_globs": ["**/*.js", "**/*.ts", "**/*.jsx", "**/*.tsx", "**/*.mjs", "**/*.html"],
    "skip_if_line_matches": "//.*innerHTML|sanitize|DOMPurify|escapeHtml|encodeHTML",
    "severity": "high",
    "confidence": "medium",
    "owasp": "A03",
    "cwe": "CWE-79",
    "recommendation": "Avoid innerHTML with dynamic values. Alternatives:\n  - Use textContent instead of innerHTML for plain text\n  - Sanitize with DOMPurify before assigning: el.innerHTML = DOMPurify.sanitize(userInput)\n  - Use createElement/appendChild to build DOM nodes safely",
    "references": [
      "https://cheatsheetseries.owasp.org/cheatsheets/DOM_based_XSS_Prevention_Cheat_Sheet.html"
    ]
  },
  {
    "id": "a03_document_write",
    "title": "OWASP A03:2021 (Injection): document.write() — XSS Risk",
    "description": "document.write() inserts HTML directly into the document stream. Any user-controlled input passed to document.write() results in XSS. It is also deprecated in strict mode and blocks the HTML parser.",
    "pattern": "\\bdocument\\.write\\s*\\(",
    "file_globs": ["**/*.js", "**/*.ts", "**/*.jsx", "**/*.tsx", "**/*.mjs", "**/*.html"],
    "skip_if_line_matches": "//.*document\\.write",
    "severity": "medium",
    "confidence": "medium",
    "owasp": "A03",
    "cwe": "CWE-79",
    "recommendation": "Replace document.write() with DOM manipulation APIs:\n  document.getElementById('target').textContent = value; // for text\n  document.getElementById('target').appendChild(node);  // for elements",
    "references": [
      "https://developer.mozilla.org/en-US/docs/Web/API/Document/write"
    ]
  },
  {
    "id": "a05_cors_wildcard",
    "title": "OWASP A05:2021 (Security Misconfiguration): CORS Wildcard Origin",
    "description": "The CORS configuration allows requests from any origin (*). Combined with credentials (cookies, auth headers), this allows any website to make authenticated requests to your API on behalf of users.",
    "pattern": "origin\\s*:\\s*['\"`]\\*['\"`]",
    "file_globs": ["**/*.js", "**/*.ts", "**/*.mjs", "**/*.cjs", "**/*.json"],
    "severity": "high",
    "confidence": "high",
    "owasp": "A05",
    "cwe": "CWE-942",
    "recommendation": "Specify an explicit allowlist of trusted origins:\n  cors({ origin: ['https://app.example.com', 'https://admin.example.com'] })\nNever use '*' in production, especially if credentials are sent.",
    "references": [
      "https://cheatsheetseries.owasp.org/cheatsheets/CORS_Security_Cheat_Sheet.html"
    ]
  },
  {
    "id": "a05_ssl_reject_unauthorized_false",
    "title": "OWASP A05:2021 (Security Misconfiguration): TLS Certificate Verification Disabled",
    "description": "rejectUnauthorized: false disables TLS certificate validation. All HTTPS connections made with this option are vulnerable to man-in-the-middle attacks — the server's identity is never verified.",
    "pattern": "rejectUnauthorized\\s*:\\s*false",
    "file_globs": ["**/*.js", "**/*.ts", "**/*.mjs", "**/*.cjs"],
    "severity": "high",
    "confidence": "high",
    "owasp": "A05",
    "cwe": "CWE-295",
    "recommendation": "Remove rejectUnauthorized: false. If connecting to a server with a self-signed certificate in development, add the CA certificate instead:\n  const agent = new https.Agent({ ca: fs.readFileSync('ca.crt') });\nNever disable certificate verification in production.",
    "references": [
      "https://nodejs.org/api/tls.html#tlscreatesecurecontextoptions"
    ]
  },
  {
    "id": "a07_jwt_long_expiry",
    "title": "OWASP A07:2021 (Identification and Authentication Failures): Excessively Long JWT Expiry",
    "description": "The JWT token is configured with a very long expiry (7 days or more). Long-lived tokens increase the window of opportunity for token theft and replay attacks. There is no way to invalidate a JWT before it expires without maintaining a denylist.",
    "pattern": "expiresIn\\s*:\\s*['\"`](?:[7-9]d|[1-9]\\d+d|[7-9]D|[1-9]\\d+D)['\"`]",
    "file_globs": ["**/*.js", "**/*.ts", "**/*.mjs", "**/*.cjs"],
    "severity": "medium",
    "confidence": "high",
    "owasp": "A07",
    "cwe": "CWE-613",
    "recommendation": "Keep JWT expiry short (15 minutes to 1 hour for access tokens). Use refresh tokens for longer sessions:\n  accessToken: expiresIn '15m'\n  refreshToken: expiresIn '7d' (stored securely, rotated on use)\nImplement a token revocation/denylist mechanism for logout.",
    "references": [
      "https://cheatsheetseries.owasp.org/cheatsheets/JSON_Web_Token_for_Java_Cheat_Sheet.html"
    ]
  },
  {
    "id": "a07_cookie_missing_flags",
    "title": "OWASP A07:2021 (Identification and Authentication Failures): Cookie Set Without Security Flags",
    "description": "A cookie is being set without the 'secure' flag. Without 'secure', the cookie will be transmitted over plain HTTP connections, making it vulnerable to interception by network attackers.",
    "pattern": "res\\.cookie\\s*\\([^)]+\\)",
    "file_globs": ["**/*.js", "**/*.ts", "**/*.mjs", "**/*.cjs"],
    "skip_if_line_matches": "secure\\s*:\\s*true|httpOnly\\s*:\\s*true",
    "severity": "medium",
    "confidence": "medium",
    "owasp": "A07",
    "cwe": "CWE-614",
    "recommendation": "Always set security flags on cookies:\n  res.cookie('token', value, {\n    httpOnly: true,   // prevent JS access\n    secure: true,     // HTTPS only\n    sameSite: 'strict' // CSRF protection\n  });",
    "references": [
      "https://cheatsheetseries.owasp.org/cheatsheets/Session_Management_Cheat_Sheet.html#cookies"
    ]
  },
  {
    "id": "a03_os_system_python",
    "title": "OWASP A03:2021 (Injection): os.system() — Command Injection Risk",
    "description": "os.system() passes the command string to the shell. If any part of the string is derived from user input, this is a command injection vulnerability allowing attackers to execute arbitrary system commands.",
    "pattern": "\\bos\\.system\\s*\\(",
    "file_globs": ["**/*.py"],
    "severity": "high",
    "confidence": "medium",
    "owasp": "A03",
    "cwe": "CWE-78",
    "recommendation": "Use subprocess.run() with a list of arguments (no shell=True) to avoid shell injection:\n  import subprocess\n  subprocess.run(['ls', '-la', path], check=True)  # safe\n  # Never: os.system(f'ls {user_input}')",
    "references": [
      "https://cheatsheetseries.owasp.org/cheatsheets/OS_Command_Injection_Defense_Cheat_Sheet.html"
    ]
  },
  {
    "id": "a03_subprocess_shell_true",
    "title": "OWASP A03:2021 (Injection): subprocess with shell=True — Command Injection Risk",
    "description": "subprocess is called with shell=True, which passes the command through the system shell. Any user input incorporated into the command string enables command injection.",
    "pattern": "subprocess\\.\\w+\\s*\\([^)]*shell\\s*=\\s*True",
    "file_globs": ["**/*.py"],
    "severity": "high",
    "confidence": "high",
    "owasp": "A03",
    "cwe": "CWE-78",
    "recommendation": "Remove shell=True and pass the command as a list:\n  # Unsafe\n  subprocess.run(f'echo {user_input}', shell=True)\n  # Safe\n  subprocess.run(['echo', user_input])  # user_input is a separate argument",
    "references": [
      "https://docs.python.org/3/library/subprocess.html#security-considerations"
    ]
  },
  {
    "id": "a08_pickle_loads",
    "title": "OWASP A08:2021 (Software and Data Integrity Failures): pickle.load/loads — Arbitrary Code Execution",
    "description": "Deserializing untrusted data with pickle can execute arbitrary Python code. Any data source that could be influenced by an attacker (files, network data, user uploads, Redis, databases) is a potential vector.",
    "pattern": "\\bpickle\\.loads?\\s*\\(",
    "file_globs": ["**/*.py"],
    "skip_if_line_matches": "#.*pickle|test.*pickle|pickle.*test",
    "severity": "critical",
    "confidence": "medium",
    "owasp": "A08",
    "cwe": "CWE-502",
    "recommendation": "Replace pickle with a safe serialization format:\n  - json.dumps/loads for simple data structures\n  - msgpack for binary efficiency\n  - If pickle is unavoidable, restrict to trusted internal data and verify with HMAC before deserializing",
    "references": [
      "https://docs.python.org/3/library/pickle.html#pickle-restrict",
      "https://owasp.org/Top10/A08_2021-Software_and_Data_Integrity_Failures/"
    ]
  },
  {
    "id": "a08_yaml_load_unsafe",
    "title": "OWASP A08:2021 (Software and Data Integrity Failures): yaml.load() Without Safe Loader",
    "description": "yaml.load() without an explicit Loader defaults to the full YAML loader, which can construct arbitrary Python objects. Parsing attacker-controlled YAML can lead to remote code execution.",
    "pattern": "\\byaml\\.load\\s*\\(",
    "file_globs": ["**/*.py"],
    "skip_if_line_matches": "yaml\\.safe_load|Loader\\s*=|SafeLoader|BaseLoader",
    "severity": "high",
    "confidence": "high",
    "owasp": "A08",
    "cwe": "CWE-502",
    "recommendation": "Replace yaml.load() with yaml.safe_load():\n  # Unsafe\n  data = yaml.load(stream)\n  # Safe\n  data = yaml.safe_load(stream)\nIf you need custom objects, use yaml.load(stream, Loader=yaml.BaseLoader) and validate explicitly.",
    "references": [
      "https://pyyaml.org/wiki/PyYAMLDocumentation"
    ]
  },
  {
    "id": "a02_ssl_verify_false_python",
    "title": "OWASP A02:2021 (Cryptographic Failures): SSL Certificate Verification Disabled",
    "description": "SSL/TLS certificate verification is disabled (verify=False). All HTTPS connections made with this setting are vulnerable to man-in-the-middle attacks — the server's identity is never verified.",
    "pattern": "\\bverify\\s*=\\s*False",
    "file_globs": ["**/*.py"],
    "severity": "high",
    "confidence": "high",
    "owasp": "A02",
    "cwe": "CWE-295",
    "recommendation": "Remove verify=False. If connecting to a server with a custom CA in development:\n  requests.get(url, verify='/path/to/ca-bundle.crt')\nNever disable certificate verification in production environments.",
    "references": [
      "https://requests.readthedocs.io/en/latest/user/advanced/#ssl-cert-verification"
    ]
  },
  {
    "id": "a05_django_debug_true",
    "title": "OWASP A05:2021 (Security Misconfiguration): Django DEBUG=True in Settings",
    "description": "Django's DEBUG=True mode exposes full stack traces, local variables, settings values, and SQL queries to anyone who triggers an error. This should never be enabled in production.",
    "pattern": "^\\s*DEBUG\\s*=\\s*True",
    "file_globs": ["**/*.py"],
    "ignore_case": false,
    "severity": "high",
    "confidence": "medium",
    "owasp": "A05",
    "cwe": "CWE-94",
    "recommendation": "Set DEBUG = False in production settings:\n  DEBUG = os.environ.get('DEBUG', 'False') == 'True'\nAlternatively use separate settings files (settings/production.py) that always have DEBUG=False.",
    "references": [
      "https://docs.djangoproject.com/en/stable/ref/settings/#debug"
    ]
  },
  {
    "id": "a03_eval_python",
    "title": "OWASP A03:2021 (Injection): eval() in Python — Code Injection Risk",
    "description": "Python's eval() executes an arbitrary expression string. If any part of the evaluated string is derived from user input, this is a code injection vulnerability allowing arbitrary code execution.",
    "pattern": "\\beval\\s*\\(",
    "file_globs": ["**/*.py"],
    "skip_if_line_matches": "#.*eval|evaluate|evaluat",
    "severity": "high",
    "confidence": "medium",
    "owasp": "A03",
    "cwe": "CWE-95",
    "recommendation": "Eliminate eval() entirely:\n  - Parse numbers/booleans with int(), float(), bool()\n  - Parse JSON with json.loads()\n  - For math expressions, use ast.literal_eval() (safe subset only)\n  - For configuration, use proper config parsers",
    "references": [
      "https://docs.python.org/3/library/functions.html#eval"
    ]
  },
  {
    "id": "a02_hashlib_weak_algo",
    "title": "OWASP A02:2021 (Cryptographic Failures): Weak Hash Algorithm (MD5/SHA-1)",
    "description": "MD5 and SHA-1 are cryptographically broken and must not be used for password hashing or any security-sensitive context. MD5 collisions can be generated in seconds; SHA-1 is practically broken against determined attackers.",
    "pattern": "hashlib\\.(md5|sha1)\\s*\\(",
    "file_globs": ["**/*.py"],
    "ignore_case": true,
    "skip_if_line_matches": "#.*non.?security|checksum|integrity|etag|dedup|cache_key|content.?hash",
    "severity": "medium",
    "confidence": "medium",
    "owasp": "A02",
    "cwe": "CWE-327",
    "recommendation": "For passwords: use bcrypt, scrypt, or argon2 (never a raw hash).\nFor data integrity: use SHA-256 or SHA-3.\nExample:\n  import bcrypt\n  hashed = bcrypt.hashpw(password.encode(), bcrypt.gensalt())",
    "references": [
      "https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html"
    ]
  },
  {
    "id": "a02_hardcoded_mongo_uri_no_auth",
    "title": "OWASP A02:2021 (Cryptographic Failures): MongoDB Connection Without Authentication or TLS",
    "description": "A MongoDB connection string using the plain mongodb:// scheme is used. Without TLS (use mongodb+srv:// or explicit ssl option), the connection is unencrypted. If the URI lacks credentials, the database may be unauthenticated.",
    "pattern": "mongoose\\.connect\\s*\\(\\s*['\"`]mongodb://",
    "file_globs": ["**/*.js", "**/*.ts", "**/*.mjs", "**/*.cjs"],
    "skip_if_line_matches": "ssl|tls|authSource|process\\.env",
    "severity": "medium",
    "confidence": "medium",
    "owasp": "A02",
    "cwe": "CWE-311",
    "recommendation": "Use the mongodb+srv:// scheme (which enforces TLS) or pass SSL options explicitly:\n  mongoose.connect(process.env.MONGO_URI, {\n    tls: true,\n    tlsCAFile: '/path/to/ca.pem'\n  });\nAlways load connection strings from environment variables, never hardcode them.",
    "references": [
      "https://www.mongodb.com/docs/manual/tutorial/configure-ssl/"
    ]
  },
  {
    "id": "a03_sql_fstring_python",
    "title": "OWASP A03:2021 (Injection): SQL Query Built with f-string or % Formatting",
    "description": "A SQL query is constructed using Python f-strings or % formatting. Any user-controlled variable interpolated into the query string is a SQL injection vulnerability.",
    "pattern": "\\.execute\\s*\\(\\s*f['\"]|cursor\\.execute\\s*\\(\\s*['\"][^'\"]*%\\s*[\\w(]",
    "file_globs": ["**/*.py"],
    "severity": "critical",
    "confidence": "high",
    "owasp": "A03",
    "cwe": "CWE-89",
    "recommendation": "Always use parameterized queries:\n  # Unsafe\n  cursor.execute(f\"SELECT * FROM users WHERE id = {user_id}\")\n  # Safe\n  cursor.execute(\"SELECT * FROM users WHERE id = %s\", (user_id,))",
    "references": [
      "https://cheatsheetseries.owasp.org/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.html"
    ]
  },
  {
    "id": "a03_nosql_injection_js",
    "title": "OWASP A03:2021 (Injection): NoSQL Injection — Dynamic Object Key from User Input",
    "description": "A MongoDB filter object is constructed using a dynamic key derived from user input (e.g., req.query or req.params). Attackers can inject MongoDB operators like $where, $regex, or $gt to bypass filters or exfiltrate data.",
    "pattern": "\\{\\s*\\[(?:req\\.(?:query|params|body)\\.[\\w]+|`[^`]*\\$\\{[^}]*req\\.[^}]*\\}[^`]*`)\\]",
    "file_globs": ["**/*.js", "**/*.ts", "**/*.mjs", "**/*.cjs"],
    "severity": "high",
    "confidence": "high",
    "owasp": "A03",
    "cwe": "CWE-943",
    "recommendation": "Never use user input as a MongoDB object key. Validate and allowlist the key:\n  const ALLOWED_FIELDS = ['gender', 'category', 'brand'];\n  if (!ALLOWED_FIELDS.includes(req.query.field)) return res.status(400).send('Invalid field');\n  const filter = { [req.query.field]: req.query.value };",
    "references": [
      "https://cheatsheetseries.owasp.org/cheatsheets/Injection_Prevention_Cheat_Sheet.html"
    ]
  },
  {
    "id": "a05_nextjs_missing_security_headers",
    "title": "OWASP A05:2021 (Security Misconfiguration): No Security Headers Configured in next.config",
    "description": "The Next.js config file does not define a headers() function. Without explicit security headers (Content-Security-Policy, X-Frame-Options, X-Content-Type-Options, HSTS), the application is missing important browser-enforced protections.",
    "pattern": "^(?!.*\\bheaders\\s*\\().*$",
    "file_globs": ["**/next.config.js", "**/next.config.mjs", "**/next.config.ts"],
    "multiline": false,
    "severity": "medium",
    "confidence": "low",
    "owasp": "A05",
    "cwe": "CWE-693",
    "recommendation": "Add a headers() function to next.config.js:\n  async headers() {\n    return [{\n      source: '/(.*)',\n      headers: [\n        { key: 'X-Frame-Options', value: 'DENY' },\n        { key: 'X-Content-Type-Options', value: 'nosniff' },\n        { key: 'Referrer-Policy', value: 'strict-origin-when-cross-origin' },\n        { key: 'Content-Security-Policy', value: \"default-src 'self'\" },\n      ]\n    }];\n  }",
    "references": [
      "https://nextjs.org/docs/app/api-reference/next-config-js/headers"
    ]
  },
  {
    "id": "a02_hardcoded_secret_env_file",
    "title": "OWASP A02:2021 (Cryptographic Failures): Hardcoded Secret in .env File Committed to Repo",
    "description": "A .env file containing secrets appears to be committed to the repository. .env files should never be committed as they contain credentials that will be permanently stored in git history.",
    "pattern": "(?:PASSWORD|SECRET|TOKEN|KEY|CREDENTIALS|PRIVATE)\\s*=\\s*(?!\\$|<|your|changeme|placeholder|example|todo|xxx|dummy|sample|fake|test|none|null)[^\\s\"'`]{8,}",
    "file_globs": ["**/.env", "**/.env.local", "**/.env.production", "**/.env.staging"],
    "ignore_case": true,
    "severity": "critical",
    "confidence": "high",
    "owasp": "A02",
    "cwe": "CWE-798",
    "recommendation": "1. Remove the .env file from git tracking: git rm --cached .env\n2. Add .env to .gitignore immediately\n3. Rotate all exposed credentials\n4. Use .env.example with placeholder values for documentation\n5. Use a secrets manager (AWS Secrets Manager, Vault, Doppler) for production secrets",
    "references": [
      "https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html"
    ]
  },
  {
    "id": "a07_python_no_password_hashing",
    "title": "OWASP A07:2021 (Identification and Authentication Failures): Password Stored Without Proper Hashing",
    "description": "A password field is being set from request data without any indication of proper hashing. Storing plain-text or weakly-encoded passwords means any database breach exposes all user passwords.",
    "pattern": "(?:user|account|profile)\\.password\\s*=\\s*(?:req\\.body|request\\.data|data)\\.",
    "file_globs": ["**/*.py", "**/*.js", "**/*.ts"],
    "skip_if_line_matches": "hash|bcrypt|argon|scrypt|pbkdf|encrypt",
    "severity": "critical",
    "confidence": "medium",
    "owasp": "A07",
    "cwe": "CWE-256",
    "recommendation": "Always hash passwords before storing:\n  # Python\n  from passlib.context import CryptContext\n  pwd_context = CryptContext(schemes=['bcrypt'])\n  user.password = pwd_context.hash(request.data['password'])\n  # Node.js\n  const bcrypt = require('bcrypt');\n  user.password = await bcrypt.hash(req.body.password, 12);",
    "references": [
      "https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html"
    ]
  },
  {
    "id": "a01_idor_no_auth_check",
    "title": "OWASP A01:2021 (Broken Access Control): Route Handler Missing Authorization Check",
    "description": "An async route handler accesses req.params or req.query to find a resource but does not check req.user or any session/token to verify the requester is authorized to access that resource. This is a potential IDOR vulnerability.",
    "pattern": "async\\s+(?:function\\s+)?\\w*\\s*\\([^)]*req[^)]*\\)[^{]*\\{[^}]*req\\.params\\.[\\w]+[^}]*(?:find|get|update|delete|remove)[^}]*\\}",
    "file_globs": ["**/*.js", "**/*.ts", "**/*.mjs"],
    "skip_if_line_matches": "req\\.user|req\\.session|authenticate|authorize|isAuth|checkAuth|protect|guard",
    "multiline": true,
    "severity": "high",
    "confidence": "low",
    "owasp": "A01",
    "cwe": "CWE-639",
    "recommendation": "Add authorization checks before accessing resources by ID:\n  // Verify the resource belongs to the requesting user\n  const resource = await Model.findById(req.params.id);\n  if (!resource || resource.userId.toString() !== req.user.id) {\n    return res.status(403).json({ error: 'Forbidden' });\n  }",
    "references": [
      "https://cheatsheetseries.owasp.org/cheatsheets/Insecure_Direct_Object_Reference_Prevention_Cheat_Sheet.html"
    ]
  }
]
