Advisory Database
  • Advisories
  • Dependency Scanning
  1. npm
  2. ›
  3. node-opcua
  4. ›
  5. CVE-2026-54155

CVE-2026-54155: node-opcua missing nonce verification in UserNameIdentityToken authentication

August 20, 2026

Summary A missing nonce verification in the UserNameIdentityToken authentication handler allows an unauthenticated remote attacker to forge a password token that extracts as an empty string, and to replay captured authentication tokens across sessions.

Affected versions: <= 2.165.0 Tested version: 2.165.0 CVSS Score: 8.1 (High) CVSS Vector: CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:L CWE: CWE-347 Improper Verification of Cryptographic Signature


Root Cause

In packages/node-opcua-server/source/opcua_server.ts at line 1886-1887, after RSA-OAEP decrypting the UserNameIdentityToken password blob, the server reads a 4-byte little-endian length field and extracts buff[4 : 4+length] as the password. It never verifies that the trailing bytes equal session.nonce.

This has two consequences:

  1. Forged empty password: An attacker who retrieves the server’s public key via an unauthenticated GetEndpoints call can craft a token where the 4-byte length field equals serverNonce.length (32). The server computes length = 32 - 32 = 0 and calls isValidUser(username, ""). Any account that accepts an empty password is compromised.

  2. Unconditional replay attack: Because nonce binding is structurally absent, any captured UserNameIdentityToken ciphertext can be replayed in a different session unconditionally.

The impact is compounded by a second issue: when the channel uses SecurityMode=None, verifyClientSignature returns true unconditionally (security_policy.ts:697-700), bypassing the channel-level signature check entirely.


Proof of Concept (logic, no exploit code)

1. GetEndpoints (unauthenticated) → retrieve server public key and RSA token policy
2. OpenSecureChannel (SecurityMode=None)
3. CreateSession
4. Craft plaintext: [0x20, 0x00, 0x00, 0x00]  (readUInt32LE = 32 = serverNonce.length)
5. RSA-OAEP encrypt with server public key → 256-byte ciphertext
6. ActivateSession with crafted UserNameIdentityToken
7. Server decrypts → length = 32 - 32 = 0 → password = ""
8. isValidUser(username, "") is called

Dynamically confirmed: decryption produces password = "" with no error and no nonce verification.


Suggested Fix

After decrypting the password blob, verify that buff.slice(4 + passwordLength) equals session.nonce before extracting the password. Reject the token if verification fails.


I am following a 90-day responsible disclosure policy. I am happy to provide additional technical details under embargo. Please confirm receipt at your earliest convenience.

Reporter: Stanley Tobias Discovery date: 2026-03-23

References

  • github.com/advisories/GHSA-mq36-523m-x7vv
  • github.com/node-opcua/node-opcua/security/advisories/GHSA-mq36-523m-x7vv
  • nvd.nist.gov/vuln/detail/CVE-2026-54155

Code Behaviors & Features

Detect and mitigate CVE-2026-54155 with GitLab Dependency Scanning

Secure your software supply chain by verifying that all open source dependencies used in your projects contain no disclosed vulnerabilities. Learn more about Dependency Scanning →

Affected versions

All versions up to 2.165.0

Solution

Unfortunately, there is no solution available yet.

Impact 7.7 HIGH

CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:L

Learn more about CVSS

Weakness

  • CWE-347: Improper Verification of Cryptographic Signature

Source file

npm/node-opcua/CVE-2026-54155.yml

Spotted a mistake? Edit the file on GitLab.

  • Site Repo
  • About GitLab
  • Terms
  • Privacy Statement
  • Contact

Page generated Thu, 17 Sep 2026 00:18:08 +0000.