Dependency Management

Why We Abandoned NPM Packages for Cryptography

April 18, 2026
7 Min Read

For years, the standard way to encrypt data in a JavaScript application was to run npm install crypto-js. It was easy, ubiquitous, and heavily documented. But if you are building a modern, secure application today, relying on third-party cryptographic libraries is a massive architectural liability.

When we architected ZeroKey, we made a strict decision: Zero external dependencies for cryptographic operations. Here is why we abandoned NPM for cryptography, and why you should migrate to native browser APIs immediately.

The Threat: Supply Chain Attacks

Every time you import a package from NPM, you are inherently trusting the maintainer of that package—and the maintainers of all of their sub-dependencies.

In recent years, we have seen a massive rise in Supply Chain Attacks. Hackers compromise a popular open-source developer's NPM account and inject malicious code into a widely used package. If your application relies on an external library for AES encryption, a compromised package update could silently exfiltrate your users' plaintext passwords and encryption keys before the data is ever scrambled.

Note: As of recently, the popular crypto-js library is officially unmaintained, meaning no future security patches will be released. Using it in production is now highly discouraged.

The Performance Cost: Bundle Bloat

Beyond security, shipping cryptography libraries in your JavaScript bundle destroys your application's load time.

  • Heavy Payloads: Importing a full suite of hashing algorithms, block ciphers, and encoding utilities can easily add 100kb+ of parsed JavaScript to your client's browser.
  • Single-Threaded Bottlenecks: JavaScript is single-threaded. When a third-party library performs 100,000 iterations of PBKDF2 to hash a password, it completely blocks the main thread, freezing your UI and causing the browser to stutter.

The Solution: The Native Web Crypto API

Modern browsers already have military-grade cryptographic libraries written in highly optimized C++ built right into them. You can access these engines directly using window.crypto.subtle.

Advantage 1: Absolute Security

Because the Web Crypto API is part of the browser's core engine, it cannot be hijacked by a rogue NPM package update. It is audited by the security teams at Google, Apple, and Mozilla.

Advantage 2: Hardware Acceleration

The Web Crypto API doesn't run in the standard JavaScript event loop. It offloads heavy cryptographic math (like AES-GCM encryption and RSA key generation) directly to the device's hardware, running asynchronously. This means you can encrypt a 2MB file without freezing the user's screen.

Example: AES-256-GCM without Dependencies

Here is how simple it is to encrypt data natively, with zero NPM installs required:

// No import statements needed!

async function nativeEncrypt(text, key) {
    const encoder = new TextEncoder();
    const encodedData = encoder.encode(text);
    
    // Generate an Initialization Vector
    const iv = window.crypto.getRandomValues(new Uint8Array(12));

    // Perform the encryption asynchronously using native browser C++ engines
    const ciphertext = await window.crypto.subtle.encrypt(
        { name: "AES-GCM", iv: iv },
        key,
        encodedData
    );

    return { ciphertext, iv };
}

Zero Dependencies. Zero Knowledge.

We built ZeroKey to be as lightweight and secure as mathematically possible. If you audit our frontend source code, you will find exactly zero cryptographic dependencies in our package.json.

Every single AES encryption, PBKDF2 hash, and CSPRNG token is generated entirely by your own device's hardware through native Web APIs.

Conclusion

Every dependency you add to your project increases your attack surface. When it comes to handling your users' most sensitive data, you must remove the middlemen. Drop the legacy libraries, embrace the Web Crypto API, and let the browser do the heavy lifting safely.