CVEReports
Reports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Reports
  • Sitemap

Company

  • About
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Powered by Google Gemini & CVE Feed

|
•

CVE-2025-9287
CVSS 9.1|EPSS 0.12%

Broken Base: How `cipher-base` Rewound the Crypto Stack

Amit Schendel
Amit Schendel
Senior Security Researcher•August 20, 2025•6 min read
PoC AvailableNot in KEV

Executive Summary (TL;DR)

The `cipher-base` package, a dependency of widely used libraries like `crypto-browserify`, failed to correctly handle `TypedArray` inputs. This improper validation allows attackers to pass malicious data structures that "rewind" or corrupt the internal hash state, leading to potential signature forgeries and collision attacks in browser environments.

A critical flaw in the foundational `cipher-base` package allows attackers to manipulate cryptographic states and bypass integrity checks in browser-based applications.

The Invisible Foundation

In the sprawling, chaotic metropolis of the JavaScript ecosystem, there are skyscrapers like React and sprawling suburbs like Express. But underneath the pavement, in the sewers and utility tunnels, live the tiny, unloved libraries that keep the lights on. cipher-base is one of those libraries. You didn't install it. You probably don't even know it's there. But if you've ever run npm install crypto-browserify, create-hash, or create-hmac to do cryptography in a browser, cipher-base is sitting in your node_modules, quietly doing the heavy lifting.

Its job is deceptively simple: it provides the abstract base class for cryptographic streams. It handles the boring stuff—buffering data, managing internal states, and normalizing input before handing it off to the actual hashing algorithms (like SHA-256 or MD5). It is the gatekeeper. It decides what data gets hashed and how.

And that is exactly why CVE-2025-9287 is terrifying. When the gatekeeper falls asleep, it doesn't matter how strong your castle walls (the hashing algorithms) are. If the base class can be tricked into feeding garbage—or worse, manipulated garbage—into the crypto engine, the entire premise of data integrity evaporates. This isn't just a bug; it's a structural failure in the foundation of browser-based cryptography.

The 'Not a String' Fallacy

The vulnerability here is a classic case of "Developer Assumption Syndrome." The code in cipher-base versions 1.0.4 and earlier had a very specific worldview: data is either a String, or it is a Buffer. There was no middle ground in its philosophy.

When the .update(data) method was called, the library performed a check that feels almost insultingly simple for a cryptography library:

var bufferData = typeof data === 'string' 
    ? Buffer.from(data, inputEnc) 
    : data;

Do you see the horror? If data is a string, it converts it to a Buffer. Great. But if data is anything else—a Uint16Array, a Float32Array, a DataView, or a custom object with a length property—it just passes it through raw.

This is the coding equivalent of a bouncer saying, "If you aren't wearing sneakers, you must be wearing dress shoes, come on in." Meanwhile, the attacker just walked in wearing flippers. Because Node.js's native crypto module is flexible, it attempts to digest these weird inputs. But cipher-base operates on the assumption that it's handling standard 8-bit bytes. When you pass a Uint16Array (where each element is 2 bytes), the internal offset calculations desynchronize. The library thinks it's reading byte 1, but it's reading the lower half of a 16-bit integer.

Code Autopsy: The Smoking Gun

Let's look at the fix to understand the severity of the break. The patch introduced in version 1.0.5 doesn't just add a type check; it fundamentally changes how memory is viewed. The developers realized that blindly trusting input was a suicide pact.

Here is the logic that patches the hole:

// The Fix (simplified)
if (data instanceof Buffer) {
    bufferData = data;
} else if (typeof data === 'string') {
    bufferData = Buffer.from(data, inputEnc);
} else if (useArrayBuffer && ArrayBuffer.isView(data)) {
    // The critical addition:
    // Explicitly grab the underlying buffer based on offset and length
    bufferData = Buffer.from(data.buffer, data.byteOffset, data.byteLength);
} else {
    throw new Error('The "data" argument must be of type string or an instance of Buffer, TypedArray, or DataView.');
}

[!NOTE] Why does this matter? A TypedArray is just a "view" into a raw memory buffer. If you create a Uint8Array that represents a slice of a larger buffer, simply passing the array object might not point to the data you think it does. The fix forces the library to respect the byteOffset and byteLength, ensuring the crypto engine hashes exactly what the user intended, not random adjacent memory.

The Exploit: Rewinding Reality

This is where it gets dark. The analysis indicates that this isn't just about crashing the application (though you could certainly do that). The real danger is State Manipulation.

Because cipher-base manages the internal state of the hash (buffering partial data until a block size is reached), passing a crafted object or a malformed TypedArray can confuse the buffering logic. An attacker can trigger a condition where the internal buffer pointer is reset or moved incorrectly.

Imagine an application verifying a file signature:

  1. App calls hash.update(header)
  2. App calls hash.update(malicious_payload)
  3. App calls hash.update(footer)

If the malicious_payload is a crafted Uint16Array that tricks the buffering logic, it could effectively "rewind" the hash state, overwriting the header data in the internal buffer before the hash function processes it.

The result? The final hash matches a legitimate file, but the content processed was different. This is a Second Preimage Attack enabler. In the context of create-hmac, it breaks the message authentication entirely.

The Impact: Why Browser Crypto is Fragile

This vulnerability highlights the precarious nature of polyfills. We use crypto-browserify so we can write Isomorphic JavaScript—code that runs on both the server and the browser. But on the server (Node.js), these operations are handled by C++ bindings to OpenSSL. In the browser, they are handled by JavaScript logic like cipher-base.

If you are using a browser-based wallet, a secure messaging app that encrypts in the frontend, or a JWT verification routine running in a Service Worker, you are likely relying on this stack. An attacker exploiting CVE-2025-9287 doesn't need to hack the server; they just need to feed your frontend code a weirdly typed array.

By manipulating the hash input, they can forge signatures or bypass checksum verifications. It turns "End-to-End Encryption" into "End-to-Attacker-to-End Encryption".

Official Patches

NPMPatched version 1.0.5 release on NPM

Fix Analysis (1)

Technical Appendix

CVSS Score
9.1/ 10
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:H
EPSS Probability
0.12%
Top 100% most exploited

Affected Systems

crypto-browserifycreate-hashcreate-hmacBrowser-based cryptocurrency walletsFrontend JWT verification libraries

Affected Versions Detail

ProductAffected VersionsFixed Version
cipher-base
crypto-browserify ecosystem
<= 1.0.41.0.5
AttributeDetail
CWE IDCWE-20 (Improper Input Validation)
CVSS9.1 (Critical)
Attack VectorNetwork / Local (Context Dependent)
ImpactIntegrity Violation / State Manipulation
Root CauseType Confusion in Buffer Handling
Fix Version1.0.5

MITRE ATT&CK Mapping

MITRE ATT&CK Mapping

T1565.002Data Manipulation: Transmitted Data Manipulation
Impact
T1203Exploitation for Client Execution
Execution
CWE-20
Improper Input Validation

The product does not validate or incorrectly validates input that can affect the control flow or data flow of a program.

Exploit Resources

Known Exploits & Detection

GitHubDiscussion regarding TypedArray handling issues leading to state corruption.

Vulnerability Timeline

Vulnerability Timeline

Vulnerability identified in input validation logic.
2025-01-10
Patch proposed in Pull Request #23.
2025-01-15
cipher-base v1.0.5 released.
2025-01-20

References & Sources

  • [1]PR #23: Fix TypedArray handling
  • [2]crypto-browserify Repository

Subscribe to updates

Get the latest CVE analysis reports delivered to your inbox.

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.