#
561
2025/12/4
今日のトレンド

npm感染防御とDRYの落とし穴

どうもー、おはようございます。zenncastパーソナリティのマイクです。
今日は2025年12月5日、金曜日の朝7時を少し回ったところでございます。
この時間は、技術情報共有プラットフォーム「Zenn」で、いまホットに読まれている記事たちを、朝イチでまとめてチェックしていきます。通勤・通学のお供に、耳だけ貸してもらえたらうれしいです。

今日はお便りはお休みということで、そのぶん記事紹介をみっちりやっていきましょう。

さて、今日紹介する記事は全部で5本です。セキュリティから設計の話、新言語デザイン、TypeScriptのこれから、そしてNode.jsランタイム管理まで、フルコースでお届けします。

まず1本目。タイトルは「【npm】11月21日以降にnpm installした人へ - Shai-Hulud感染チェック & 多層防御ガイド」。
これは、11月21日以降に npm install を実行した開発者さん、全員一度は耳を傾けてほしい内容です。サプライチェーン攻撃「Shai-Hulud 2.0」というマルウェアが話題になっていますが、その感染チェックの具体的な手順と、今後どう防御していくかの“実践ガイド”になっています。
ポイントは三段構えの多層防御。「入れない」「実行させない」「見逃さない」。まず「入れない」では、npm の minimumReleaseAge や Aikido Safe Chain を使って、新しすぎる怪しいパッケージをそもそもインストールしない方針。次に「実行させない」では、npm の ignore-scripts や allow-scripts、pnpm v10 の設定などでライフサイクルスクリプトを制御して、勝手に実行されるスクリプトを止めていきます。そして「見逃さない」では、OSV-Scanner などの SCA ツールで既知の脆弱性を継続的にスキャン。加えて、GitHub に変なリポジトリが作られていないか、「Sha1-Hulud: The Second Coming」という説明文や、`.github/workflows/discussion.yaml`、謎のセルフホストランナー「SHA1HULUD」がいないかをチェック、ローカルに `setup_bun.js` など特定ファイルが紛れ込んでいないかも確認する手順がまとまっています。完璧な防御はないけれど、やれることをちゃんと積み上げてリスクを減らしていこう、という現実的で頼れる記事でした。心当たりがある方は、今日の業務の前に一度チェックしておくと安心かもしれません。

。。。。

続いて2本目。「DRYにしすぎるとコードは干からびる」。
タイトルからして刺さる人、多いんじゃないでしょうか。DRY、つまり「Don’t Repeat Yourself」。同じことを繰り返し書かない、っていう開発の鉄板スローガンですけど、これを“短期効率”だけを見て乱用すると、逆に開発速度を奪ってしまうよ、という話です。
記事の中で繰り返し出てくるのが、「DRYはビジネスルールや知識を一意に保つための原則であって、手続きやワークフローをなんでも一箇所にまとめる話じゃない」という指摘。たとえば「ユーザー名は20文字以内」といった不変条件は、まさに共通化すべきドメインルール。一方で、異なるユースケースを“なんとなく似ているから”と1つの抽象に押し込み始めると、境界が溶けて、責務がどんどん太っていきます。結果として、N+1問題が起きやすくなったり、オプショナル引数だらけの関数が生まれたりして、数週間で開発速度がガタ落ち、というやつですね。
AI時代の今は、「コードを速く書けること」より、「安全に変え続けられる設計」が大事になってきている、とも指摘されています。型や境界をはっきりさせて、ユースケースごとの手順はあえて重複を許すことで、変更しやすさやパフォーマンスの最適化、そしてAIの支援もしやすくなる。共通化は正義、ではなく、どこを共通化してどこは分けるか、を意識的に選ぶことが大事だよね、という話でした。リファクタしすぎて「なんか前より触りづらい…」って経験ある人には、かなり響く内容だと思います。

。。。。

3本目は、言語マニア・コンパイラ好きに刺さるテーマ。「新しくプログラミング言語を作る際に文字列型をどうするべきか」。
プログラミング言語を設計するときに、「文字列」をどう扱うかって、実はかなり厄介で奥が深いテーマなんですよね。記事ではまず、「文字」というあいまいな言葉を避けて、文字列をどう抽象化するかをちゃんと分解しています。例えば、「単なる8ビット列なのか」「エンコーディング付き8ビット列なのか」「UTF-16前提の16ビット列なのか」「Unicodeコードポイント列なのか」「Unicodeスカラー値列なのか」、さらにヌル文字を許すかどうか、といった軸ですね。
実装レベルでは、UTF-8 / UTF-16 / UTF-32 のどれをベースにするか、「Unicodeスカラー値として正しい」ことを型の不変条件として保証するかどうか、内部表現を言語仕様にどこまで露出させるか、ASCII最適化や small string optimization をどうするか、といった話題も取り上げられています。さらに、文字列を不変にするか可変にするか、ランダムアクセスは本当に必要か、スライスや連結をどう効率化するか、ビルダーAPIの役割、Unicodeスカラー値や書記素クラスタ単位のイテレーターの必要性、OSとのやりとりではヌル終端やUnicode対応をどう考えるか、と、かなり網羅的。
C/C++ のワイド文字列や、Haskell の String、Haxe といった“反面教師”的な例から、JS や Ruby、Python、Rust、Go、C#、Swift などたくさんの言語を比較しつつ、「しがらみのない新言語なら、UTF-8ベースで不変文字列+ビルダー+Unicodeスカラー値イテレーターを推奨」「JVM や .NET、JS ターゲットならUTF-16や抽象化も選択肢」といった、かなり現実路線な結論に落とし込んでいます。自作言語に興味がある人はもちろん、普段触っている言語の文字列が「なんでこうなってるんだろう」とモヤモヤしている人にも、背景がよく分かる読みごたえのある記事でした。

