Chromiumのバグ報奨金を可視化するMoney Tree Browser
(lyra.horse)- Chromium Money Tree Browserは、Chrome VRPの報奨金をChromiumリポジトリ内のディレクトリ・ファイル別の修正履歴にマッピングし、セキュリティ報奨金がコードツリーのどこに積み上がっているかをざっと見られるようにする
- 報奨金額は修正されたファイル数で割って配分され、$1,000の報奨金が付いたバグ修正で5つのファイルが変更された場合、各ファイルに$200ずつ割り当てられる
- 最上位の集計はroot $9,873,277 / 10,944件、chromium $9,014,838 / 10,218件、chrome $2,568,260 / 2,574件と表示される
- chrome/browser/ui/views、extensions、media、safe_browsing、enterprise、Android、net、device、gpu、storage、base、iOS、pdfなど多くの領域がファイル単位に分解されて表示され、V8も$858,439 / 726件と大きな割合を占める
- データとUIは「very very hacked together」な状態だという注意書きがあり、対象範囲も2023年11月初めまでなので、正確な会計資料というより探索用の地図として見るのが適切
報奨金額をコードツリーに分配して載せる仕組み
- Chrome VRPのバグバウンティ報奨金を、Chromiumコードベースのファイル・ディレクトリツリーに結び付けて表示するブラウザ
- 特定のセキュリティ修正が複数のファイルを変更した場合、報奨金額をファイル数で割って各ファイルに割り当てる
- この関連付けは、「どのコードがセキュリティ報奨金と一緒に頻繁に変更されているか」をざっと見る用途に近い
- 最上位の集計を見るだけでも、Chromium全体でかなり大きな規模の報奨金分布が見えてくる
- root: $9,873,277 / 10,944件
- chromium: $9,014,838 / 10,218件
- chrome: $2,568,260 / 2,574件
- chrome/browser: $2,250,643 / 1,920件
目を引くディレクトリ別の分布
- chrome/browser/ui/views配下には、ユーザーUI機能単位の報奨金分布が細かく分かれている
- views: $514,665 / 441件
- tabs: $56,705 / 30件
- eye_dropper: $47,000 / 7件
- bookmarks: $46,697 / 31件
- payments: $43,623 / 60件
- media_router: $36,395 / 12件
- tab_sharing: $30,591 / 9件
- Chrome extensions関連の領域も、大きなまとまりとして繰り返し登場する
- extensions: $157,507 / 262件
- extensions/api: $115,471 / 161件
- api/tabs: $42,705 / 48件
- api/debugger: $28,488 / 35件
- api/downloads: $15,225 / 13件
- 別のextensions領域も**$132,615 / 213件**として集計されており、rendererやguest_view/web_view、file_system APIなどが含まれる
- V8は、提供されたメモの中で最も大きな単一の下位領域に見える
- V8全体: $858,439 / 726件
- v8/src: $626,845 / 503件
- v8/test: $209,030 / 195件
- v8/src/compiler: $151,267 / 85件
- v8/src/heap: $91,891 / 64件
- v8/src/builtins: $68,133 / 30件
- v8/test/mjsunit: $164,644 / 113件
- chrome/browser側では、UI・タブ・自動入力・パスワード・DevTools・レンダラーのコンテキストメニューといったユーザー接点が目立つ
- chrome/browser/autofill: $114,656 / 40件
- chrome/browser/tabs: $92,316 / 25件
- passwords: $51,060 / 10件
- chrome_content_browser_client.cc: $51,512 / 11件
- devtools: $48,255 / 35件
- renderer_context_menu: $47,842 / 16件
- printing: $42,225 / 14件
- payments: $41,252 / 10件
- メディア・セキュリティ・エンタープライズ・プラットフォーム領域も大きな金額として集計されている
- media: $134,523 / 65件、別のchrome/browser/media領域は**$89,008 / 34件**
- safe_browsing: $80,161 / 31件
- enterprise: $59,000 / 38件
- ash: $130,389 / 161件、別のash区間も**$56,867 / 55件**と続く
- mojo: $112,725 / 26件
- net: $97,558 / 175件
- device: $61,770 / 32件
- gpu: $51,155 / 30件
- storage: $48,303 / 66件
- base: $36,013 / 27件
- AndroidとiOSも、別々のプラットフォームコードで報奨金分布が分かれている
- Android chrome/browserのJava・リソース・テスト領域: $94,441 / 159件
- Android Javaパス: $62,571 / 91件
- Android fullscreen: $18,707 / 11件、FullscreenHtmlApiHandler.javaが**$18,540 / 10件**
- iOS: $33,625 / 86件
- ios/chrome/browser/web: $11,663 / 4件
- ios/chrome/browser/ui: $9,884 / 24件
テストファイルと解釈上の注意点
- テストデータや回帰テストファイルも報奨金分布に含まれる
- test: $147,193 / 311件
- test/data: $116,355 / 271件
- test/data/extensions/api_test: $59,337 / 166件
- V8 test/mjsunit/regress: $82,180 / 58件
- V8 test/mjsunit/compiler: $46,233 / 28件
- セキュリティ修正がテストファイルの変更と一緒に記録されると、そのファイルにも報奨金額が配分されるため
- 算定方式が単純なため、金額をそのままリスク度や脆弱性の原因として読むのは難しい
- 報奨金額を「修正されたファイル数」で割るため、あるファイルの金額がそのファイル自体のリスク度を直接意味するわけではない
- データとUIは「very very hacked together」な状態であり、優れたUXや正確なデータを期待しないよう注意書きがある
- データの対象範囲は2023年11月初めまで
- 関連する議論リンクも提供されている
1件のコメント
Hacker Newsの意見
以前から作りたかったものにかなり近い。特定の変更が問題を引き起こす可能性を、同じファイルやファイル内の同じ領域で過去に発生した破壊的変更の履歴に基づいて計算できれば有用だと思っていた
基本的には各変更ごとにリスクスコアを付け、PRごとにそのスコアを表示して、レビュー担当者がより注意して見るべきコードを分かるようにし、デプロイ時にも危険な変更を強調するという方式
難しいのは、上の方での挿入・削除によってコード位置が上下するときに、同じコード領域を継続して追跡することで、単純に行番号に依存するアルゴリズムだとここで問題が起きる
それでも、この事例のようにファイル単位だけでも十分に有用そうに見える
リスクが高い変更にはより多くのテストを回すが、ユニットテストではなくクライアントテストを回す。ときには選べるクライアントテストが10万件あるので、順位付けしたうえで小さなサブセットだけ実行する
難しい問題だ。興味深い観察の1つは、原因となる変更の中に原因シンボルが1つか2つある一方で、そのシンボルの接続性が同じ変更内の非原因シンボルと非常によく似ていること
また、変更後に推移的に修正されたコールグラフがかなり大きく、深さ50も珍しくない。変更とテストの間で推移的に影響を受けるシンボルの重なり具合以外には、有用なシグナルをあまり取り出せなかった
ファイル単位やビルドターゲット単位は粗すぎて、ASTシンボルはうまく機能している
とてもすばらしい。ただ、抜けている項目が少しある気がする。third_party/ffmpegにも少なくとも1つはあったはず
そうした修正はたいてい先にupstreamに入るので追跡が難しいことがある
chrome/browser/ui配下の大きなまとまりを見て回ると、手動メモリ管理の性能上の利点がほとんど重要でないデータで、use-after-freeがいかに多く発生しているかを考えさせられる。たとえば[1]は「ファイル選択」ダイアログのライフサイクル周りの問題大きな視点では、こういうコードには防御のために、より賢いが遅いポインタを常に使うほうがよさそうに見える。[2]で
raw_ptr型[3]がそうした助けを狙っているように見えたし、もしかすると[2]のクラッシュは実際に防御に成功した例なのかもしれないプロジェクトの中で、「ここは性能が重要で細心にレビューされたコード」と「ここは性能に鈍感で非同期状態が多く、間違えやすいコード」のように、より広い形で方言を切り替える方法がうまくないのが残念。後者にはGC付きの別言語を混在させるのがほとんど価値があるのではと考えたこともある
ちなみに昔このコードに長く関わっていたし、これらのバグのうち0個より多くを自分が作っていたとしても驚かない
[1] https://bugs.chromium.org/p/chromium/issues/detail?id=120103...
[2] https://bugs.chromium.org/p/chromium/issues/detail?id=132323...
[3] https://source.chromium.org/chromium/chromium/src/+/main:bas...
unsafeキーワード**を説明しているのと同じそして、この種のコードこそが文字通りRustが生まれた本来の動機の1つだった。そもそもブラウザ実装を念頭に設計された言語だったのだから
逆に速い言語からスクリプト言語を呼ぶこともできる。今はみんなwasmに熱狂しているが、コンピュータゲームはすでに約20年間そういう用途にluaを使ってきた。ゲームはおそらく性能に敏感なソフトウェアの最大カテゴリだろう
Chrome UIコードの大半は少なくともWeb UIで書かれている。今なら、ブラウザ内部のより多くのオーケストレーション作業にTypeScriptを検討すべきだと思う。Electronが実証した戦略だ
ただ、今の流れは実際にはMiraclePtrの方にあるようだ
raw_ptrは実際、ほとんどのuse-after-free悪用を緩和するスマートポインタラッパー: https://security.googleblog.com/2022/09/use-after-freedom-mi...これをツリーマップ可視化に移してみた[1]: https://vrp-treemap.surge.sh/
ツリーマップライブラリは、このスレッドにもいるChrome古参のevmarが作った
とてもきれいな可視化。領域を展開するときにCPUを少し多めに使うけれど、Chromeチーム内部にも似たものがあるとよさそう
いわば攻撃面を理解するのに本当に役立ちそう
本当にすばらしいアイデアで、実装もよい
生データはどこかにあるのだろうか? サンバーストやツリーマップも試す価値がありそう
これ、たぶんdiff単位まで下りているはずなので、変更されたコード行数で重み付けすると面白そう。たとえばファイルAで10行、ファイルBで1行変わったなら、バグの大半はファイルAにあるので、ファイルAに賞金の1/11が割り当てられる感じだろうか?
あるいは変更行数 / ファイル全体の行数で配分してもよい。そうすれば各ファイルがどれだけバグまみれかを金額タグ付きで見られる
各ノードにファイルごとの平均報奨金額も表示するとよい
細かい指摘だけれど、DEPS、AUTHORS、BUILD.gnファイルは含めないほうがよい
金額をコード行数で正規化した版はどうだろう?