CVE-2026-46395: HAXcms Private Key Disclosure Vulnerability

CRITICAL
Advisory Identifier: GHSA-6c8g-9hfh-pq5h
CWE-321 CWE-327 CWE-200
Published
Advisory Summary

CVE-2026-46395 is a CRITICAL private key disclosure vulnerability (CWE-321: Use of Hard-coded Cryptographic Key) affecting HAXcms libraries in the npm ecosystem. The issue involves private key disclosure via broken hmac implementation. Remediation is available by upgrading affected packages to version 26.0.0.

CVE-2026-46395 at a Glance

CVE Identifier CVE-2026-46395
GHSA Identifier GHSA-6c8g-9hfh-pq5h
Severity CRITICAL
CVSS v3.1 Base Score N/A
CWE Classification CWE-321: Use of Hard-coded Cryptographic Key
Affected Product HAXcms
Package Ecosystem npm
Published Date
Last Updated

How to Fix CVE-2026-46395

To remediate this vulnerability, upgrade all affected HAXcms dependencies to a patched release. Both direct and transitive dependencies should be checked, as frameworks or security libraries may pull in vulnerable versions transitively.

@haxtheweb/haxcms-nodejs fixed: 26.0.0
npm install @haxtheweb/haxcms-nodejs@26.0.0
Verify Direct and Transitive Dependencies

Run the following command in your project directory to verify that all resolved dependencies use the patched release:

npm ls @haxtheweb/haxcms-nodejs

How to Check if You Are Affected

To determine whether your Node.js application is affected by CVE-2026-46395, inspect your project dependencies using npm:

npm ls @haxtheweb/haxcms-nodejs

Analyze the terminal output to locate any version of HAXcms in your dependency tree. If any resolved version matches the vulnerable ranges listed in the table below (for example, versions earlier than 26.0.0), your application is affected.

Note: The npm ls @haxtheweb/haxcms-nodejs command inspects dependencies declared in your package.json and lockfile; it does not perform automated runtime dynamic scanning.

Technical Details

Vulnerability Mechanism & Technical Analysis

This vulnerability is classified under CWE-321: Use of Hard-coded Cryptographic Key, where the product uses a hard-coded, unchangeable cryptographic key. In HAXcms, software state validation or input boundaries are circumvented during processing. Review the official source advisory statement below for specific affected components, classes, and reproduction details.

Source Advisory Statement

### Summary The `hmacBase64()` function in the HAXcms Node.js backend contains two critical cryptographic implementation errors that together allow any unauthenticated attacker to extract the system’s private signing key and forge arbitrary admin-level JSON Web Tokens (JWTs) allowing them to get full admin access with a single HTTP request. ### Details Bug 1: Hardcoded HMAC Key (line 2160): The function passes the literal string "0" as the HMAC signing key instead of the key parameter, making every HAXcms instance compute identical HMACs for the same input. Bug 2: Private Key Appended to Output (lines 2161- 2163): After computing the HMAC, the function concatenates the real key parameter which is "this.privateKey + this.salt", the system’s master signing secret is directly onto the output. The combined buffer is base64-encoded and returned as the token. Every base64url token produced has the same structure: 32 bytes HMAC keyed with "0" and N bytes of `privateKey+salt`. An attacker base64-decodes any token, discards the first 32 bytes, and reads the private key directly. The `/system/api/connectionSettings` endpoint is unauthenticated and returns multiple tokens generated by this function. A single GET request to this endpoint exposes the private key. The PHP backend (HAXCMS.php:1619-1631) implements this function correctly with the actual key and returns only the hash. The PHP version produces 44-character tokens whereas the broken Node.js version produces 139+ character tokens. ### PoC 1. GET request to `/system/api/connectionSettings` endpoint and fetch the token. 2. Extract the private key from the fetched token. The `hmacBase64()` function produces 32 bytes with HMAC-SHA256 with hardcoded key "0" and the rest of the bytes are `privateKey+salt` (plaintext). Decode the Base64 token, discard the first 32 bytes, read the remaining bytes as UTF-8 (this is your extracted private key). 3. Since JWT's are signed with `privateKey+salt`, use this stolen private key to forge a JWT for admin using `JWT.sign(payload, this.privateKey+this.salt)`. NOTE: the payload uses {id, user (set this as admin), iat (current timestamp), exp (expiration timestamp)} 4. The same key can also be used to create other tokens (user_token, base_token, form_token, etc). 5. Use these forged tokens to hit all authenticated endpoints (modify/delete/create etc) with admin privileges. ### Impact An unauthenticated attacker can perform the complete attack chain with a single HTTP request: 1. Extract private key: GET "/system/api/connectionSettings", base64-decode any token, discard first 32 bytes. 2. Forge admin JWT: sign arbitrary JWT payloads with the stolen privateKey+salt. 3. Forge all request tokens: compute valid user_token, site_token for any API call. 4. Full admin access: create/modify/delete sites, upload files, modify content. This works even if the admin has changed the default credentials to a strong password. The forged tokens produce no login events in logs.

CVE-2026-46395 Affected HAXcms Versions

1 component(s)
Fixed Versions:
26.0.0
Product / Package Ecosystem Affected Versions Fixed Version
@haxtheweb/haxcms-nodejs
npm
< 26.0.0
26.0.0

References

Frequently Asked Questions

