GHSA-5cwg-6vw7-rj6p: Forge: AES-GCM authentication bypass via unvalidated tagLength option

  • Severity: MEDIUM
  • CVE: CVE-2026-119186
  • Ecosystems: npm
  • Packages: node-forge

### Summary

The AES-GCM mode in forge.cipher does not validate the tagLength option passed to start(). With a tagLength of 0 or a value that converts to 0 (such as null, false, ” or ‘0’), the authentication tag is empty, and decipher.finish() returns true for any ciphertext and additional data when the supplied tag is empty or missing. Fixed in node-forge 1.4.1.

### Details

`modes.gcm.prototype.start()` in `lib/cipherModes.js` stored the `tagLength` option without validation, and `lib/cipher.js` documented it as accepting “0-128”. After processing the data, `afterFinish()` truncates the 16-byte tag with `truncate(16 % (tagLength / 8))`. For a `tagLength` that converts to 0, this is `16 % 0 = NaN`, and truncating by `NaN` empties the tag. On decryption, the start-time check that the supplied `tag` has `tagLength / 8` bytes passes for an empty tag, and the final tag comparison compares two empty strings, so `decipher.finish()` returns `true` for any ciphertext and additional data.

NIST SP 800-38D section 5.2.1.2 allows only tag lengths of 128, 120, 112, 104 and 96 bits, plus 64 and 32 bits for certain applications.

The fix validates `tagLength` in `start()`, for both encryption and decryption. A missing, `null` or `undefined` `tagLength` uses the default of 128 bits. Any other value is converted with `Number()` and must be one of 128, 120, 112, 104, 96, 64 or 32; otherwise `start()` throws “Invalid tag length.”. Numeric strings such as `’128’` are still accepted. With a v…

Source: GitHub Security Advisories · 2026-10-30