🥊

lefthookとtrivyでコミット前にローカルプロジェクトの脆弱性をチェックする

2023/01/27に公開

git commit 行う際に、クレデンシャル漏洩などを防止する目的でtrivyのスキャンを行いたくなったので、git hooksを利用してコミット前にコマンドを実行するようにしてみたいと思います。git hooksの管理ツールには Huskypre-commit などのツールがありますが、今回はシングルバイナリで動作する lefthook を試してみました。

インストール

必要なコマンドをインストールします。手元の環境がMacなのでHomebrewを利用しています。

brew install trivy lefthook

手動でスキャンしてみる

まず手動でtrivyを実行して、認証情報が記載されたファイルを検出してくれるか試します。

$ cd repo
$ cat <<EOF > aws_credentials
[default]
aws_access_key_id=********************
aws_secret_access_key=****************************************
EOF

# スキャン実行
$ trivy fs . --quiet

aws_credentials (secrets)

Total: 2 (UNKNOWN: 0, LOW: 0, MEDIUM: 0, HIGH: 0, CRITICAL: 2)

CRITICAL: AWS (aws-access-key-id)
════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════
AWS Access Key ID
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
 aws_credentials:2
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
   1   [default]
   2 [ aws_access_key_id=********************
   3   aws_secret_access_key=****************************************
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────


CRITICAL: AWS (aws-secret-access-key)
════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════
AWS Secret Access Key
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
 aws_credentials:3
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
   1   [default]
   2   aws_access_key_id=********************
   3 [ aws_secret_access_key=****************************************
   4
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

想定通り警告してくれました。

lefthookのタスクを定義

検出してくれることを確認したので、lefthookを使って git commit のタイミングでスキャンを実行するフックを作成していきます。

lefthook install

上記のコマンドを実行すると、リポジトリに lefthook.yml ファイルが作成され、初期状態ではいくつかの設定例が記載されています。テンプレートと公式のドキュメントを参考に、次のように書き換えました。

lefthook.yml
pre-commit:
  commands:
    trivy-scan:
      run: echo {staged_files} | xargs -n1 trivy fs --exit-code 1 --quiet

補足する点として、コミット対象のファイルのみにスキャンを行いたいので、{staged_files} を指定しました。こうすることで、 pre-commit のフック時にステージされているファイルのリストをスペース区切りで渡してくれます。

また、trivy fs コマンドが受け取る引数は1つだけ(ディレクトリもしくは単一ファイルの指定)なので、xargs でファイルの数だけ実行しています。加えて、デフォルトの挙動では脆弱性を検知した場合でも終了コードは0を返すため、--exit-code フラグで検出時は1を返すように指定して、フックの中で実行された時にコミットが中断されるようにしました。(参考)

こちらもまずは手動で試してみます。lefthookはサブコマンドの run で定義したフックを指定すると、タスクランナーのように利用することもできます。(タスク名には pre-commit などのgit hooksに関連する名前以外も自由に利用可能です)

# ファイルをステージ
$ git add aws_credentials 

# pre-commitフックを手動で実行
$ lefthook run pre-commit
Lefthook v1.2.8
SYNCING
SERVED HOOKS: pre-commit
RUNNING HOOK: pre-commit

  EXECUTE > trivy-scan

/aws_credentials (secrets)

Total: 2 (UNKNOWN: 0, LOW: 0, MEDIUM: 0, HIGH: 0, CRITICAL: 2)

CRITICAL: AWS (aws-access-key-id)
════════════════════════════════════════
AWS Access Key ID
────────────────────────────────────────
 /aws_credentials:2
────────────────────────────────────────
   1   [default]
   2 [ aws_access_key_id=********************
   3   aws_secret_access_key=****************************************
────────────────────────────────────────


CRITICAL: AWS (aws-secret-access-key)
════════════════════════════════════════
AWS Secret Access Key
────────────────────────────────────────
 /aws_credentials:3
────────────────────────────────────────
   1   [default]
   2   aws_access_key_id=********************
   3 [ aws_secret_access_key=****************************************
   4
────────────────────────────────────────

問題なさそうです。

git hooksからタスクが呼び出されるように設定

最後にgit hooksに登録して、定義した pre-commit タスクがコミット時に実行されるかを確認します。

# git hooksに定義したタスクを登録
$ lefthook install

$ git commit -m "test"
Lefthook v1.2.8
RUNNING HOOK: pre-commit

  EXECUTE > trivy-scan

/aws_credentials (secrets)

Total: 2 (UNKNOWN: 0, LOW: 0, MEDIUM: 0, HIGH: 0, CRITICAL: 2)

CRITICAL: AWS (aws-access-key-id)
════════════════════════════════════════
AWS Access Key ID
────────────────────────────────────────
 /aws_credentials:2
────────────────────────────────────────
   1   [default]
   2 [ aws_access_key_id=********************
   3   aws_secret_access_key=****************************************
────────────────────────────────────────


CRITICAL: AWS (aws-secret-access-key)
════════════════════════════════════════
AWS Secret Access Key
────────────────────────────────────────
 /aws_credentials:3
────────────────────────────────────────
   1   [default]
   2   aws_access_key_id=********************
   3 [ aws_secret_access_key=****************************************
   4
────────────────────────────────────────




SUMMARY: (done in 0.66 seconds)
🥊  trivy-scan

これで git commit の実行時にtrivyのスキャンが走り、脆弱性を検知した場合は中断されるようになりました。今回はクレデンシャルが含まれていないかをチェックするために使いましたが、DockerfileやKubernetesマニフェストの設定不備をチェックするなど様々な用途がありそうです。

該当のリポジトリを改めてcloneした時などは、再度 lefthook install を実行する必要がありますので、READMEなどに書いておきましょう。なお、lefthookのインストールは npm で行うこともできますが、その場合は postinstall スクリプトによって自動的に実行されるようです。

Discussion