OpenSSF Scorecard / ソースコードの守り方

Fuzzing
ファジングが行われているか

でたらめな入力を大量に与えて異常を探す「ファジング」が行われているかを見るチェックです。ほとんどのプロジェクトは 0点 で、それが問題を示すことはまずありません。

何を見るチェックか

ファジング(Fuzzing)は、プログラムに大量のでたらめな入力を与え続けて、 異常終了やメモリ破壊が起きないかを探すやり方です。

想定外の入力を人が考えて書くのは限界があるので、機械に総当たりさせます。 パーサ、画像や動画のデコーダ、圧縮、暗号、ネットワークプロトコルの実装など、 外部から来たデータをそのまま解釈する種類のコードに効果があります。

Scorecard は次のいずれかが見つかると 10点にします。

  • OSS-Fuzz にプロジェクトが登録されている
  • ClusterFuzzLite が設定されている
  • Go の組み込みファジング(func FuzzXxx(f *testing.F))がある
  • Rust の cargo-fuzz、Python の atheris などの設定がある

無ければ 0点です。

点が低いと何を意味するか

点が低いということは、ファジングによる検査が確認できないという、それだけの意味です。

ファジングが有効なのは、限られた種類のコードです。

  • ファイル形式やプロトコルを解析するもの
  • メモリを直接扱う言語(C / C++ / Rust の unsafe など)で書かれたもの
  • 外部から来た信頼できないデータを最初に受け取るもの

こうした条件に当てはまるライブラリで 0点 なら、 検討されていない可能性がある、という材料にはなります。

一方、Web フレームワーク、ORM、日付ライブラリ、UI コンポーネントのようなものでは、 ファジングの費用対効果は低く、行われていないのが普通です。

誤解しやすい点

Scorecard のチェックの中で、0点が最も当たり前な項目です。

実際、広く使われている OSS の圧倒的多数が 0点 です。 ファジングを実施しているのは、C / C++ で書かれた基盤ライブラリや、 Google の OSS-Fuzz に受け入れられた主要プロジェクトが中心で、 全体から見ればごく一部です。

したがって、

  • 0点 を減点材料として扱わないでください。 総合スコアを見るときも、この項目が引き下げているケースが多くあります。
  • メモリ安全な言語で書かれたライブラリでは、効果が限られます。 JavaScript / Python / PHP / Ruby などでは、 ファジングで見つかるのは主に例外や無限ループで、 C 言語のようなメモリ破壊は起きません。
  • 10点 でも「脆弱性が無い」ではありません。 ファジングが見つけるのはクラッシュ系の問題が中心で、 権限設計の誤りやロジックの間違いは見つかりません。

「この種類のコードなら意味がある」という観点で読む項目であって、 点の高低をそのまま比べる項目ではありません。

採用する側が確認すべきこと

  1. そのライブラリが何を解析しているかを考える。 外部から来たバイト列を解釈するもの(パーサ、デコーダ、プロトコル実装)なら、 この項目に意味があります。それ以外なら、ほぼ気にしなくてよいでしょう。

  2. 書かれている言語を見る。 C / C++ / Rust の unsafe を含むコードなら、 ファジングの有無は現実的な材料になります。

  3. OSS-Fuzz に登録されているかを見る。 登録されていれば、そのプロジェクトは継続的に検査されており、 見つかった問題は Advisory として公開されています。 これは強い加点材料です。

  4. 登録されていなくても、それを理由に見送らない。 繰り返しますが、0点が普通です。

メンテナーなら何を改善できるか

まず、自分のプロジェクトにファジングが向いているかを判断してください。

向いているもの: パーサ、シリアライザ、デコーダ、圧縮、暗号、 ネットワークプロトコル、バイナリ形式の読み書き。

向いていないもの: Web アプリのフレームワーク、ORM、UI 部品、CLI のラッパ。

向いている場合

  • Go なら組み込みのファジングが手軽です。
    func FuzzParse(f *testing.F) {
        f.Add([]byte("example"))
        f.Fuzz(func(t *testing.T, data []byte) {
            _, _ = Parse(data)   // panic しないことを見る
        })
    }
    
  • Rust なら cargo fuzzPython なら atheris
  • C / C++ で広く使われているライブラリなら、 OSS-Fuzz への登録 を検討する価値があります。無料で継続的に回してもらえます。
  • 手軽に始めるなら ClusterFuzzLite を CI に入れる方法もあります。

向いていない場合

この項目は満たさなくてかまいません。 点のためだけに形だけのファザーを置いても、CI の時間を消費するだけです。 CI-TestsSAST に力を入れるほうが、 同じ労力で得られるものが大きくなります。

あわせて読む