Skip to main content
DevOpsintermediate

Fix "digital envelope routines::unsupported" in Node

Fix `error:0308010C:digital envelope routines::unsupported` (ERR_OSSL_EVP_UNSUPPORTED). Why Node 17+ broke webpack 4, and the real fix.

9 min readUpdated August 2026

After upgrading Node, a build that worked yesterday fails with an OpenSSL error:

Error: error:0308010C:digital envelope routines::unsupported
    at new Hash (node:internal/crypto/hash:103:19)
    at Object.createHash (node:crypto:146:10)
    ...
  opensslErrorStack: [
    'error:03000086:digital envelope routines::initialization error',
    'error:0308010C:digital envelope routines::unsupported'
  ],
  library: 'digital envelope routines',
  reason: 'unsupported',
  code: 'ERR_OSSL_EVP_UNSUPPORTED'
}

Nothing in your project changed. Node 17 upgraded its bundled OpenSSL to version 3, and OpenSSL 3 moved a set of old algorithms — MD4 among them — into an optional "legacy provider" that is disabled by default. Webpack 4 hashes module identifiers with MD4. The moment Node stopped offering MD4, every webpack 4 build started failing this way.

Check which OpenSSL you are on:

node -p "process.versions.openssl"
# 3.6.2   → legacy provider off by default; this error is possible
# 1.1.1x  → Node 16 or earlier; unaffected

Why This Happens

createHash('md4') used to work because OpenSSL 1.1 offered every algorithm it shipped. Under OpenSSL 3, providers gate them, and the legacy provider must be loaded explicitly. You can see the whole mechanism in two commands:

node -e "require('crypto').createHash('md4')"
# Error: error:0308010C:digital envelope routines::unsupported

node --openssl-legacy-provider -e "console.log(require('crypto').createHash('md4').update('a').digest('hex'))"
# bde52cb31de33e46245e05fbdbd6fb24

The error code itself is unhelpfully generic — 0308010C names an OpenSSL subsystem, not the algorithm. The algorithm is in the stack trace, in the frame that called createHash.

Match your situation before choosing a fix:

What you are runningCauseFix
webpack 4, or a tool that bundles itMD4 default hashFix 1 — upgrade
react-scripts 4 or earlierwebpack 4 underneathFix 1 — upgrade
webpack 5, error persistsExplicit md4 in config or a pluginFix 2 — change the hash function
Your own createHash('md4')Legacy algorithm in your codeFix 3 — switch algorithm
Cannot upgrade right nowFix 4 — the legacy flag, temporarily

Fix 1: Upgrade the Bundler (The Real Fix)

Webpack 5 uses a supported hash function, so upgrading removes the cause rather than working around it:

npm install --save-dev webpack@5 webpack-cli@latest

For create-react-app, the equivalent is react-scripts 5, which moved to webpack 5:

npm install --save-dev react-scripts@latest

Check what you are actually on before and after — the bundler is often a transitive dependency you never installed directly:

npm ls webpack

Other toolchains have their own thresholds: Vue CLI 5, Angular 12+, and Next.js 12+ are all on webpack 5 or their own bundler and are unaffected. If you are on an older major of any of those, upgrading the framework is the path.

Fix 2: webpack 5 and Still Failing

Webpack 5 does not use MD4 by default, so if the error survives the upgrade, something is asking for it explicitly. Search your configuration:

grep -rn "md4\|hashFunction" webpack.config.js config/ 2>/dev/null

Set a supported algorithm if you find one:

// webpack.config.js
module.exports = {
  output: {
    hashFunction: 'xxhash64',   // or 'sha256'
  },
};

If nothing in your own config matches, a plugin or loader is responsible. The stack trace names it — read the frames just below Object.createHash and upgrade that package.

Advertisement

Fix 3: MD4 in Your Own Code

If your code calls it directly, the fix is to choose a different algorithm — and which one depends on what the hash is for:

const crypto = require('crypto');

crypto.createHash('md4');       // fails on OpenSSL 3
crypto.createHash('sha256');    // use for anything security-relevant
crypto.createHash('sha1');      // still available, but not for security

MD4 has been cryptographically broken for decades. If it was protecting anything — signatures, integrity checks, password material — this error has surfaced a real problem and sha256 is the answer. If it was only ever a fast non-cryptographic cache key, xxhash64 or sha1 is fine.

