VYPR
Critical severityNVD Advisory· Published Jun 23, 2025· Updated Apr 15, 2026

CVE-2025-6545

CVE-2025-6545

Description

Improper Input Validation vulnerability in pbkdf2 allows Signature Spoofing by Improper Validation. This vulnerability is associated with program files lib/to-buffer.Js.

This issue affects pbkdf2: from 3.0.10 through 3.1.2.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
pbkdf2npm
>= 3.0.10, < 3.1.33.1.3

Patches

2
e3102a8cd483

[Refactor] use `to-buffer`

https://github.com/browserify/pbkdf2Jordan HarbandJun 18, 2025via ghsa
4 files changed · +35 24
  • .github/workflows/node-aught.yml+1 1 modified
    @@ -6,7 +6,7 @@ jobs:
       tests:
         uses: ljharb/actions/.github/workflows/node.yml@main
         with:
    -      range: '< 10'
    +      range: '>= 0.12 < 10'
           type: minors
           command: npm run tests-only
     
    
  • lib/to-buffer.js+13 9 modified
    @@ -1,16 +1,20 @@
     'use strict';
     
     var Buffer = require('safe-buffer').Buffer;
    +var toBuffer = require('to-buffer');
    +
    +var useUint8Array = typeof Uint8Array !== 'undefined';
    +var useArrayBuffer = useUint8Array && typeof ArrayBuffer !== 'undefined';
    +var isView = useArrayBuffer && ArrayBuffer.isView;
     
     module.exports = function (thing, encoding, name) {
    -	if (Buffer.isBuffer(thing)) {
    -		return thing;
    -	}
    -	if (typeof thing === 'string') {
    -		return Buffer.from(thing, encoding);
    -	}
    -	if (ArrayBuffer.isView(thing)) {
    -		return Buffer.from(thing.buffer);
    +	if (
    +		typeof thing === 'string'
    +		|| Buffer.isBuffer(thing)
    +		|| (useUint8Array && thing instanceof Uint8Array)
    +		|| (isView && isView(thing))
    +	) {
    +		return toBuffer(thing, encoding);
     	}
    -	throw new TypeError(name + ' must be a string, a Buffer, a typed array or a DataView');
    +	throw new TypeError(name + ' must be a string, a Buffer, a Uint8Array, or a DataView');
     };
    
  • package.json+2 1 modified
    @@ -53,7 +53,8 @@
     		"create-hmac": "^1.1.7",
     		"ripemd160": "=2.0.1",
     		"safe-buffer": "^5.2.1",
    -		"sha.js": "^2.4.11"
    +		"sha.js": "^2.4.11",
    +		"to-buffer": "^1.2.0"
     	},
     	"engines": {
     		"node": ">=0.12"
    
  • test/index.js+19 13 modified
    @@ -14,6 +14,8 @@ var fixtures = require('./fixtures');
     var js = require('../browser');
     var browserImpl = require('../lib/sync-browser');
     
    +var errMsg = function (name) { return new RegExp(name + ' must be a string, a Buffer, a Uint8Array, or a DataView'); };
    +
     var pVersionMajor = parseInt(process.version.split('.')[0].slice(1), 10);
     /* istanbul ignore next */
     if (pVersionMajor !== 4 || process.browser) {
    @@ -108,25 +110,29 @@ function runTests(name, compat) {
     	tape(name + ' should throw if the password is not a string or an ArrayBuffer', function (t) {
     		t.plan(2);
     
    -		t['throws'](function () {
    -			compat.pbkdf2(['a'], 'salt', 1, 32, 'sha1', function () {});
    -		}, /Password must be a string, a Buffer, a typed array or a DataView/);
    +		t['throws'](
    +			function () { compat.pbkdf2(['a'], 'salt', 1, 32, 'sha1', function () {}); },
    +			errMsg('Password')
    +		);
     
    -		t['throws'](function () {
    -			compat.pbkdf2Sync(['a'], 'salt', 1, 32, 'sha1');
    -		}, /Password must be a string, a Buffer, a typed array or a DataView/);
    +		t['throws'](
    +			function () { compat.pbkdf2Sync(['a'], 'salt', 1, 32, 'sha1'); },
    +			errMsg('Password')
    +		);
     	});
     
     	tape(name + ' should throw if the salt is not a string or an ArrayBuffer', function (t) {
     		t.plan(2);
     
    -		t['throws'](function () {
    -			compat.pbkdf2('pass', ['salt'], 1, 32, 'sha1');
    -		}, /Salt must be a string, a Buffer, a typed array or a DataView/);
    +		t['throws'](
    +			function () { compat.pbkdf2('pass', ['salt'], 1, 32, 'sha1'); },
    +			errMsg('Salt')
    +		);
     
    -		t['throws'](function () {
    -			compat.pbkdf2Sync('pass', ['salt'], 1, 32, 'sha1');
    -		}, /Salt must be a string, a Buffer, a typed array or a DataView/);
    +		t['throws'](
    +			function () { compat.pbkdf2Sync('pass', ['salt'], 1, 32, 'sha1'); },
    +			errMsg('Salt')
    +		);
     	});
     
     	var algos = ['sha1', 'sha224', 'sha256', 'sha384', 'sha512', 'ripemd160'];
    @@ -250,7 +256,7 @@ tape('does not return all zeroes for any algorithm', function (t) {
     		for (var implName in impls) { // eslint-disable-line no-restricted-syntax
     			var pbkdf2Sync = impls[implName];
     			try {
    -				var key = pbkdf2Sync('secret', 'salt', 100000, 64, algo).toString('hex');
    +				var key = pbkdf2Sync('secret', 'salt', 1e4, 64, algo).toString('hex');
     				results[implName] = key;
     				t.doesNotMatch(key, /^0+$/, implName + ' does not return all zeros for ' + algo);
     			} catch (e) {
    
9699045c37a0

hmac ourselves

https://github.com/browserify/pbkdf2Calvin MetcalfApr 27, 2017via ghsa
1 file changed · +45 3
  • lib/sync.js+45 3 modified
    @@ -1,7 +1,47 @@
    -var createHmac = require('create-hmac')
    +var createHash = require('create-hash')
     var checkParameters = require('./precondition')
     var defaultEncoding = require('./default-encoding')
     var Buffer = require('safe-buffer').Buffer
    +var ZEROS = Buffer.alloc(128)
    +var sizes = {
    +  md5: 16,
    +  sha1: 20,
    +  sha224: 28,
    +  sha256: 32,
    +  sha384: 48,
    +  sha512: 64,
    +  rmd160: 20,
    +  ripemd160: 20
    +}
    +function computePad (alg, key) {
    +  var blocksize = (alg === 'sha512' || alg === 'sha384') ? 128 : 64
    +  if (key.length > blocksize) {
    +    key = hash(alg, key)
    +  } else if (key.length < blocksize) {
    +    key = Buffer.concat([key, ZEROS], blocksize)
    +  }
    +  var ipad = Buffer.allocUnsafe(blocksize)
    +  var opad = Buffer.alloc(blocksize + sizes[alg])
    +
    +  for (var i = 0; i < blocksize; i++) {
    +    ipad[i] = key[i] ^ 0x36
    +    opad[i] = key[i] ^ 0x5C
    +  }
    +  return {
    +    ipad: ipad,
    +    opad: opad,
    +    alg: alg,
    +    blocksize: blocksize
    +  }
    +}
    +function hash (algo, buffer) {
    +  return createHash(algo).update(buffer).digest()
    +}
    +function hmac (pad, data) {
    +  var h = hash(pad.alg, Buffer.concat([pad.ipad, data]))
    +  h.copy(pad.opad, pad.blocksize)
    +  return hash(pad.alg, pad.opad)
    +}
     module.exports = function (password, salt, iterations, keylen, digest) {
       if (!Buffer.isBuffer(password)) password = Buffer.from(password, defaultEncoding)
       if (!Buffer.isBuffer(salt)) salt = Buffer.from(salt, defaultEncoding)
    @@ -10,6 +50,8 @@ module.exports = function (password, salt, iterations, keylen, digest) {
     
       digest = digest || 'sha1'
     
    +  var pad = computePad(digest, password)
    +
       var hLen
       var l = 1
       var DK = Buffer.allocUnsafe(keylen)
    @@ -21,7 +63,7 @@ module.exports = function (password, salt, iterations, keylen, digest) {
     
       for (var i = 1; i <= l; i++) {
         block1.writeUInt32BE(i, salt.length)
    -    var U = createHmac(digest, password).update(block1).digest()
    +    var U = hmac(pad, block1)
     
         if (!hLen) {
           hLen = U.length
    @@ -33,7 +75,7 @@ module.exports = function (password, salt, iterations, keylen, digest) {
         U.copy(T, 0, 0, hLen)
     
         for (var j = 1; j < iterations; j++) {
    -      U = createHmac(digest, password).update(U).digest()
    +      U = hmac(pad, U)
           for (var k = 0; k < hLen; k++) T[k] ^= U[k]
         }
     
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

5

News mentions

0

No linked articles in our index yet.