0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

「WSLでnpmが証明書を読めない」の正体は、LinuxとWindowsの"パスのすれ違い"だった

0
Posted at

WSLで npm install を叩くと、SELF_SIGNED_CERT_IN_CHAIN で落ちる。証明書もちゃんと用意して、.bashrcNODE_EXTRA_CA_CERTS まで設定したのに、なぜか通らない。──これは設定ミスでもnpmのバグでもない。WSLで動いていたnpmが実は"Windows版"で、Linuxのパスに置いた証明書を、そもそも読めていなかっただけだ。

社内プロキシやゼロトラスト環境で開発している人なら、一度は踏む落とし穴だと思います。私が実際にハマって、原因を突き止めて、直すまでの過程をそのまま置いておきます。

大前提:npmはどうやって証明書を検証しているか

npmがレジストリ(https://registry.npmjs.org)からパッケージを取るとき、相手のサーバーは「私は本物です」という証明書を提示します。Node.jsは手元の信頼できる認証局(CA)のリストと照合し、正しく署名されていれば通信を許可する。これがHTTPSの基本です。

ところが社内プロキシやゼロトラスト製品は、セキュリティ検査のために通信を一度復号して中継します。このときnpmが受け取るのは本物の証明書ではなく、プロキシが独自に発行し直した証明書です。その発行元(独自CA)はNode.js標準の信頼リストに入っていないので、「知らない発行元だ」と弾かれる。

だから、その独自CAを「信頼していいよ」とNode.jsに教える必要があります。それが環境変数 NODE_EXTRA_CA_CERTS の役割です。標準のCAリストに加えて、指定したCAも信頼するようになります。

export NODE_EXTRA_CA_CERTS=~/corp-proxy.pem

これを .bashrc に書いておけば、ターミナルを開くたびに効く。──はずでした。

「証明書を読めない」の正体

設定は正しいのに、npm ping(レジストリへの疎通確認)は無情に落ちます。

$ npm ping
npm notice PING https://registry.npmjs.org/
npm error code SELF_SIGNED_CERT_IN_CHAIN
npm error errno SELF_SIGNED_CERT_IN_CHAIN
npm error request to https://registry.npmjs.org/-/ping failed, reason: self-signed certificate in certificate chain
npm error A complete log of this run can be found in: C:\Users\<username>\AppData\Local\npm-cache\_logs\...

ここに決定的な手がかりがあります。最終行のログパスが C:\...(Windows側) になっている。WSLで作業しているはずなのに、なぜWindowsのパスが出るのか。ここが真犯人でした。

原因① WSLで叩いたnpmが、実はWindows版だった

which で実体を確かめると、正体が見えます。

$ which -a npm
/mnt/c/Program Files/nodejs//npm     # ← Cドライブ = Windows側

$ file "/mnt/c/Program Files/nodejs/node.exe"
node.exe: PE32+ executable for MS Windows   # ← 正真正銘のWindowsバイナリ

WSLは既定でWindowsのPATHをLinux側に引き継ぎます。そのため npm と打つと、/mnt/c/Program Files/nodejs(= C:\Program Files\nodejs)にあるWindows版のnpmが引っかかって起動していたのです。「PATHの共有」「exeをWindowsに委譲するinterop」「Cドライブを見せる /mnt/c」──この3点セットで、WSLからWindowsのNode.jsが動く。便利な仕組みですが、今回はこれが仇になりました。

原因② Windows版nodeはLinuxのパスを読めない

ここで、さっき設定した証明書のパスを思い出してください。

NODE_EXTRA_CA_CERTS = /home/<username>/corp-proxy.pem   ← Linuxのパス

これを受け取るのはWindows版のNode.jsです。そしてWindowsは、/home/... というLinux流のパスを理解できない。正確には、先頭のスラッシュを「今のドライブのルート」と解釈し、C:\home\<username>\corp-proxy.pem というまったく別の場所を探しに行ってしまう。当然そんなファイルは無いので、証明書は読み込まれない。

WSL上のファイルは、Windowsから見ると別の表記になります。wslpath で変換すると一目瞭然です。

$ wslpath -w /home/<username>/corp-proxy.pem
\\wsl.localhost\Ubuntu\home\<username>\corp-proxy.pem

つまりWindows版nodeに届けるには、/home/... ではなく \\wsl.localhost\...C:\... の形にしてやらないといけない。

結果:設定は正しいのに、渡す相手とパス形式が噛み合っていない

証明書ファイルは存在する。中身も正しい。.bashrc の設定も間違っていない。それでも動かなかったのは、「渡す相手(Windows node)」と「パスの形式(Linuxパス)」がすれ違っていたからです。私たちは正しいメモを、それを読めない相手に手渡していた。

だからこそ:解決の手順

原因がパスのすれ違いなら、直し方は「Windows版nodeが読める場所と方法で渡す」の一択です。npmの cafile 設定を使います。

① 証明書をWindowsから見えるパスに置く

cp ~/corp-proxy.pem "/mnt/c/Users/<username>/corp-proxy.pem"
# = C:\Users\<username>\corp-proxy.pem に配置される

② Windows側の .npmrccafile を登録する

npm config set cafile "C:/Users/<username>/corp-proxy.pem"

パスは /(フォワードスラッシュ)で書いておくと、バックスラッシュのエスケープで悩まずに済みます。strict-ssltrue のまま、つまり証明書の検証は有効なままで大丈夫です。

npm ping で検証する

$ npm ping
npm notice PING https://registry.npmjs.org/
npm notice PONG 366ms

PONG が返ってきました。証明書検証を通過して、レジストリと通信できています。長かった。

まとめ:証明書は"渡す相手のOS"に合わせて置く

今回の一件は、突き詰めれば 「パスのすれ違い」問題でした。

  • 症状は SELF_SIGNED_CERT_IN_CHAIN。一見すると証明書の問題に見える。
  • でも真因は「WSLで動いていたnpmが実はWindows版で、Linuxパスの証明書を読めなかった」こと。
  • 直し方は、渡す相手(Windows node)とパス形式(Windowsパス)を揃えるだけ。

そして、もっと根本的な教訓もあります。WSLで開発するなら、Linux版のnodeをちゃんと入れる(nvmなど)か、あるいはNode非依存の公式ネイティブインストーラを使う。どちらかにしておけば、「WSLなのに実体はWindows」という"すれ違い"自体が起きません。混在が、すべての混乱の入り口だった。

付録:ついでに学んだこと

このデバッグの過程で拾った小ネタも置いておきます。

  • .bashrc を変えたら source ~/.bashrc。今開いているターミナルに即反映したいならこれ。新しく開くターミナルなら起動時に自動で読まれるので不要。
  • Node.jsはbashの上で動いているわけではない。bashは「起動係」で、実行の瞬間に環境変数を渡しているだけ。だから渡した相手がLinuxかWindowsかで、こういう差が出る。
  • Windowsの Docker は WSL 2 が土台。「DockerのためにWSLを入れる」は遠回りでも何でもなく、そのものズバリ正しい判断。
  • claudecodeの npm install と公式インストーラの違い。前者はNode.jsという外部ランタイム前提のJSプログラム。後者はランタイム同梱の単体バイナリで、今回のような"どのNode問題"を最初から回避できる。ツールを入れるなら、Node非依存の公式インストーラの方が事故が少ない。

同じ環境で消耗している人の助けになれば。「WSLなのに、動いていたのはWindowsだった」──たったこれだけの話だ。


推奨タグ: WSL npm Node.js 証明書 Windows

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?