。。。。

さあ4本目。「TypeScript 7で消えるtsconfigのレガシー設定。target: es5やbaseUrlにサヨウナラ」。
TypeScript 使いにはインパクト大きめの内容です。TypeScript 7 では、コンパイラが Go 製のネイティブ実装「tsgo」に置き換わって、大体10倍くらい高速化されるという明るいニュースがある一方で、tsconfig のレガシー設定がごっそり整理されます。
まず `strict`。これまではオプション扱いでしたが、7からはデフォルトで有効。つまり、“ゆるいTypeScript”が標準ではなくなっていきます。次に `target`。指定しなければ最新の安定版 ECMAScript 向けの出力になります。そして古いブラウザ向けにおなじみだった `target: es5` は削除。どうしても IE レベルまで落としたい場合は、別途 Babel などで追加トランスパイルが必要になります。
トラブルの元になりがちだった `baseUrl` もついに廃止。今後は Node の Subpath imports や `paths` による明示的マッピングを使ってね、という方針です。`moduleResolution: node10`(`node`)も `exports` に対応していないため削除され、`bundler` や `nodenext` の利用が前提になっていきます。さらに `rootDir` の自動推論もなくなって、デフォルトは`.`固定。`src` をプロジェクトルートにしたい場合は、明示的に指定してあげる必要があります。
移行を助けるために、`baseUrl` や `rootDir` を書き換えてくれる `ts5to6` という補助ツールも用意されていて、「まずは TypeScript 6 で警告を潰しながら7への準備を進めよう」とアドバイスされています。TS プロジェクトを長く運用している人は、ちょっと腰を据えて設定を見直すタイミングかもしれません。

。。。。

そしてラスト5本目。「パッケージマネージャーで Runtime のバージョンを管理する」。
Node.js のバージョン管理といえば、これまでは nvm や nodenv といったツールを使うのが定番でしたが、最近はパッケージマネージャー自身がランタイムを面倒みる流れが出てきています。その中心にあるのが、OpenJS Foundation で標準化が進んでいる `devEngines` という仕組みです。
`devEngines` は、package.json に「開発環境の要件」を書いておいて、パッケージマネージャー側でそれを検証したり、自動インストールしたりするためのフィールド。`runtime` で Node.js などのバージョンを指定して、さらに `onFail` で要件に合わなかったときの挙動を `ignore` / `warn` / `error` / `download` から選びます。
対応状況も整理されていて、npm は v10.9.0 以降で devEngines に対応。ただし `onFail` は `ignore` / `warn` / `error` のみで、`download` はセキュリティ上の懸念から未実装です。一方 pnpm は v10.14.0 以降で devEngines と `onFail: "download"` に対応していて、必要なランタイムを自動でダウンロード可能。yarn は devEngines をサポートする予定はなく、従来どおり `engines` で要件チェックはできるけれど、自動インストールまではしてくれない、という立ち位置です。
チームで「誰がどの Node バージョンを使っているのか分からない」「CI とローカルでバージョンがズレる」といった悩みを抱えている場合は、npm や、とくに pnpm の `devEngines` をうまく使うことで、環境差異のトラブルをかなり減らせそうだな、と思わせてくれる内容でした。

。。。。

というわけで、今日のzenncastは、
・npm サプライチェーン攻撃「Shai-Hulud 2.0」のチェックと多層防御
・DRY原則の落とし穴と、「干からびない」設計の考え方
・新言語設計における文字列型の選び方・考え方
・TypeScript 7 時代に向けた tsconfig レガシー設定の整理
・パッケージマネージャーで行うランタイムバージョン管理、devEngines の活用
この5本を駆け足でご紹介しました。

気になった記事があれば、詳しい内容や元の記事へのリンクは、この番組のショーノートにまとめてありますので、そちらからじっくり読んでみてください。セキュリティ系の話やツールの設定は、聞くだけじゃなくて、ぜひ実際のプロジェクトで手を動かして反映してみてくださいね。

この番組では、感想や質問、「ここをもっと掘り下げてほしい!」といったリクエストも大歓迎です。ラジオネームを添えて、ぜひ気軽に送ってください。取り上げさせていただきます。

それでは、そろそろお別れの時間です。
今日も一日、無理せず、でもちょっとだけワクワクする開発ができますように。
zenncast、パーソナリティのマイクがお送りしました。また次回お会いしましょう。ではではー。

Related episodes

内容の近いエピソードを推薦しています