VYPR
Critical severityOSV Advisory· Published Aug 20, 2025· Updated Nov 3, 2025

Missing type checks leading to hash rewind and passing on crafted data

CVE-2025-9287

Description

Improper Input Validation vulnerability in cipher-base allows Input Data Manipulation.This issue affects cipher-base: through 1.0.4.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

Cipher-base through 1.0.4 fails to validate input types, allowing crafted objects to cause hash state rewind, collisions, or denial of service.

Vulnerability

Overview CVE-2025-9287 is an improper input validation vulnerability in the cipher-base library (up to version 1.0.4). The update method does not enforce that input data is a valid Buffer, string, TypedArray, or DataView. This permits callers to pass crafted objects such as those with a manipulated length property or other non-standard shapes, leading to undefined behavior [1][2].

Exploitation

Details An attacker can supply a specially crafted object (e.g., { length: -x }) to the update method of a hash instance. This can rewind the internal hash state, effectively turning a tagged hash into an untagged hash — a property that some cryptographic libraries rely on for security. Additionally, providing an object with { length: '1e99' } can cause a denial-of-service condition, while objects with overlapping length and enumerable properties can produce hash collisions without matching raw inputs [2]. The proof-of-concept in [2] demonstrates that an attacker can forge a series of values that produce the same digest as a set of legitimate messages.

Impact

Successful exploitation allows input data manipulation that can lead to hash state rewinding (undermining tag integrity), hash collisions (enabling substitution of payloads), or denial of service (application hang or crash). These effects are particularly dangerous in contexts where cipher-base is used as the underlying cryptographic primitive (e.g., in create-hash, create-hmac, or crypto-browserify), as they can break the security assumptions of protocols relying on hash chaining or authentication tags [2].

Mitigation

Status The vulnerability has been addressed in commit 8fd1364 [3], which adds explicit type checks in the update method: it now validates that input is a Buffer, a string, a TypedArray, or a DataView, throwing an Error for any other type. The fix is available in versions after 1.0.4. Users should update to the latest version of cipher-base and its dependents such as create-hash. No workaround is known for unpatched versions [2][3].

AI Insight generated on May 19, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
cipher-basenpm
< 1.0.51.0.5

Affected products

2
  • Browserify/Cipher BaseOSV2 versions
    v1.0.1, v1.0.2, v1.0.3, …+ 1 more
    • (no CPE)range: v1.0.1, v1.0.2, v1.0.3, …
    • (no CPE)range: <=1.0.4

Patches

1
8fd136432ca2

[Fix] return valid values on multi-byte-wide TypedArray input

https://github.com/browserify/cipher-baseNikita SkovorodaNov 16, 2024via ghsa
3 files changed · +70 1
  • .eslintrc+5 0 modified
    @@ -7,6 +7,11 @@
         "func-style": "off",
       },
     
    +  "globals": {
    +    "Uint8Array": false,
    +    "Uint16Array": false,
    +  },
    +
       "overrides": [
         {
           "files": [
    
  • index.js+40 1 modified
    @@ -22,8 +22,47 @@ function CipherBase(hashMode) {
     }
     inherits(CipherBase, Transform);
     
    +var useUint8Array = typeof Uint8Array !== 'undefined';
    +var useArrayBuffer = typeof ArrayBuffer !== 'undefined'
    +	&& typeof Uint8Array !== 'undefined'
    +	&& ArrayBuffer.isView
    +	&& (Buffer.prototype instanceof Uint8Array || Buffer.TYPED_ARRAY_SUPPORT);
    +
     CipherBase.prototype.update = function (data, inputEnc, outputEnc) {
    -	var bufferData = typeof data === 'string' ? Buffer.from(data, inputEnc) : data;
    +	var bufferData;
    +	if (data instanceof Buffer) {
    +		// No need to do anything
    +		bufferData = data;
    +	} else if (typeof data === 'string') {
    +		// Convert strings to Buffer
    +		bufferData = Buffer.from(data, inputEnc);
    +	} else if (useArrayBuffer && ArrayBuffer.isView(data)) {
    +		/*
    +		 * Wrap any TypedArray instances and DataViews
    +		 * Makes sense only on engines with full TypedArray support -- let Buffer detect that
    +		 */
    +		bufferData = Buffer.from(data.buffer, data.byteOffset, data.byteLength);
    +	} else if (useUint8Array && data instanceof Uint8Array) {
    +		/*
    +		 * Uint8Array in engines where Buffer.from might not work with ArrayBuffer, just copy over
    +		 * Doesn't make sense with other TypedArray instances
    +		 */
    +		bufferData = Buffer.from(data);
    +	} else if (
    +		Buffer.isBuffer(data)
    +		&& data.constructor
    +		&& data.constructor.isBuffer
    +		&& data.constructor.isBuffer(data)
    +	) {
    +		/*
    +		 * Old Buffer polyfill on an engine that doesn't have TypedArray support
    +		 * Also, this is from a different Buffer polyfill implementation then we have, as instanceof check failed
    +		 * Convert to our current Buffer implementation
    +		 */
    +		bufferData = Buffer.from(data);
    +	} else {
    +		throw new Error('The "data" argument must be of type string or an instance of Buffer, TypedArray, or DataView.');
    +	}
     
     	var outData = this._update(bufferData);
     	if (this.hashMode) {
    
  • test/index.js+25 0 modified
    @@ -128,3 +128,28 @@ test('encodings', function (t) {
     		st.equals(txt, enc);
     	});
     });
    +
    +test('handle UInt16Array', function (t) {
    +	function Cipher() {
    +		CipherBase.call(this, 'finalName');
    +		this._cache = [];
    +	}
    +	inherits(Cipher, CipherBase);
    +	Cipher.prototype._update = function (input) {
    +		t.ok(Buffer.isBuffer(input));
    +		this._cache.push(input);
    +	};
    +	Cipher.prototype._final = function () {
    +		return Buffer.concat(this._cache);
    +	};
    +
    +	if (ArrayBuffer.isView && (Buffer.prototype instanceof Uint8Array || Buffer.TYPED_ARRAY_SUPPORT)) {
    +		var cipher = new Cipher();
    +		var final = cipher.update(new Uint16Array([1234, 512])).finalName('hex');
    +		t.equals(final, 'd2040002');
    +	} else {
    +		t.skip('ArrayBuffer.isView and/or TypedArray not fully supported');
    +	}
    +
    +	t.end();
    +});
    

Vulnerability mechanics

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

References

6

News mentions

0

No linked articles in our index yet.