CVE-2026-118776: CVE-2026-118776: Improper PKCS#7 Padding Validation in node-forge CBC and ECB Cipher Modes
CVE-2026-118776: Improper PKCS#7 Padding Validation in node-forge CBC and ECB Cipher Modes Vulnerability ID: CVE-2026-118776 CVSS Score: 3.7 Published: 2026-11-10 CVE-2026-118776 (also tracked as GHSA-2vgq-wchc-25w7
CVE-2026-118776: Improper PKCS#7 Padding Validation in node-forge CBC and ECB Cipher Modes
Vulnerability ID: CVE-2026-118776
CVSS Score: 3.7
Published: 2026-11-10
CVE-2026-118776 (also tracked as GHSA-2vgq-wchc-25w7) is an improper input and integrity check validation vulnerability affecting the node-forge cryptographic library prior to version 1.4.1. In vulnerable versions, the PKCS#7 unpadding implementations for Cipher Block Chaining (CBC) and Electronic Codebook (ECB) modes only examined the final byte of the decrypted buffer and permitted padding counts up to four times the cipher block size. This defect allowed malformed ciphertexts containing zero-length padding, oversized padding values, or mismatched preceding padding bytes to pass validation, resulting in silent plaintext truncation of up to four blocks and integrity verification bypass in applications relying on unpadding success.
TL;DR
Versions of node-forge prior to 1.4.1 improperly validate PKCS#7 padding in CBC and ECB decryption modes by checking only the last byte and allowing padding lengths up to four blocks. Attackers can supply malformed ciphertexts that pass decryption validation or silently truncate up to four blocks of plaintext.
β οΈ Exploit Status: POC
Technical Details
- CVE ID: CVE-2026-118776 (GHSA-2vgq-wchc-25w7)
- Weakness Class: CWE-354 (Improper Validation of Integrity Check Value) / CWE-20
- Affected Component: node-forge < 1.4.1 (lib/cipherModes.js: modes.cbc.prototype.unpad & modes.ecb.prototype.unpad)
- Attack Vector: Network (AV:N) / High Attack Complexity (AC:H)
- CVSS v3.1 Score: 3.7 Low (CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:L/A:N)
- EPSS Score: 0.14% (3.10th Percentile)
- Primary Impact: Acceptance of malformed PKCS#7 ciphertexts and silent truncation of up to 4 plaintext blocks
- CISA KEV Status: Not Listed
Affected Systems
- node-forge (npm package)
- digitalbazaar/forge
-
node-forge: < 1.4.1 (Fixed in:
1.4.1)
Code Analysis
Commit: 81774ff
Validate all PKCS#7 padding bytes during CBC and ECB unpadding and add Wycheproof test vectors.
File: lib/cipherModes.js
@@ -82,13 +82,25 @@ modes.ecb.prototype.unpad = function(output, options) {
return false;
}
+ // nothing to unpad, e.g. the caller already read all output
var len = output.length();
+ if(len === 0) {
+ return true;
+ }
+
// ensure padding byte count is valid
var count = output.at(len - 1);
- if(count > (this.blockSize << 2)) {
+ if(count === 0 || count > this.blockSize || count > len) {
return false;
}
+ // ensure all padding bytes match the padding count (RFC 5652 6.3)
+ for(var i = 2; i <= count; ++i) {
+ if(output.at(len - i) !== count) {
+ return false;
+ }
+ }
+
// trim off padding bytes
output.truncate(count);
return true;
@@ -183,13 +195,25 @@ modes.cbc.prototype.unpad = function(output, options) {
return false;
}
+ // nothing to unpad, e.g. the caller already read all output
var len = output.length();
+ if(len === 0) {
+ return true;
+ }
+
// ensure padding byte count is valid
var count = output.at(len - 1);
- if(count > (this.blockSize << 2)) {
+ if(count === 0 || count > this.blockSize || count > len) {
return false;
}
+ // ensure all padding bytes match the padding count (RFC 5652 6.3)
+ for(var i = 2; i <= count; ++i) {
+ if(output.at(len - i) !== count) {
+ return false;
+ }
+ }
+
// trim off padding bytes
output.truncate(count);
return true;
Exploit Details
- GitHub: Project Wycheproof test vectors integrated into tests/unit/aes.js demonstrating malformed PKCS#7 padding ciphertexts accepted prior to 1.4.1.
- GitHub: Public repository tracking CVE-2026-118776 advisory and proof-of-concept details.
Mitigation Strategies
- Upgrade node-forge to version 1.4.1 or newer to enforce strict RFC 5652 Section 6.3 PKCS#7 padding validation.
- Migrate from unauthenticated block cipher modes (AES-CBC, AES-ECB) to Authenticated Encryption with Associated Data (AEAD) modes such as AES-GCM.
- Implement an Encrypt-then-MAC construction (e.g., AES-CBC + HMAC-SHA256) and verify the MAC prior to invoking decryption routines if legacy CBC mode is required.
- Disable automatic unpadding (decipher.mode.unpad = false) and implement explicit validation if non-PKCS#7 padding schemes (such as ANSI X.923 or ISO 10126) are intentionally used.
Remediation Steps:
- Inspect package.json and lockfiles (package-lock.json, yarn.lock, pnpm-lock.yaml) to identify direct and transitive dependencies on node-forge versions prior to 1.4.1.
- Run 'npm install node-forge@^1.4.1' or update dependency overrides/resolutions to force node-forge >= 1.4.1 across the dependency tree.
- Execute unit and integration test suites to verify that no legacy workflows depend on non-PKCS#7 padding formats (e.g., ANSI X.923) implicitly passing CBC/ECB decryption.
- Refactor cryptographic modules that rely solely on decipher.finish() for ciphertext integrity verification to use AES-GCM or verify an HMAC before decryption.
References
- CVE-2026-118776 Official CVE Record
- GitHub Security Advisory GHSA-2vgq-wchc-25w7
- node-forge Patch Commit (81774ff99e2da64aec9a43591df45a360040c136)
- node-forge v1.4.1 Release Tag
- CVEList v5 JSON Record for CVE-2026-118776
- National Vulnerability Database (NVD) - CVE-2026-118776
- zebbernCVE Repository for CVE-2026-118776
- Project Wycheproof Cryptographic Test Vectors
Read the full report for CVE-2026-118776 on our website for more details including interactive diagrams and full exploit analysis.
Originally published by Dev.to Security. Aggregated on AIWithGhost for educational purposes β full credit and traffic to the original publisher.