adm-zip: 圧縮爆弾対策(CVE-2026-39244に対する修正)は、非圧縮サイズを0と宣言することで回避される可能性があります。

**影響を受けるパッケージ:** adm-zip (npm)
**影響を受けるバージョン:** 0.6.0

## 概要

CVE-2026-39244に対する修正(`methods/inflater.js`)では、`maxOutputLength: expectedLength`によってzlibの解凍出力を制限しています。ここで、`expectedLength`は、ZIPエントリの攻撃者が制御できる「非圧縮サイズ」のヘッダーフィールド(`CENLEN`/`LOCLEN`)から直接読み込まれます。この制限は、`expectedLength > 0`の場合にのみ適用されます。

```js
const option = version >= 15 && expectedLength > 0 ? { maxOutputLength: expectedLength } : {};
return zlib.inflateRawSync(inbuf, option);
```

攻撃者が宣言された非圧縮サイズフィールドを**0**に設定すると、この条件は偽となり、`option`は`{}`となり、zlibに何の出力制限も渡されません。その結果、Nodeはzlib自身の内部デフォルト制限(数GB)に戻り、小さく、高圧縮なペイロードでも、依然として非常に大きなサイズでメモリ上に解凍される可能性があります。これは、元のCVEで対処しようとしたリソース枯渇の問題と同じ種類のものです。ただし、トリガーされる条件が異なります。

## 再現手順

1. DEFLATE圧縮されたエントリを1つ含むZIPアーカイブを作成します。このエントリの実際のデータは、冗長性が高く(例えば、繰り返されるバイトが数MB)、理論上のDEFLATE圧縮率である約1032:1に近い圧縮率を達成します。
2. エントリで宣言されている未圧縮サイズフィールド(ローカルファイルヘッダーのコピーと、中央ディレクトリのコピーの両方。4バイトのリトルエンディアン形式)を`0`に修正します。圧縮されたバイトとCRC32は変更しません。CRC検証は、CRCが宣言されたサイズではなく、実際の展開された出力に対して計算されるため、引き続き成功します。
3. `new AdmZip(buffer)`でアーカイブを読み込み、`.getEntries()[0].getData()`(または`readFile`/`readAsText`/`extractAllTo`など。これらはすべて同じコードパスを共有します)を呼び出します。
4. 観察:展開は成功し、サイズ制限が適用されずに、完全なサイズのバッファが返されます。一方、同じ実際のデータで、正直な(ただしサイズが小さすぎる)宣言された値を設定すると、正しく`Cannot create a Buffer larger than N bytes`というエラーが発生します。

## 実証

添付スクリプトは、同一の実際のペイロードを使用して、制御されたA/B比較を示しています。異なるのは、宣言されたサイズのヘッダーフィールドのみです。

- **制御**(宣言されたサイズ = 1024バイト。意図的に実際の4MBの出力よりも小さい):正しくエラーが発生し、`expectedLength > 0`の場合にキャップメカニズムが機能することが証明されます。
- **回避**(宣言されたサイズ = 0。実際のペイロードは同一):成功し、制限なしで4,194,304バイトの完全なバッファが返されます。

3回の独立した実行で再現可能であることが確認されました。

## 影響

信頼できないZIPファイルに対して、adm-zipの読み込み/展開メソッドを呼び出すアプリケーション(アップロードハンドラ、CIアーティファクトの抽出、メール添付のスキャンなど)は、アプリケーションまたはadm-zipが意図する制限ではなく、zlib自身の内部デフォルトによってのみ制限されるメモリ量を割り当てる可能性があります。比較的小さな(数十MB)アップロードでも、数GBのメモリ消費を引き起こし、プロセスがクラッシュしたり、OOM(Out of Memory)エラーが発生するリスクがあります。

## 提案される修正

`maxOutputLength` を常に適用する(例えば、適切な上限値を設定するか、宣言されたサイズを常に使用する、たとえそれが0であっても)。また、攻撃者によって提供されたサイズフィールドのみに依存しない、独立した圧縮率のチェックを追加する。

影響を受けるパッケージ:
- npm (JavaScript) adm-zip: 影響を受けるバージョンは 0.6.0 以下、0.6.1 で修正済み。