Skip to main content
Crypto-js Weak Hash: When 1 Iteration Meets ProductionIncident
4 min readFor Security Engineers

Crypto-js Weak Hash: When 1 Iteration Meets Production

What Happened

Security researcher Zemnmez discovered a use-of-weak-hash vulnerability in crypto-js and crypto-es, two widely-used JavaScript cryptography libraries. The vulnerability (CVE-2023-46233 for crypto-js, CVE-2023-46133 for crypto-es) affected all previous versions of both libraries. The issue: password-based key derivation functions defaulted to a single iteration, making brute-force attacks trivial.

The maintainers released patches that changed the default iterations parameter from 1 to 250,000. If you're using either library for password hashing or key derivation, update immediately and verify your implementation.

Timeline

While the exact discovery and disclosure timeline isn't public, here's what we know:

  • Zemnmez identified the vulnerability through code review.
  • Private disclosure was made to the maintainers.
  • CVE identifiers were assigned.
  • Patched versions were released.
  • Security advisories were published through Snyk and other channels.

This represents responsible disclosure working as intended. The researcher gave maintainers time to fix the issue before public disclosure.

Which Controls Failed or Were Missing

Secure defaults were absent. A single iteration in PBKDF2 provides effectively zero protection against brute-force attacks. Modern GPUs can test billions of single-iteration hashes per second. The library shipped with a configuration that any security review should have flagged.

Dependency health monitoring was missing. Crypto-js had been unmaintained for an extended period before this vulnerability surfaced. Organizations using it had no process to identify that their cryptographic library lacked active maintenance.

Automated vulnerability scanning wasn't catching this. The weak default existed in all previous versions, but many teams discovered it only after CVE assignment. Your SAST tools should flag cryptographic functions with insecure parameters, not just known CVE numbers.

Code review missed the implementation risk. If your team reviewed the crypto implementation at all, they likely checked that PBKDF2 was being used (good) but not what iteration count was being passed (critical). The difference between 1 and 250,000 iterations is the difference between minutes and years of brute-force resistance.

What the Relevant Standard Requires

OWASP ASVS v4.0.3 Requirement 2.4.1 specifies that passwords must be protected using approved one-way key derivation functions with a work factor appropriate to the risk. A single iteration fails this requirement categorically.

NIST 800-53 Rev 5 control IA-5(1)(e) requires password-based authentication to use approved cryptographic mechanisms with sufficient computational effort to defeat brute-force attacks. Single-iteration PBKDF2 provides no meaningful computational effort.

PCI DSS v4.0.1 Requirement 8.3.2 mandates strong cryptography for authentication credentials during transmission and storage. While this focuses on transmission, the principle extends to key derivation: weak hashing undermines the entire authentication chain.

ISO/IEC 27001:2022 Annex A.9.4.3 addresses password management systems. Your implementation must protect passwords using cryptographic controls that meet current security standards. This vulnerability demonstrates what happens when you inherit defaults without validating them against those standards.

The standards don't just say "use PBKDF2" — they require appropriate work factors. You're responsible for verifying that your dependencies meet this requirement, not just that they use the right algorithm name.

Lessons and Action Items for Your Team

Audit your cryptographic dependencies now. Don't wait for a CVE. Run this command in your JavaScript projects:

npm ls crypto-js crypto-es

If either appears in your dependency tree, check the version. Anything before the patched release is vulnerable. Update immediately, then verify that your code doesn't override the new default with an explicit low iteration count.

Check your iteration counts explicitly. Even with the patched library, you need to verify your implementation. Search your codebase for PBKDF2 calls and confirm they're using at least 250,000 iterations (the new default) or higher. If you're supporting legacy systems that can't handle that computational load, document the risk and create a migration plan.

Add dependency health to your security reviews. Before adopting any cryptographic library, check:

  • Last commit date (if over 6 months, investigate why)
  • Number of open security issues
  • Maintainer response time to vulnerabilities
  • Whether the project accepts security reports through a private channel

Crypto-js's lack of maintenance should have triggered an evaluation of alternatives before this vulnerability surfaced.

Configure your SAST tools to flag weak crypto parameters. Don't rely solely on CVE databases. Your static analysis should catch:

  • PBKDF2 with iteration counts below 100,000
  • Any use of MD5 or SHA-1 for password hashing
  • Custom cryptographic implementations (you shouldn't be writing these)

Create a cryptographic inventory. You need a list of every library and function in your codebase that performs:

  • Password hashing
  • Key derivation
  • Encryption/decryption
  • Digital signatures

When a vulnerability like this drops, you should know within minutes whether you're affected and where. If you're scrambling to grep your codebase, you don't have adequate visibility.

Test your incident response for dependency vulnerabilities. When the next crypto library vulnerability hits (and it will), can you:

  • Identify affected systems within 1 hour?
  • Deploy patches to dev/staging within 4 hours?
  • Complete production deployment within 24 hours?

If not, run a tabletop exercise using this crypto-js incident as the scenario. Find the gaps before you're under pressure.

The crypto-js vulnerability wasn't sophisticated. It was a weak default that survived because teams assumed the library had made secure choices. Your job is to verify those assumptions, not inherit them.

PBKDF2

Topics:Incident

You Might Also Like