🎉

IntelliJ ファミリーで Semgrep

2023/02/13に公開

IntelliJ ファミリーで Semgrep

最近、静的解析ツールの Semgrep にはまっています。Visual Studio Code の拡張は Semgrep の開発元が提供していますが、IntelliJ ファミリー向けはありません。有志が semgrep-idea として公開していますが、古いバージョンの IntelliJ にしか対応しておらず、実質使うことができません。

いちいち semgrep コマンドを叩いて... とやるのも面倒なので、Semgrep Plugin を作りました!

  • 別途 Semgrep (と Python) が必要です。
  • Windows には対応していません。(Semgrep 自身が今のところ Windows 非対応です...)
  • IntelliJ IDEA 以外 (Rider / WebStorm など) でも多分動作するはずです
  • macOS でも動くはずですけど、確かめてません (どなたかレポートをお待ちしております)

Semgrep とは?

Semgrep様々な言語に対応した静的解析ツールです。一般的に、静的解析ツールは JavaScript での ESLint のように、特定の言語専用なことが多いので、同じツールで様々な言語に対応しているのは多分珍しいです。

Semgrep Registry には公式やコミュニティが作成した様々な検査ルールが登録されていて、これを使うことができますし、カスタムルールを自作することもできます。

対応している言語なら、同じ書き方で検査ルールを書けるのが強みです。

.NET でも .NET でなくても静的セキュリティコード検査 (Semgrep 編) も参考にしてください。

使い方

インストール

プラグインをインストールする前に Semgrep をインストールします。

$ pip install semgrep

もしくは、virtualenv にも対応しています。プロジェクトディレクトリ直下の venv/bin/semgrep があればそれを使います。

IntelliJ IDEA をはじめとする JetBrains の IDE のプラグインのインストール手順に従ってください。プラグインの名前は Semgrep です。

検査する

適当なプロジェクト (新しいプロジェクトでも可) IntelliJ ファミリーで開いてください。

脆弱性のある次のコードを作成します。

sample.js
function run(e) {
  eval(e);
}

Semgrep Plugin は標準で auto ルールを使います。このルールはちょっと重くて、検査結果が IDE に反映されるまで時間がかかります。自分の手元のしょぼい環境だと 20 秒くらいかかりました。

なお、このプラグインは Semgrep の実行パスをキャッシュします。IntelliJ を起動後に Semgrep をインストールした場合は、IntelliJ を再起動してください。

ルールを選ぶ

Semgrep Registry には公式やコミュニティが用意した様々なルールがあります。auto ルールは重たいので、Semgrep Registry からルールを選んだ方がよいでしょう。

設定 -> TODO -> Semgrepconfigurations にルールをカンマ区切りで入力します。例えば、r2c (Semgrep の開発元) 公式の JavaScript の検査ルールを利用する場合は、p/javascript とします。

GitLab SAST

GitLab では脆弱性検査のための GitLab SAST が使えます。(参考: SASTで脆弱性を発見しよう!) 脆弱性検査自体は SAST Analyzer と呼ばれ、以前は言語ごとに用意されていましたが、Semgrep を利用した Semgrep analyzer に順次置き換えられています。

GitLab SAST で脆弱性検査をするのはいいことなのですが、コミットしてプッシュした後に検査されるため、どうしても指摘が多くなりがちで、修正が大変です。IDE で開発中も検査すべきです。

GitLab SAST (Semgrep analyzer) の検査ルールは p/gitlab として公開されています。(多分、Semgrep analyzer と同一のものだと思います) これを、Semgrep Plugin 設定の configurations に設定してください。

GitLab SAST (Semgrep analyzer) の脆弱性検査を開発中にすることができます。

自前のルールを書く

Semgrep の強みは検査ルールの書きやすさです。どの言語でも同じ書き方でいいのは魅力的です。正直、脆弱性の検出率は言語専用のツールのほうが高いです。言語専用の静的検査ツールを使いつつ、それで拾えない脆弱性を Semgrep のカスタムルールを書いて検出するのがよさそうです。

プロジェクトディレクトリに次のファイルを作成します。

---
rules:
  - id: eval
    languages: [javascript]
    message: eval は使わんといて
    severity: ERROR
    patterns:
      - pattern: eval($ARG, ...)
      - pattern-inside: |
          function $FUNC($ARG) {
            ...
          }

Semgrep Plugin 設定の configurationssemgrep.yml と設定します。

sample.js ファイルを開いて検査結果を確認してください。

ルールの書き方は Semgrep で SQL Injection と戦う #1 を参考にしてください。

ださいところ

Semgrep は検査ルールをインターネットからダウンロードしてくるのですが、このファイルをキャッシュしないんです。また、大きなルールファイルの解析に時間がかかるようで、(多分ですけど) IntelliJ のプラグインのようにファイル一つ一つをそれぞれ検査するスタイルだと、auto ルールのように重たいものは CPU 時間を結構持っていきます。特にコミット時には対象ファイルを一つ一つ検査しますので、すごく待たされます。

改善したいけど、Semgrep や IntelliJ 側の問題なのでなかなか...

いいアイデアお持ちの方はぜひ Issue を作成してください!

IntelliJ プラグインを作成するのも初めてで、Swing も初めてで手探り状態です。なので、通知メッセージや設定画面が不親切なのもどうにかしていきたいですねぇ。

Discussion