[解説] LiquidJSのdateフィルターにおけるDoS脆弱性 (GHSA-hh27-hf48-9f5q)
はじめに:LiquidJSユーザーが知るべき高深刻度DoS脆弱性
日本のフロントエンドエンジニアの皆さん、こんにちは。静的サイトジェネレーターやHeadless CMSのテンプレートエンジンとして、LiquidJSを利用されている方も多いのではないでしょうか。今回は、LiquidJSに報告された高深刻度(Severity: high)のサービス拒否(DoS)脆弱性、「GHSA-hh27-hf48-9f5q / CVE-2026-45357」について、その詳細と緊急の対策方法を解説します。
この脆弱性は、特定の攻撃パターンによってサーバーのメモリを大量に消費させ、アプリケーションのクラッシュやサービス停止を引き起こす可能性があります。何よりも深刻なのは、既存のDoS対策機能がこの脆弱性に対して無効であるという点です。自身のアプリケーションが影響を受ける可能性があるか確認し、速やかに対策を講じましょう。
脆弱性の概要:`date`フィルターと無制限の幅指定
今回の脆弱性は、LiquidJSの`date`フィルター内で日付書式設定に使われる`strftime`の実装に起因します。`strftime`は日付や時刻を指定されたフォーマット文字列に基づいて整形する機能ですが、この実装において幅指定子(例: `%9999999d`)が不適切に処理される問題がありました。
通常、幅指定は出力される文字列の最小幅を指定するために使われますが、LiquidJSの`strftime`はこれを無制限に解釈し、内部の`pad()`関数に非常に大きな数値を渡してしまいます。この結果、`pad()`関数内で大量の文字列連結処理が発生し、システムリソースが枯渇するのです。
既存のDoS対策が機能しない理由
LiquidJSには、悪意のあるテンプレートによるリソース枯渇を防ぐための`memoryLimit`や`renderLimit`といったDoS対策機能が実装されています。しかし、今回の脆弱性はこの`memoryLimit`や`renderLimit`といった既存の対策を完全に回避してしまいます。
無制限の幅指定が`pad()`関数に渡された際、`pad()`関数は大量の空白文字を非効率な方法(文字列連結の繰り返し)で生成しようとします。このプロセスが、既存のメモリやレンダリングの制限を超えて実行されてしまうため、設計されたDoS対策が機能せず、最終的にメモリ不足によるプロセス停止やCPUリソースの枯渇を引き起こしてしまいます。
影響を受ける条件:あなたのアプリケーションは大丈夫か?
この脆弱性の影響を受けるのは、LiquidJSを使用しているアプリケーションで、**`date`フィルターの`format`引数にユーザーが制御できる(または影響を与えられる)値を渡している場合**です。
例えば、ブログやCMSでユーザーが投稿の日付表示フォーマットをカスタマイズできる機能があり、そのフォーマット文字列が直接`date`フィルターに渡されているようなケースが該当します。
具体的なコード例としては、`{{ post.created_at | date: user_supplied_format }}`のように、`user_supplied_format`が攻撃者によって操作された場合に危険に晒されます。
`date_to_xmlschema`など他の日付関連フィルターも内部的に`strftime`を使用していますが、これらは通常ハードコードされた安全なフォーマットを使うため、直接的な攻撃対象となるリスクは低いと考えられます。しかし、ユーザー入力が間接的にこれらに影響を与える可能性もゼロではないため、注意が必要です。
推奨される対応策:二段階での修正
この脆弱性に対する根本的な解決には、以下の二つの対策を両方実施することが強く推奨されます。これにより、OOM(Out Of Memory)クラッシュの防止と、既存のDoS対策の回復が期待できます。
`src/util/underscore.ts`内の`pad()`関数を修正し、文字列連結の際にメモリ制限を考慮するように変更します。また、非効率な繰り返し連結ではなく、JavaScript標準の`String.prototype.repeat`を使用するように改善することで、CPU効率も向上させます。
変更のポイントは、`pad()`が受け取る幅が不正に大きくても、安全な範囲で処理を打ち切る、あるいはメモリ消費を適切に計上するロジックを追加することです。
`src/util/strftime.ts`内で、幅指定子(`padWidth`)に適切な上限値(例えば`Math.min(width, 1024)`)を設定します。これにより、攻撃者が極端に大きな幅を指定しても、安全な範囲で処理が実行されるようになります。
さらに、`date`フィルター(`src/filters/date.ts`)で`strftime`を呼び出す前に、フォーマット文字列をスキャンして最大幅を推定し、その推定されるメモリ消費量を`this.context.memoryLimit`に事前に計上するように変更します。これにより、既存のDoS対策がこの種の攻撃に対しても機能するようになります。
まとめ:早急な対応を
LiquidJSの`date`フィルターにおけるDoS脆弱性は、既存のセキュリティ機構を回避する危険なものです。もしあなたのアプリケーションがユーザー入力によって`date`フィルターのフォーマットを制御している場合、この脆弱性の影響を直接受ける可能性があります。
LiquidJSのバージョンアップや、上記のパッチ適用によって、速やかにシステムを保護することを強く推奨します。セキュリティは一度破られると大きな損害につながる可能性がありますので、早めの対応が何よりも重要です。
最新のLiquidJSの公式リリースやセキュリティアナウンスメントを常にチェックし、安全な開発を心がけましょう。