{
  "rule": {
    "id": "S022",
    "name": "Escape data properly based on output context",
    "description": "Ensure data is properly escaped or sanitized based on the output context (HTML, JavaScript, CSS, URL) to prevent Cross-Site Scripting (XSS) attacks. Different contexts require different escaping methods.",
    "category": "security",
    "severity": "error",
    "languages": ["typescript", "javascript"],
    "frameworks": ["express", "nestjs", "react", "vue", "angular", "node"],
    "version": "1.0.0",
    "status": "stable",
    "tags": ["security", "xss", "escaping", "sanitization", "owasp", "injection"],
    "references": [
      "https://owasp.org/www-community/attacks/xss/",
      "https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html",
      "https://cheatsheetseries.owasp.org/cheatsheets/DOM_based_XSS_Prevention_Cheat_Sheet.html",
      "https://portswigger.net/web-security/cross-site-scripting",
      "https://cwe.mitre.org/data/definitions/79.html"
    ]
  },
  "configuration": {
    "contexts": {
      "html": {
        "dangerousMethods": [
          "innerHTML",
          "outerHTML",
          "insertAdjacentHTML",
          "document.write",
          "document.writeln",
          "v-html",
          "dangerouslySetInnerHTML"
        ],
        "requireEscaping": true,
        "severity": "error"
      },
      "javascript": {
        "dangerousMethods": [
          "eval",
          "Function",
          "setTimeout",
          "setInterval",
          "execScript"
        ],
        "requireEscaping": true,
        "severity": "error"
      },
      "url": {
        "dangerousMethods": [
          "location.href",
          "window.location",
          "location.assign",
          "location.replace",
          "window.open"
        ],
        "requireValidation": true,
        "severity": "warning"
      },
      "attribute": {
        "dangerousAttributes": [
          "onclick",
          "onload",
          "onerror",
          "onmouseover",
          "href",
          "src"
        ],
        "requireEscaping": true,
        "severity": "error"
      }
    },
    "userInputSources": [
      "req.body",
      "req.query",
      "req.params",
      "request.body",
      "request.query",
      "request.params",
      "localStorage",
      "sessionStorage",
      "window.location",
      "location.search",
      "location.hash",
      "URLSearchParams",
      "document.cookie",
      "window.name",
      "postMessage"
    ],
    "safeEscapingFunctions": [
      "escape",
      "escapeHtml",
      "sanitize",
      "DOMPurify.sanitize",
      "textContent",
      "innerText",
      "setAttribute",
      "encodeURIComponent",
      "encodeURI",
      "validator.escape",
      "xss.filterXSS"
    ],
    "safeFrameworkMethods": {
      "react": [
        "textContent",
        "children",
        "{variable}"
      ],
      "vue": [
        "{{ variable }}",
        "v-text"
      ],
      "angular": [
        "{{ variable }}",
        "[textContent]"
      ]
    }
  },
  "examples": {
    "violations": [
      {
        "description": "Unescaped user input in innerHTML",
        "code": "element.innerHTML = userInput;",
        "context": "html"
      },
      {
        "description": "User input in eval without validation",
        "code": "eval(req.query.code);",
        "context": "javascript"
      },
      {
        "description": "Unvalidated URL from user input",
        "code": "window.location = req.query.redirect;",
        "context": "url"
      },
      {
        "description": "React dangerouslySetInnerHTML without sanitization",
        "code": "<div dangerouslySetInnerHTML={{__html: userInput}} />",
        "context": "html"
      },
      {
        "description": "Vue v-html directive with user input",
        "code": "<div v-html=\"userInput\"></div>",
        "context": "html"
      },
      {
        "description": "Dynamic event handler with user input",
        "code": "element.setAttribute('onclick', userInput);",
        "context": "attribute"
      }
    ],
    "fixes": [
      {
        "description": "Use textContent instead of innerHTML",
        "code": "element.textContent = userInput;",
        "context": "html"
      },
      {
        "description": "Sanitize HTML with DOMPurify",
        "code": "element.innerHTML = DOMPurify.sanitize(userInput);",
        "context": "html"
      },
      {
        "description": "Never use eval with user input",
        "code": "// Avoid eval entirely, use JSON.parse or safe alternatives",
        "context": "javascript"
      },
      {
        "description": "Validate and whitelist URLs",
        "code": "const allowedHosts = ['example.com'];\nconst url = new URL(req.query.redirect);\nif (allowedHosts.includes(url.hostname)) {\n  window.location = url.href;\n}",
        "context": "url"
      },
      {
        "description": "React with proper sanitization",
        "code": "<div dangerouslySetInnerHTML={{__html: DOMPurify.sanitize(userInput)}} />",
        "context": "html"
      },
      {
        "description": "Vue using v-text for safe output",
        "code": "<div v-text=\"userInput\"></div>",
        "context": "html"
      }
    ]
  },
  "testing": {
    "testCases": [
      {
        "name": "innerHTML_with_user_input",
        "type": "violation",
        "description": "Using innerHTML with unsanitized user input"
      },
      {
        "name": "eval_with_user_input",
        "type": "violation",
        "description": "Using eval with user input"
      },
      {
        "name": "location_with_user_input",
        "type": "violation",
        "description": "Setting location with unvalidated user input"
      },
      {
        "name": "textContent_safe_output",
        "type": "clean",
        "description": "Using textContent for safe output"
      },
      {
        "name": "dompurify_sanitization",
        "type": "clean",
        "description": "Using DOMPurify to sanitize HTML"
      },
      {
        "name": "url_validation",
        "type": "clean",
        "description": "Validating URLs before redirect"
      }
    ]
  },
  "performance": {
    "complexity": "O(n)",
    "description": "Linear complexity based on number of DOM manipulation and output operations in the source code"
  },
  "owaspMapping": {
    "category": "A03:2021 – Injection",
    "subcategories": [
      "A07:2021 – Identification and Authentication Failures"
    ],
    "cweId": "CWE-79",
    "description": "Validates that all output is properly escaped or sanitized based on context to prevent XSS attacks"
  }
}