What is CVE-2026-46395?
CVE-2026-46395 is a security vulnerability in HAXcms involving Private Key Disclosure via Broken HMAC Implementation under CWE-321: Use of Hard-coded Cryptographic Key.
Which HAXcms versions are affected?
Affected versions include releases prior to 26.0.0 across affected packages: @haxtheweb/haxcms-nodejs.
What version fixes CVE-2026-46395?
Upgrading to 26.0.0 (or the latest patched release for your respective branch) resolves the vulnerability.
Is @haxtheweb/haxcms-nodejs affected?
Yes, @haxtheweb/haxcms-nodejs is affected in releases prior to 26.0.0. Upgrade your dependency to 26.0.0 or later.
What CWE is associated with CVE-2026-46395?
CVE-2026-46395 is classified under CWE-321: Use of Hard-coded Cryptographic Key (The product uses a hard-coded, unchangeable cryptographic key.).
How can I check npm dependencies for CVE-2026-46395?
Run the dependency tree command: 'npm ls @haxtheweb/haxcms-nodejs'. This command lists direct and transitive dependencies in your build configuration so you can verify if a vulnerable version is resolved.
Machine-readable OSV JSON OSV v1.5 Schema
Normalized schema output
{
  "schema_version" : "1.4.0",
  "id" : "GHSA-6c8g-9hfh-pq5h",
  "modified" : "2026-06-09T11:56:50Z",
  "published" : "2026-05-19T14:44:55Z",
  "aliases" : [ "CVE-2026-46395" ],
  "summary" : "HAXcms: Private Key Disclosure via Broken HMAC Implementation",
  "details" : "### Summary\nThe `hmacBase64()` function in the HAXcms Node.js backend contains two critical cryptographic implementation errors that together allow any unauthenticated attacker to extract the system’s private signing key and forge arbitrary admin-level JSON Web Tokens (JWTs) allowing them to get full admin access with a single HTTP request.\n\n### Details\nBug 1: Hardcoded HMAC Key (line 2160): The function passes the literal string \"0\" as the HMAC signing key instead of the key parameter, making every HAXcms instance compute identical HMACs for the same input.\n\nBug 2: Private Key Appended to Output (lines 2161- 2163): After computing the HMAC, the function concatenates the real key parameter which is \"this.privateKey + this.salt\", the system’s master signing secret is directly onto the output. The combined buffer is base64-encoded and returned as the token.\n\nEvery base64url token produced has the same structure: 32 bytes HMAC keyed with \"0\" and N bytes of `privateKey+salt`. An attacker base64-decodes any token, discards the first 32 bytes, and reads the private key directly.\n\nThe `/system/api/connectionSettings` endpoint is unauthenticated and returns multiple tokens generated by this function. A single GET request to this endpoint exposes the private key.\n\nThe PHP backend (HAXCMS.php:1619-1631) implements this function correctly with the actual key and returns only the hash. The PHP version produces 44-character tokens whereas the broken Node.js version produces 139+ character tokens.\n\n### PoC\n1. GET request to `/system/api/connectionSettings` endpoint and fetch the token.\n2. Extract the private key from the fetched token. The `hmacBase64()` function produces 32 bytes with HMAC-SHA256 with hardcoded key \"0\" and the rest of the bytes are `privateKey+salt` (plaintext). Decode the Base64 token, discard the first 32 bytes, read the remaining bytes as UTF-8 (this is your extracted private key).\n3. Since JWT's are signed with `privateKey+salt`, use this stolen private key to forge a JWT for admin using `JWT.sign(payload, this.privateKey+this.salt)`. NOTE: the payload uses {id, user (set this as admin), iat (current timestamp), exp (expiration timestamp)}\n4. The same key can also be used to create other tokens (user_token, base_token, form_token, etc).\n5. Use these forged tokens to hit all authenticated endpoints (modify/delete/create etc) with admin privileges.\n\n### Impact\nAn unauthenticated attacker can perform the complete attack chain with a single HTTP request:\n1. Extract private key: GET \"/system/api/connectionSettings\", base64-decode any token, discard first 32 bytes.\n2. Forge admin JWT: sign arbitrary JWT payloads with the stolen privateKey+salt.\n3. Forge all request tokens: compute valid user_token, site_token for any API call.\n4. Full admin access: create/modify/delete sites, upload files, modify content.\n\nThis works even if the admin has changed the default credentials to a strong password. The forged tokens produce no login events in logs.",
  "severity" : [ {
    "type" : "CVSS_V4",
    "score" : "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N"
  } ],
  "affected" : [ {
    "package" : {
      "ecosystem" : "npm",
      "name" : "@haxtheweb/haxcms-nodejs"
    },
    "ranges" : [ {
      "type" : "ECOSYSTEM",
      "events" : [ {
        "introduced" : "0"
      }, {
        "fixed" : "26.0.0"
      } ]
    } ],
    "database_specific" : {
      "last_known_affected_version_range" : "<= 25.0.0"
    }
  } ],
  "references" : [ {
    "type" : "WEB",
    "url" : "https://github.com/haxtheweb/issues/security/advisories/GHSA-6c8g-9hfh-pq5h"
  }, {
    "type" : "ADVISORY",
    "url" : "https://nvd.nist.gov/vuln/detail/CVE-2026-46395"
  }, {
    "type" : "PACKAGE",
    "url" : "https://github.com/haxtheweb/issues"
  } ],
  "database_specific" : {
    "cwe_ids" : [ "CWE-200", "CWE-321", "CWE-327" ],
    "severity" : "CRITICAL",
    "github_reviewed" : true,
    "github_reviewed_at" : "2026-05-19T14:44:55Z",
    "nvd_published_at" : "2026-06-05T19:16:33Z"
  }
}