Error [ERR_OSSL_EVP_UNSUPPORTED]

digital envelope routines::unsupported の直し方(Node.js の ERR_OSSL_EVP_UNSUPPORTED)

FIX SUMMARY verified
Applies when
node:18-alpinewebpack 4 / CRAOpenSSL 3 hashing

Verified: reproduced in node:18-alpine, then the ERR_OSSL_EVP_UNSUPPORTED signature was gone after the fix (exit 0).

npm run build(webpack、Create React App、vue-cli、Angular など)が、次のエラーで突然落ちるようになったら、原因はほぼ確実に Node のバージョンを上げたことです。

Error: error:0308010C:digital envelope routines::unsupported

エラーの末尾には code: 'ERR_OSSL_EVP_UNSUPPORTED' が付きます。ビルドツール上では次のような表示になることもありますが、原因はすべて同じです。

Module build failed: Error: error:0308010C:digital envelope routines::unsupported
opensslErrorStack: [ 'error:03000086:digital envelope routines::initialization error' ]

急いでビルドを通したいだけなら、NODE_OPTIONS=--openssl-legacy-provider を付けるのが手っ取り早い対処です。ただしこれは一時しのぎで、常用すべきではありません。まずはなぜ出るのかを一目で確認してください。

まず node -v を確認する

このエラーは、あなたのコードが変わったから出るのではありません。Node に同梱される OpenSSL のメジャーバージョンが変わったから出ます。

Node のバージョン同梱 OpenSSLmd4 などの旧アルゴリズム
Node 16 系OpenSSL 1.1.1既定で使える(エラーにならない)
17 以上(18 / 20 / 22 / 24 …)OpenSSL 3.x既定で無効。使うと ERR_OSSL_EVP_UNSUPPORTED

(境界は Node 17 で OpenSSL 3 に上がった点です。16 系までは OpenSSL 1.1.1 系でした。)

OpenSSL 3 では、md4・RC4・RIPEMD-160・DES といった古い暗号が 「legacy プロバイダ」に隔離され、既定では読み込まれなくなりましたmd5 は default プロバイダに残るので、このエラーの原因にはなりません)。webpack などのビルドツールは、成果物のハッシュ計算に内部で md4 を使っています。そのため「コードは何も変えていないのに、Node を 17 以上に上げた瞬間ビルドが落ちる」という状況が起きます。

典型的なのは 「自分のPC(まだ Node 16)では通るのに、Node を上げた同僚や、新しいイメージの CI でだけ落ちる」 というパターンです。原因を追う前に、まず落ちている環境の node -v を見てください。

再現(最小構成)

ビルドツールを持ち出さなくても、md4 を呼ぶだけで同じエラーになります。

// index.cjs
const crypto = require('crypto');

const hash = crypto.createHash('md4');
hash.update('errfix');
console.log(hash.digest('hex'));

これを Node 18 で実行すると、次のように落ちます(終了コードは 1)。

Error: error:0308010C:digital envelope routines::unsupported
    at new Hash (node:internal/crypto/hash:69:19)
    ...
  library: 'digital envelope routines',
  reason: 'unsupported',
  code: 'ERR_OSSL_EVP_UNSUPPORTED'
}

createHash('md4') の行で、md4 を提供するはずのプロバイダが見つからずに失敗しています。

