{"id":"CVE-2026-33979","aliases":["EUVD-2026-16876","GHSA-3843-rr4g-m8jq"],"status":"published","title":"Express XSS Sanitizer: allowedTags/allowedAttributes bypass leads to permissive sanitization (XSS risk)","description":"Express XSS Sanitizer is Express 4.x and 5.x middleware which sanitizes user input data (in req.body, req.query, req.headers and req.params) to prevent Cross Site Scripting (XSS) attack. A vulnerability has been identified in versions prior to 2.0.2 where restrictive sanitization configurations are silently ignored. In version 2.0.2, the validation logic has been updated to respect explicitly provided empty configurations. Now, if allowedTags or allowedAttributes are provided (even if empty), they are passed directly to sanitize-html without being overridden.","severity":{"version":"3.1","score":8.2,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:H/A:N","level":"high","assessor":"cna","from":"cve"},"epss":{"day":"2026-11-09","score":0.00389,"percentile":0.33288,"model":"v2026.06.15"},"facts":{"in_kev":false,"known_exploited":false,"public_exploit":false,"fix_available":true},"cwes":["CWE-183","CWE-79"],"published":"2026-03-27T17:56:45Z","modified":"2026-10-28T02:31:04Z","fixes":[{"ecosystem":"npm","package":"express-xss-sanitizer","fixed_in":["2.0.2"],"sources":["ghsa","osv"]}],"affected":[{"source":"ghsa","ecosystem":"npm","package":"express-xss-sanitizer","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"2.0.2"}]}]},{"source":"osv","ecosystem":"npm","package":"express-xss-sanitizer","ranges":[{"type":"SEMVER","events":[{"introduced":"0"},{"fixed":"2.0.2"}]}]}],"products":[{"vendor":"ahmedadelfahim","product":"express-xss-sanitizer"},{"vendor":"express_xss_sanitizer_project","product":"express_xss_sanitizer"}],"references":[{"url":"https://github.com/AhmedAdelFahim/express-xss-sanitizer/security/advisories/GHSA-3843-rr4g-m8jq","tags":["x_refsource_CONFIRM","Exploit","Mitigation","Vendor Advisory","advisory","web"]},{"url":"https://github.com/AhmedAdelFahim/express-xss-sanitizer/commit/5623009ef11dcf095c163a38dea07b9cc22ad19f","tags":["x_refsource_MISC","Patch","fix","web"]},{"url":"https://github.com/AhmedAdelFahim/express-xss-sanitizer/releases/tag/v2.0.2","tags":["x_refsource_MISC","Product","Release Notes","web"]},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-33979","tags":["advisory"]},{"url":"https://github.com/advisories/GHSA-3843-rr4g-m8jq"},{"url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/33xxx/CVE-2026-33979.json","tags":["advisory"]},{"url":"https://github.com/AhmedAdelFahim/express-xss-sanitizer","tags":["package"]}],"sources":{"cve":[{"id":"CVE-2026-33979","title":"Express XSS Sanitizer: allowedTags/allowedAttributes bypass leads to permissive sanitization (XSS risk)","description":"Express XSS Sanitizer is Express 4.x and 5.x middleware which sanitizes user input data (in req.body, req.query, req.headers and req.params) to prevent Cross Site Scripting (XSS) attack. A vulnerability has been identified in versions prior to 2.0.2 where restrictive sanitization configurations are silently ignored. In version 2.0.2, the validation logic has been updated to respect explicitly provided empty configurations. Now, if allowedTags or allowedAttributes are provided (even if empty), they are passed directly to sanitize-html without being overridden.","status":"published","published":"2026-03-27T21:29:19.759Z","modified":"2026-03-31T14:29:43.694Z","cvss":[{"version":"3.1","score":8.2,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:H/A:N","level":"high","assessor":"cna"}],"cwes":["CWE-183","CWE-79"],"updated_at":"2026-11-02T14:20:08.009733Z"}],"euvd":[{"id":"EUVD-2026-16876","description":"Express XSS Sanitizer is Express 4.x and 5.x middleware which sanitizes user input data (in req.body, req.query, req.headers and req.params) to prevent Cross Site Scripting (XSS) attack. A vulnerability has been identified in versions prior to 2.0.2 where restrictive sanitization configurations are silently ignored. In version 2.0.2, the validation logic has been updated to respect explicitly provided empty configurations. Now, if allowedTags or allowedAttributes are provided (even if empty), they are passed directly to sanitize-html without being overridden.","status":"published","published":"2026-03-27T21:29:19Z","modified":"2026-03-31T14:29:43Z","cvss":[{"version":"3.1","score":8.2,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:H/A:N","level":"high"}],"updated_at":"2026-11-02T19:25:24.891983Z"}],"ghsa":[{"id":"GHSA-3843-rr4g-m8jq","title":"Express XSS Sanitizer: allowedTags/allowedAttributes bypass leads to permissive sanitization (XSS risk)","description":"## Description\nA vulnerability has been identified in express-xss-sanitizer (\u003c= 2.0.1) where restrictive sanitization configurations are silently ignored.\n\nWhen a developer explicitly sets:\n\n  allowedTags: []\n  allowedAttributes: {}\n\nthe library incorrectly treats these values as \"not provided\" due to length/emptiness checks, and falls back to sanitize-html's default configuration.\n\nAs a result, instead of stripping all HTML tags and attributes, the sanitizer allows a permissive set of tags ``` (e.g., \u003ca\u003e, \u003cp\u003e, \u003cdiv\u003e, etc.) and attributes (e.g., href on \u003ca\u003e)```.\n\nThis behavior violates the expected API contract and may lead to security issues such as content injection or XSS, depending on how the sanitized output is used.\n\n##  Impact\n\nDevelopers intending to fully strip HTML content by providing empty allowedTags or allowedAttributes configurations may unknowingly allow a wide range of HTML elements and attributes.\n\nThis can result in:\n- Injection of unintended HTML content ```(e.g., \u003cdiv\u003e, \u003ctable\u003e, headings)```\n- Injection of links via``` \u003ca href=\"...\"\u003e```\n- Potential XSS vectors depending on downstream usage\n\nThe impact depends on how the sanitized output is rendered or consumed, but the root issue is a mismatch between developer intent and actual behavior.\n\n## Proof of Concept\n\n```javascript\nconst { sanitize } = require('express-xss-sanitizer');\nconst sanitizeHtml = require('sanitize-html');\n\nconst input = '\u003ca href=\"http://evil.com\"\u003eclick\u003c/a\u003e\u003cp\u003ephish\u003c/p\u003e';\n\n// Using express-xss-sanitizer (v2.0.1)\nsanitize(input, { allowedTags: [], allowedAttributes: {} });\n// =\u003e '\u003ca href=\"http://evil.com\"\u003eclick\u003c/a\u003e\u003cp\u003ephish\u003c/p\u003e'\n\n// Expected behavior (sanitize-html directly)\nsanitizeHtml(input, { allowedTags: [], allowedAttributes: {} });\n// =\u003e 'clickphish'\n```\n\n## Root Cause\nThe issue was caused by validation logic that checked for non-empty arrays/objects:\n\n- allowedTags required length \u003e 0\n- allowedAttributes required Object.keys(...).length \u003e 0\n\nThis caused empty configurations ([]) and ({}) to be ignored, resulting in fallback to default permissive settings.\n\n## Fix\nThe validation logic has been updated to respect explicitly provided empty configurations.\n\nNow, if allowedTags or allowedAttributes are provided (even if empty), they are passed directly to sanitize-html without being overridden.","status":"published","published":"2026-03-27T17:56:45Z","modified":"2026-03-30T20:11:03Z","cvss":[{"version":"3.1","score":8.2,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:H/A:N","level":"high"}],"cwes":["CWE-79","CWE-183"],"updated_at":"2026-11-02T14:39:46.119458Z"}],"nvd":[{"id":"CVE-2026-33979","description":"Express XSS Sanitizer is Express 4.x and 5.x middleware which sanitizes user input data (in req.body, req.query, req.headers and req.params) to prevent Cross Site Scripting (XSS) attack. A vulnerability has been identified in versions prior to 2.0.2 where restrictive sanitization configurations are silently ignored. In version 2.0.2, the validation logic has been updated to respect explicitly provided empty configurations. Now, if allowedTags or allowedAttributes are provided (even if empty), they are passed directly to sanitize-html without being overridden.","status":"published","published":"2026-03-27T22:16:22.433Z","modified":"2026-06-17T10:38:22.467Z","cvss":[{"version":"3.1","score":8.2,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:H/A:N","level":"high","assessor":"secondary"}],"cwes":["CWE-79","CWE-183"],"updated_at":"2026-11-02T14:12:11.678711Z"}],"osv":[{"id":"CVE-2026-33979","title":"Express XSS Sanitizer: allowedTags/allowedAttributes bypass leads to permissive sanitization (XSS risk)","description":"Express XSS Sanitizer is Express 4.x and 5.x middleware which sanitizes user input data (in req.body, req.query, req.headers and req.params) to prevent Cross Site Scripting (XSS) attack. A vulnerability has been identified in versions prior to 2.0.2 where restrictive sanitization configurations are silently ignored. In version 2.0.2, the validation logic has been updated to respect explicitly provided empty configurations. Now, if allowedTags or allowedAttributes are provided (even if empty), they are passed directly to sanitize-html without being overridden.","status":"published","published":"2026-03-27T21:29:19.759Z","modified":"2026-10-28T02:31:04.023137956Z","cvss":[{"version":"3.1","score":8.2,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:H/A:N","level":"high"}],"cwes":["CWE-183","CWE-79"],"updated_at":"2026-11-02T15:45:02.247031Z"},{"id":"GHSA-3843-rr4g-m8jq","title":"Express XSS Sanitizer: allowedTags/allowedAttributes bypass leads to permissive sanitization (XSS risk)","description":"## Description\nA vulnerability has been identified in express-xss-sanitizer (\u003c= 2.0.1) where restrictive sanitization configurations are silently ignored.\n\nWhen a developer explicitly sets:\n\n  allowedTags: []\n  allowedAttributes: {}\n\nthe library incorrectly treats these values as \"not provided\" due to length/emptiness checks, and falls back to sanitize-html's default configuration.\n\nAs a result, instead of stripping all HTML tags and attributes, the sanitizer allows a permissive set of tags ``` (e.g., \u003ca\u003e, \u003cp\u003e, \u003cdiv\u003e, etc.) and attributes (e.g., href on \u003ca\u003e)```.\n\nThis behavior violates the expected API contract and may lead to security issues such as content injection or XSS, depending on how the sanitized output is used.\n\n##  Impact\n\nDevelopers intending to fully strip HTML content by providing empty allowedTags or allowedAttributes configurations may unknowingly allow a wide range of HTML elements and attributes.\n\nThis can result in:\n- Injection of unintended HTML content ```(e.g., \u003cdiv\u003e, \u003ctable\u003e, headings)```\n- Injection of links via``` \u003ca href=\"...\"\u003e```\n- Potential XSS vectors depending on downstream usage\n\nThe impact depends on how the sanitized output is rendered or consumed, but the root issue is a mismatch between developer intent and actual behavior.\n\n## Proof of Concept\n\n```javascript\nconst { sanitize } = require('express-xss-sanitizer');\nconst sanitizeHtml = require('sanitize-html');\n\nconst input = '\u003ca href=\"http://evil.com\"\u003eclick\u003c/a\u003e\u003cp\u003ephish\u003c/p\u003e';\n\n// Using express-xss-sanitizer (v2.0.1)\nsanitize(input, { allowedTags: [], allowedAttributes: {} });\n// =\u003e '\u003ca href=\"http://evil.com\"\u003eclick\u003c/a\u003e\u003cp\u003ephish\u003c/p\u003e'\n\n// Expected behavior (sanitize-html directly)\nsanitizeHtml(input, { allowedTags: [], allowedAttributes: {} });\n// =\u003e 'clickphish'\n```\n\n## Root Cause\nThe issue was caused by validation logic that checked for non-empty arrays/objects:\n\n- allowedTags required length \u003e 0\n- allowedAttributes required Object.keys(...).length \u003e 0\n\nThis caused empty configurations ([]) and ({}) to be ignored, resulting in fallback to default permissive settings.\n\n## Fix\nThe validation logic has been updated to respect explicitly provided empty configurations.\n\nNow, if allowedTags or allowedAttributes are provided (even if empty), they are passed directly to sanitize-html without being overridden.","status":"published","published":"2026-03-27T17:56:45Z","modified":"2026-03-30T20:19:57.372851Z","cvss":[{"version":"3.1","score":8.2,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:H/A:N","level":"high"}],"cwes":["CWE-183","CWE-79"],"updated_at":"2026-11-02T15:46:35.406455Z"}]}}
