
CVE-2026-0994のAny-unwrapping再帰バグクラスが、RubyおよびPHPのprotobufバインディングにおけるupbのCコアに影響を与えるかどうかを、ASan/UBSanペイロードを用いてテストする監査ハーネス。
ステータス: 完了。 3つの独立した実装(Ruby/PHPが共有するupbコア、C#の別個のマネージド実装)にわたる6つの再帰ガードチェックはすべて反証されました。ただし、この監査が照合対象としていた、すでに公開済みでパッチ適用済みのPython CVEは除きます。新たな脆弱性は発見されませんでした。
protobufのPythonおよびJavaScriptバインディングで確認されたAnyアンラップ再帰CVE(直近ではCVE-2026-0994。これはjson_format.pyの_ConvertAnyMessageにおける純粋なPythonのバグで、ConvertMessage()ではなくmethodcaller()を介して再帰し、深さカウンタを黙ってスキップしていました)のフォローアップです。
問い: 同じバグクラスが、RubyおよびPHPのネイティブ拡張にバンドルされているCのupbコアにも存在するのでしょうか?
短い答え: いいえ。 JSONデコード経路、バイナリワイヤデコード経路、そして独立したマネージドC#実装はすべて、ここでテストされたあらゆるケースにおいて再帰制限を正しく適用しています。これには、1MBスタック上で実行された200,000レベルのストレスペイロードも含まれます。これは証拠を伴う反証された仮説であり、脆弱性ではありません。他のあらゆる研究スレッドで反証された仮説を記録するのと同じように、ここにクリーンなネガティブ結果として記録します。
protobufのRubyおよびPHPネイティブ拡張はそれぞれ、共有ライブラリにリンクするのではなく、upbのCコアの単一ファイルアマルガメーション(ruby-upb.c、php-upb.c)をベンダリングしています。この監査では、その正確なファイルをスタンドアロンのCターゲットとしてビルドし(RubyやPHPのランタイムは関与しません)、google.protobuf.Any / Struct / Value / ListValueのディスクリプタでupb_DefPoolをブートストラップし、実際のデコーダエントリポイント(upb_JsonDecode、upb_Decode)を敵対的ペイロードで直接駆動します。ASan/UBSanの下で行います。
| 経路 | ガード | デフォルト制限 | 結果 |
|---|---|---|---|
JSONデコード、jsondec_any(Ruby) | d->depth、jsondec_pushでチェック | 64 | 反証 — 5000レベルのペイロードでクリーンなエラー、バイトオフセットは約64レベルと正確に一致 |
バイナリワイヤデコード、upb_Decode(Ruby) | Decode_LimitDepth | 100 | 反証 — 60レベルの境界ペイロードおよび200,000レベルのストレスペイロードでクリーンなkUpb_DecodeStatus_MaxDepthExceeded、いずれも8MBスタックと1MBスタック(非メインのRubyスレッドを近似)の下で |
| PHPバインディング | 同じガード関数 | 同じ | 同一性の証明により反証、別個の実行ではない — 下記参照 |
JSONデコード、JsonParser.MergeAny(C#、Google.Protobuf 3.36.1) | tokenizer.RecursionDepth、Merge()でチェック | 100 | 反証 — 200レベルのペイロードで確認済み。MergeAnyはAnyアンラップごとにFromReplayedTokensを介して新しいJsonTokenizerを構築するが、深さの計上はそれを正しく伝播する |
バイナリワイヤデコード、CodedInputStream/Value.Parser(C#、Google.Protobuf 3.36.1) | ストリーム上のrecursionDepth/recursionLimit | 64 | 反証 — 60レベルの境界ペイロード(Rubyワイヤテストと同じペイロードバイトを直接再利用)でクリーンなInvalidProtocolBufferException |
いずれの実行でもASanまたはUBSanの違反は観測されませんでした。クラッシュ、ハング、スタック枯渇もありませんでした。
php-upb.cとruby-upb.cは全体で約1,964行異なりますが、jsondec_any、jsondec_push、およびワイヤ深さ制限の定数は2つのファイル間でバイト単位で同一です(verify_php_identical.shがこれを証明します。鵜呑みにせず、実行してください)。ガードコード自体が証明可能に同一であるため、Rubyの結果は冗長なPHP専用ハーネスを必要とせずに転用できます。
テストされた4つのバインディング(Ruby、PHP、C#、およびすでに公開済みのPython CVE)はすべて反証されました。ただし、すでにアップストリームでパッチ適用済みのものを除きます。残る未解決のスレッドは、いずれもこの特定のバグクラスではありません:
utf8_range.cの検証。dotnet run -- wire <payload>)はまだCIに組み込まれていません — 自動化されているのはJSONモードのC#テストのみです。./fetch_source.sh # pins & clones protobuf @ ead3f0029facc43da13588132e9091bf9bd7a26f
./build.sh # compiles both harnesses w/ ASan+UBSan against the fetched source
./run_tests.sh # generates payloads, runs the full matrix, prints results
./verify_php_identical.sh # confirms the PHP claim above instead of asserting it
必要なもの: gcc、protoc(apt-get install protobuf-compiler)、python3、
git。gcc (Ubuntu 13.3.0-6ubuntu2~24.04.1) 13.3.0 と libprotoc 3.21.12 に対してビルドおよび検証済みです — バージョンが異なると挙動が変わる可能性があります。結果が上記の表と一致しない場合、それはデータであり、あなたの環境のバグではありません。ツールの不一致だと決めつける前に、原因を突き止めてください。
third_party/(fetch_source.sh によって取得)には、Google の
Apache-2.0 ライセンスの protobuf ソースが含まれており、上記のコミットに固定されています。これはこのリポジトリにコミットされることは決してありません — 他人のソースツリーをこのリポジトリにベンダリングする代わりに、fetch_source.sh が再現性のアンカーとなります。