{
  "dimension": "security",
  "prefix": "SEC",
  "description": "Rules for detecting security vulnerabilities including XSS, injection, and credential exposure",
  "rules": [
    {
      "id": "xss-innerHTML",
      "category": "xss-risk",
      "severity": "critical",
      "pattern": "innerHTML\\s*=|dangerouslySetInnerHTML",
      "patternType": "includes",
      "description": "Direct HTML injection via innerHTML or dangerouslySetInnerHTML can lead to XSS vulnerabilities",
      "recommendation": "Use textContent for plain text, or sanitize HTML input using a library like DOMPurify before injection",
      "fixExample": "// Before\nelement.innerHTML = userInput;\n<div dangerouslySetInnerHTML={{__html: data}} />\n\n// After\nelement.textContent = userInput;\n// or\nimport DOMPurify from 'dompurify';\nelement.innerHTML = DOMPurify.sanitize(userInput);"
    },
    {
      "id": "hardcoded-secret",
      "category": "hardcoded-secret",
      "severity": "critical",
      "pattern": "(?:password|secret|api[_-]?key|token|credential)\\s*[=:]\\s*['\"][^'\"]{8,}['\"]",
      "patternType": "regex",
      "caseInsensitive": true,
      "description": "Hardcoded credentials detected in source code. This is a security risk if code is exposed",
      "recommendation": "Use environment variables, secret management services, or configuration files excluded from version control",
      "fixExample": "// Before\nconst apiKey = 'sk-1234567890abcdef';\n\n// After\nconst apiKey = process.env.API_KEY;\n// or\nconst apiKey = await getSecretFromVault('api-key');"
    },
    {
      "id": "sql-injection",
      "category": "injection",
      "severity": "critical",
      "pattern": "query\\s*\\(\\s*[`'\"].*\\$\\{|execute\\s*\\(\\s*[`'\"].*\\+",
      "patternType": "regex",
      "description": "String concatenation or template literals in SQL queries can lead to SQL injection",
      "recommendation": "Use parameterized queries or prepared statements with placeholders",
      "fixExample": "// Before\ndb.query(`SELECT * FROM users WHERE id = ${userId}`);\n\n// After\ndb.query('SELECT * FROM users WHERE id = ?', [userId]);\n// or\ndb.query('SELECT * FROM users WHERE id = $1', [userId]);"
    },
    {
      "id": "command-injection",
      "category": "injection",
      "severity": "critical",
      "pattern": "exec\\s*\\(|execSync\\s*\\(|spawn\\s*\\([^,]*\\+|child_process",
      "patternType": "regex",
      "description": "Command execution with user input can lead to command injection attacks",
      "recommendation": "Validate and sanitize input, use parameterized commands, or avoid shell execution entirely",
      "fixExample": "// Before\nexec(`ls ${userInput}`);\n\n// After\nexecFile('ls', [sanitizedInput], options);\n// or use spawn with {shell: false}"
    },
    {
      "id": "insecure-random",
      "category": "cryptography",
      "severity": "high",
      "pattern": "Math\\.random\\(\\)",
      "patternType": "includes",
      "description": "Math.random() is not cryptographically secure and should not be used for security-sensitive operations",
      "recommendation": "Use crypto.randomBytes() or crypto.getRandomValues() for security-critical random generation",
      "fixExample": "// Before\nconst token = Math.random().toString(36);\n\n// After\nimport crypto from 'crypto';\nconst token = crypto.randomBytes(32).toString('hex');"
    }
  ]
}