Fix 4: The Legacy Provider Flag (Temporary)

When you cannot upgrade today, re-enable the legacy algorithms:

export NODE_OPTIONS=--openssl-legacy-provider
npm run build

Make it survive across contributors by putting it in package.json rather than everyone's shell:

{
  "scripts": {
    "start": "cross-env NODE_OPTIONS=--openssl-legacy-provider react-scripts start",
    "build": "cross-env NODE_OPTIONS=--openssl-legacy-provider react-scripts build"
  }
}

cross-env is worth the dependency here — the bare NODE_OPTIONS=... command form is shell syntax that PowerShell and cmd do not accept. Without it, Windows contributors get a different, more confusing failure. The manual equivalents:

$env:NODE_OPTIONS="--openssl-legacy-provider"   # PowerShell
set NODE_OPTIONS=--openssl-legacy-provider      :: cmd

Treat this as a stopgap with a deadline. The flag re-enables broken algorithms for the whole process, so never set it on a server that also performs real cryptography — you would be re-enabling MD4 and friends for your application code, not just your bundler. It is defensible for a build step on a CI runner. It is not defensible in production runtime configuration, and it is not a substitute for the upgrade.

Verify the Fix

Run the build that was failing:

npm run build

Confirm you are no longer relying on the flag — this should now succeed with it explicitly unset:

env -u NODE_OPTIONS npm run build

And confirm the bundler you expect is the one being used:

npm ls webpack
node -p "process.versions.openssl"

If the build passes without NODE_OPTIONS, the underlying cause is genuinely gone and you can delete the flag from your scripts.

Prevention

  • Upgrade the bundler rather than carrying the flag. Every month the flag stays in package.json, it becomes more likely someone copies it into a runtime environment.
  • Pin Node in .nvmrc and in engines so a developer or CI runner cannot silently jump a major version mid-project.
  • Read process.versions.openssl in CI when debugging a build that works locally and fails on the runner — an OpenSSL 1.1 laptop and an OpenSSL 3 runner produce exactly this split.
  • Never use MD4 or MD5 for anything security-relevant. If this error caught one in your own code, the correct response is sha256, not the legacy provider.

Frequently Asked Questions

Find answers to common questions

Node's bundled OpenSSL 3 refused to use a legacy hash algorithm, almost always MD4. Node 17 upgraded to OpenSSL 3, which moved MD4 and other old algorithms into an optional legacy provider that is off by default, and webpack 4 hashes with MD4 by default.

The durable fix is to stop using the legacy algorithm — upgrade to webpack 5 or react-scripts 5, which hash with a supported algorithm. If you cannot upgrade yet, run Node with --openssl-legacy-provider as a temporary unblock while you plan the upgrade.

It is safe in the sense that it re-enables algorithms Node already ships, and for build-time hashing MD4 is used as a cache key rather than for security. It is still a workaround: it re-enables broken cryptography process-wide, so never set it on a server that also handles real cryptographic work.

Node 17 bundled OpenSSL 3 for the first time. Nothing in your project changed — the algorithm your bundler was already using stopped being available by default. That is why the error appears immediately after a Node upgrade with no code change.

Upgrade react-scripts to version 5 or later, which uses webpack 5. If you are pinned to react-scripts 4, set NODE_OPTIONS=--openssl-legacy-provider in the start and build scripts as a stopgap, and treat it as technical debt rather than a solution.

Yes for the MD4 default — webpack 5 uses a supported hash function. A plugin or loader in your build can still request MD4 explicitly, so if the error survives the upgrade, search your config and dependencies for output.hashFunction or a hard-coded md4.

PowerShell and cmd do not accept the inline VAR=value syntax. Use '$env:NODE_OPTIONS="--openssl-legacy-provider"' in PowerShell or 'set NODE_OPTIONS=--openssl-legacy-provider' in cmd, or add cross-env to your package.json scripts so one line works on every platform.

Run 'node -p "process.versions.openssl"'. Anything starting with 3 means the legacy provider is off by default and this error is possible. Node 16 and earlier report 1.1.x and are unaffected.

That is an OpenSSL error code, not a Node one, so it names the OpenSSL subsystem rather than the algorithm your code asked for. The algorithm appears in the stack trace instead — look for the createHash call and the bundler frame directly beneath it.