YT: returntocorp/semgrep
YouTube
今回は1日の中で昼と夜の 2 回配信を行いました。
1 回目は Semgrep CLI を使って、ローカルで semgrep を動作させました。
1 回目で Semgrep CI を GitHub Actions で動かす設定をしているときに息子が起きたので、Semgrep CI の実行を夜に行いました。
驚くことに、1 回目の配信には Semgrep 開発元のr2cの Founder の方が、2 回目の配信の方には開発者の方が配信に参加し、コメントをくれました。なぜこんな誰も見ない配信までキャッチアップできるんだ…すごい…。(誰もコメントなんてしないだろうと思って 1 回目の配信の方ではコメントに気づかず無視してしまいました…すいません…)
returntocorp/semgrep
https://github.com/returntocorp/semgrep
why?
最近、semgrep を使った事例がいくつか紹介されていたので名前は知っていました。
- Semgrep を使った構文木ベースの検索と置換でコードのリファクタリングをする | Web Scratch
- セキュアに Go を書くための「ガードレール」を置こう - 安全な Go プロダクト開発に向けた持続可能なアプローチ - Flatt Security Blog
少しルールを見た感じでは正規表現ベースの解析・置換ツールかなと思っていたのですが、言語非依存で多言語対応しているという説明を読み、具体的にどんなことができるのだろうと興味があったので触ってみました。
what?
Lightweight な静的解析ツール。問題のあるコードを見つけるためのルールを定義し、それに合致したコードを脆弱性として検出する。また、autofix に関するルールを書くこともでき、検出された箇所のコードをルールに沿って一括で書き換えることもできる。
言語非依存な静的解析ツールというとGitHub の Code Scanningが思い起こされるが、Code Scanning は検出ルールの記述にSemmle(acquired by GitHub)が開発していた CodeQL という独自形式を採用しているのに対し、semgrep では開発者にとって馴染み深い正規表現ベースで検出ルールを書けるという違いがある。また、実行環境も Code Scanning が GitHub Actions での実行を想定しているのに対し、semgrep は CLI ツールが配布されているためローカル環境でも実行することができる。
semgrep では、他の人が書いたルールを共有し、サーバー上で実行できる Semgrep CI というサービスもあり、これを使えば簡単に GitHub Actions とも連携することができる。
https://semgrep.dev/manage/projects
How?
Install
Semgrep を実行するには CLI ツールをインストールする必要がある。Homebrew
,pip
,Docker
での環境構築方法があるらしいが、Homebrew
,pip
に関しては自分の環境ではエラーになったため、今回はDocker
を使って実行した。
# For macOS
$ brew install semgrep
# For Ubuntu/WSL/Linux/macOS
$ python3 -m pip install semgrep
# To try Semgrep without installation run via Docker
$ docker run --rm -v "${PWD}:/src" returntocorp/semgrep --help
https://semgrep.dev/docs/getting-started/
Execute
Semgrep CLI では、1 ライナーで解析を実行することができる。
以下は Java コードから System.out.println
を呼んでいる箇所を検出する 1 ライナー。
$ docker run --rm -v "${PWD}:/src" returntocorp/semgrep -e 'System.out.println(...)' --lang=java java/Sample.java
java/Sample.java
3: System.out.println("Hello, world!");
ran 1 rules on 1 files: 1 findings
https://youtu.be/cMa6RJeaBJ0?t=1568
基本的には文法的に正しくコンパイル可能なコードに対して実行するものだが、コンパイル不可能なコード断片でも解析を実行し、ルールに合致する箇所を検出すること自体はできる。ただし、中括弧が閉じていないなど、文法として部分的にも完結していない場合は検出もできない。
動画の中ではその辺りもいろいろ試している。
Rule
Semgrep のルールは 1 ライナーとして指定するだけでなく、YAML 形式でファイルに記述することもできる。ルールの詳細については公式ドキュメントを参照。https://semgrep.dev/docs/writing-rules/overview/
今回は以下のような Rule を定義した。
rules:
- id: sample
pattern: System.out.println($MSG)
fix: logger.info($MSG)
metadata:
hello: world
references: https://github.com/orta-contrib
message: |-
Do not use sysout. Use logger.
languages: [java]
severity: WARNING
検出パターン (pattern
) に対し、修正方法 (fix
) を定義し -a
オプションを付けて Semgrep CLI を実行することで、ルールに合致する箇所を検出すると同時に、fix
に書かれた通りに検出箇所を変換することができる。
$ docker run --rm -v "${PWD}:/src" returntocorp/semgrep -f rule.yaml --lang=java java/Sample.java --json -o results.json -a
https://youtu.be/cMa6RJeaBJ0?t=2528
Semgrep CI
Semgrep は CLI だけでなく Semgrep CI という SaaS サービスも提供している。
Semgrep CI 上で GitHub と連携し、Semgrep を実行したいリポジトリを選択すると、GitHub Actions 実行用ワークフローファイル(.github/workflows/semgrep.yml
)をコミットしてくれる。ワークフローファイルをコミットした後は GitHub 上で master/main ブランチに push したり、PR を作ったりすれば Semgrep による解析が行われる。
https://youtu.be/cMa6RJeaBJ0?t=3317
Semgrep の検出ルールは Semgrep CI の画面上で設定することができる。すでに他の開発者によって公開されたルールを使用することもできるし、自分で作ったカスタムルールを適用することもできる。(ルールをリポジトリに設定する方法については、配信を見ていてくれた Semgrep の開発者の方が教えてくれた)
https://youtu.be/7ZwkHIdYhco?t=909
Semgrep によって検出された警告は、以下のように表示される。
https://youtu.be/7ZwkHIdYhco?t=1072
Semgrep の Autofix による修正を PR に対する Suggestions として扱えると便利だと思ったが、今はまだその機能はないらしい。しかし、配信を見ていてくれた開発者の方が Issue を立ててくれたので、数ヶ月のうちに利用可能になるかもしれない。
https://github.com/returntocorp/semgrep-action/issues/213
Analytics
Semgrep CI の実行結果を確認するための Analytics というメニューもある。Analytics では、今までの Semgrep CI の実行結果から、どのような警告が検出されているか、どのルールによる警告が多いか、どのような警告が修正されているか、などをリポジトリ単位などの切り口で見ることができる。
あまり警告が検出されないルールを外したり、どのような警告が修正されにくいのかなどを一覧し、ルールを見直す時の手掛かりになりそう。
https://youtu.be/7ZwkHIdYhco?t=1851
Impression
正規表現ベースの解析・置換ツールだが、YAML によるルール記述や、CI サービスなど、随所にモダンさが感じられ、最近話題になっているのも納得という感じだった。開発したルールの共有の仕組みや、共有されたルールを簡易に再利用できる仕組みもあり、ローカル/サーバー共に解析を実行できるため、広く普及していくのではないかと思う。
GitHub Code Scanning が出た時は、さすが GitHub と思ったが、あちらは独特な機能の CodeQL を採用していることや、GitHub Actions に特化していることなどから汎用性の部分で難があるように感じられるようになった。Semgrep は正規表現ベースという多くの人が読み書きできる(複雑でなければ…)記法をベースとしているため、ルールに関する議論も活発になりやすいのではないかと思う。
また、こんな誰も見ていないような配信にまで Founder/Developer の方が駆けつけてコメントしてくれるなど、ユーザーの利用動向に目を向け、より良いものを作っていくという気概を感じた。フアンになりそう(上沼恵美子風に)。
Contribute
直接コントリビューションはできなかったが、必要そうな機能に関する提案を行い、Issue を立ててもらうことができた。 https://github.com/returntocorp/semgrep-action/issues/213