解決1:まず動かす(--openssl-legacy-provider

いますぐビルドを通したいなら、legacy プロバイダを明示的に有効化します。コードは 1 行も変えません。

# macOS / Linux
export NODE_OPTIONS=--openssl-legacy-provider
npm run build
# Windows PowerShell
$env:NODE_OPTIONS="--openssl-legacy-provider"
npm run build

npm スクリプトに直接埋め込む形でも構いません。

{
  "scripts": {
    "build": "node --openssl-legacy-provider ./node_modules/.bin/webpack"
  }
}

先ほどの再現コードも、node --openssl-legacy-provider index.cjs として実行すればエラーは消え、ハッシュ値が出力されて終了コードは 0 になります。コードは 1 文字も変えず、フラグを足しただけで通ります。

仕組み:OpenSSL 3 のプロバイダ

OpenSSL 3 は暗号アルゴリズムを「プロバイダ」という単位に分割しました。既定で読み込まれるのは default プロバイダで、そこには安全な現行アルゴリズムしか入っていません。md4 のような古いものは legacy プロバイダに移され、明示的に有効化しない限り使えません

--openssl-legacy-provider は、この legacy プロバイダを起動時に読み込ませるフラグです。これで md4 が再び使えるようになり、ビルドツールのハッシュ計算が通ります。

解決2:恒久対応(フラグを外せる状態にする)

--openssl-legacy-provider無効化された古い暗号をわざわざ復活させるフラグです。md4 や RC4 が既定から外されたのは、それらが弱くて危険だからです。フラグを付けっぱなしにするのは、鍵の壊れた古い錠前をあえて使い続けるようなもの——動きはしますが、外せるなら外すべきです。恒久対応は次のどれかです。

  • ビルドツールを Node 17+ 対応済みの版へ上げる。もっとも確実です。webpack 単体なら 5.61.0 以上(このバージョンでハッシュ計算を OpenSSL 非依存の実装に切り替え、Node 17+ で落ちなくなった)。Create React App なら react-scripts を v5 系へ(webpack ^5.64.4 を取り込む)。なお webpack v5 も既定のハッシュは md4 のままなので、「v5 にすれば無条件で直る」ではなく「Node 17+ 対応版に上げる」と捉えてください。必要なら output.hashFunction: 'xxhash64' を明示設定する手もあります。
  • 自分のコードで md4 を使っている場合は、sha256 など OpenSSL 3 の既定プロバイダにあるアルゴリズムへ置き換える。用途が「衝突耐性のいらない一意キー生成」なら置換して差し支えありませんが、ハッシュ値が変わる影響(値の長さが変わる/保存済みのID・ファイル名との互換/キャッシュが一度きり再生成される)だけは確認してください。
  • どうしても Node を上げられない事情があるなら、Node 16 系(OpenSSL 1.1.1 同梱)に留まるのも短期的には有効です。ただし Node 16 はすでにサポート終了しており、これも先送りにすぎません。

順番としては、まず解決1でビルドを通し、その上で解決2でツールを上げてフラグを消す。フラグは「移行までの松葉杖」と割り切ってください。

切り分け(うまくいかないとき)

  • --openssl-legacy-provider を付けても変わらない:フラグが実際のビルドプロセスに渡っていないことが多い。package.json の別スクリプト経由や、ビルドを子プロセスで起動している場合は、そのプロセスに NODE_OPTIONS が引き継がれているか確認する。
  • webpack や CRA ではなく Vite / esbuild などで出た:原因は同じ(OpenSSL 3 で無効化された暗号を使っている)。まず解決1で動かし、そのツールのバージョンを上げてフラグを外す方針は変わらない。
  • 手元では出ないのに CI でだけ出る:手元がまだ Node 16 で、CI が 17 以上のことがある。両方の node -v をそろえて再現環境を合わせる。
  • フラグは常設環境変数にしないNODE_OPTIONS=--openssl-legacy-provider を shell の常設プロファイル(.bashrc など)に入れると、すべての Node プロセスで無効化された弱い暗号が復活します。そのビルドコマンドに限定して渡してください。

検証(machine-verified)

この修正は node:18-alpine のバージョン固定コンテナ内で再現し、修正後に ERR_OSSL_EVP_UNSUPPORTED のシグネチャが消えることを機械で確認しています。

verify — run-case.mjs
$ node run-case.mjs node/err-ossl-evp-unsupported
● reproduce ERR_OSSL_EVP_UNSUPPORTED present ✓
● apply fix exit 0
● re-run ERR_OSSL_EVP_UNSUPPORTED gone ✓
PASS verified · node:18-alpine · signature gone