CVE-2026-125335: Forge: Ed25519 signature verification accepts small-order public keys

Published Nov 10, 2026
·
Updated

Summary ed25519.verify() does not reject public keys of small order, such as the identity point. Under such a key, a signature with S = 0 and a small-order R verifies for many messages, or for every message with the identity key, without any private key. Fixed in node-forge 1.4.3.

Details cryptosignopen() in lib/ed25519.js decodes the public key A with unpackneg(), which only checks that the point is on the curve, and then checks R == [S]B - [k]A with k = SHA-512(R || A || M). Nothing rejects public keys of small order: the identity point, the other 7 points of order 2, 4 or 8, and their non-canonical encodings with y >= p.

With S = 0, the check becomes R == k. For a small-order A, k is one of at most 8 small-order points, so an attacker can make a valid signature by trying the small-order values of R. For the identity key (01 00 … 00), R = identity and S = 0 verifies for every message. For the other small-order keys, a given message can be forged with high probability. No private key is involved. The S < L check added for CVE-2026-33895 (GHSA-q67f-28xg-22rw) doesn't apply, because S = 0 is canonical.

Keys produced by Ed25519 key generation (ed25519.generateKeyPair() or any RFC 8032 implementation) are never small-order, so signatures under them cannot be forged this way. Applications are affected when they verify signatures against a public key an attacker can choose (for example a key included with the signed data, a self-registered key, or a key in an attacker-controlled document) and rely on the signature being bound to the message: proof of possession, attribution, non-repudiation or deduplication.

RFC 8032 doesn't require rejecting small-order public keys, and implementations differ. libsodium rejects them, and Node.js crypto.verify() (OpenSSL) rejects these signatures.

The fix rejects a public key A when [8]A is the identity point. This covers all small-order points and their non-canonical encodings.

Patches Fixed in node-forge 1.4.3. ed25519.verify() returns false for small-order public keys.

Workarounds Before calling ed25519.verify() with a public key from untrusted input, reject keys whose 32-byte encoding is one of the small-order points (the identity 01 00 … 00 and the other encodings that libsodium blocks), or only verify against keys you generated or have otherwise validated.

Resources - RFC 8032, Section 5.1.7 (Ed25519 verification): https://www.rfc-editor.org/rfc/rfc8032#section-5.1.7 - GHSA-q67f-28xg-22rw / CVE-2026-33895 (a different Ed25519 verification issue, fixed in 1.4.0): https://github.com/digitalbazaar/forge/security/advisories/GHSA-q67f-28xg-22rw

Severity CVSS 3.1: CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:L/A:N (3.7, Low) CVSS 4.0 (informational): CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:L/VA:N/SC:N/SI:N/SA:N (6.3) CVSS 4.0 rates this Moderate because its integrity weighting is higher; the severity rating follows CVSS 3.1.

Credits Reported by @analisaperlengkapan.

Proof of concept Identity public key A = 01 00 … 00 (32 bytes) and signature R = 01 00 … 00, S = 00 … 00 (64 bytes):

forge.ed25519.verify({message: 'admin=true', encoding: 'utf8', signature: SIG, publicKey: IDENTITY}); // <= 1.4.2: true for any message; node:crypto.verify(): false // 1.4.3: false

Other small-order public keys (orders 2, 4 and 8, and non-canonical encodings) give forgeries for many messages with S = 0 and a small-order R.

Regression tests are in tests/unit/ed25519.js, and the reporter's PoC is in tests/pocs/ghsa-6889-vf6x-f3g5.js.

Impact Applications that verify Ed25519 signatures with node-forge against a public key that an attacker can choose are affected. An attacker can provide a small-order public key and then produce signatures that verify for many or all messages without a private key, defeating checks that rely on a signature being bound to its message under that key (proof of possession, attribution, non-repudiation, deduplication). Signatures under keys from honest key generation cannot be forged, and applications that only verify against their own or otherwise trusted keys are not affected.

Other sources

Forge (also called node-forge) is a native implementation of Transport Layer Security in JavaScript. Prior to 1.4.3, ed25519.verify() decodes a public key in cryptosignopen() without rejecting small-order points or their non-canonical encodings. With S = 0 and a small-order R value, an attacker who can choose the public key can produce signatures that verify for many messages, or all messages with the identity key, without a private key. This can defeat proof-of-possession, attribution, non-repudiation, or deduplication checks that rely on a signature being bound to the message. Keys produced by normal Ed25519 key generation are not small-order, so applications that verify only trusted or internally generated public keys are not affected. This issue is fixed in version 1.4.3.

— MITRE

Affected Software

3 affected componentsFixes available
npm/node-forge<1.4.3
npm/node-forge<=1.4.2
1.4.3
npm/node-forge<1.4.3
1.4.3

Remediation

Recommended actions to resolve this vulnerability, in priority order.

  1. Upgrade

    Upgrade npm/node-forge to a version that resolves this vulnerability.

    Fixed in 1.4.3
  2. Upgrade

    Upgrade node-forge to a version that resolves this vulnerability.

    Fixed in 1.4.3
  3. Compensating control

    Before calling ed25519.verify() with a public key from untrusted input, reject keys whose 32-byte encoding is a small-order point, including the identity point and other encodings blocked by libsodium; alternatively, verify only against keys generated by the application or otherwise validated.

Event History

Nov 10, 2026
CVE Published
via MITRE·06:51 PM
Data Sourced
via MITRE·06:51 PM
DescriptionSeverityWeakness
Data Sourced
via NVD·07:21 PM
DescriptionSeverityWeakness
Advisory Published
via GitHub·09:18 PM
Data Sourced
via GitHub·09:18 PM
DescriptionSeverityWeaknessAffected Software

Frequently Asked Questions

1

Which applications are exposed to this issue?

Applications are exposed if they use node-forge Ed25519 verification with public keys an attacker can choose or supply. Applications that verify only trusted or internally generated public keys are not affected, because normal Ed25519 key generation does not produce small-order keys.

2

What does an attacker need to exploit it?

The attacker needs to be able to choose the public key used for verification. They can then use a small-order public key and a signature with S = 0 and a small-order R value to obtain verification without possessing the corresponding private key.

3

What security controls can this bypass?

The issue can defeat checks that assume a verified signature is bound to a message, including proof-of-possession, attribution, non-repudiation, and deduplication checks. With the identity key, signatures may verify for all messages.

4

What version fixes the issue?

Upgrade node-forge to version 1.4.3. Versions prior to 1.4.3 do not reject small-order public-key points or their non-canonical encodings during Ed25519 verification.

Contact

SecAlerts Pty Ltd.
132 Wickham Terrace
Fortitude Valley,
QLD 4006, Australia
info@secalerts.co
By using SecAlerts services, you agree to our services end-user license agreement. This website is safeguarded by reCAPTCHA and governed by the Google Privacy Policy and Terms of Service. All names, logos, and brands of products are owned by their respective owners, and any usage of these names, logos, and brands for identification purposes only does not imply endorsement. If you possess any content that requires removal, please get in touch with us.
© 2026 SecAlerts Pty Ltd.
ABN: 70 645 966 203, ACN: 645 966 203