コミット内容にトークンやSSHの秘密鍵など機密情報が入ってないかをチェックできるSecretlint 3.0をリリースしました。

secretlint 3.0

secretlint 3.0では、GitHubの新しくなったトークン形式の検出に対応する@secretlint/secretlint-rule-githubのルールが追加されました。

secretlintでは@secretlint/secretlint-rule-preset-recommendという、ESLintのような推奨ルールプリセットも提供しています。 そのため、プリセットを使っている人やDocker版を使ってる人は自動的にGitHubトークンも対応できます。

とりあえず、今あるディレクトリにsecretlintの推奨プリセットで検出できる機密情報がないかは、次のコマンドでチェックできます。

Dockerが入ってる人はdocekr runを使えます。

docker run -v `pwd`:`pwd` -w `pwd` --rm -it secretlint/secretlint secretlint "**/*"

Node.jsが入ってる人は、@secretlint/quick-startが簡易版のチェッカーとして使えます。

npx @secretlint/quick-start "**/*"

secretlintはESLinttextlintのようにJavaScriptでルールを書いて拡張できるようになっています。 この辺をもっと知りたい人は、Configurationsecretlint/secretlint-rule.mdを読んでください。

GitHub Tokenの対応

2021年4月ごろから新しく発行されたGitHub Tokenは次のようなルールで、トークン自体にprefixが入るのでトークンをみてGitHub Tokenか分かるようになっています。

The character set changed from [a-f0-9] to [A-Za-z0-9_]
The format now includes a prefix for each token type:
ghp_ for Personal Access Tokens
gho_ for OAuth Access tokens
ghu_ for GitHub App user-to-server tokens
ghs_ for GitHub App server-to-server tokens
ghr_ for GitHub App refresh tokens

同じような仕組みはSlack(@secretlint/secretlint-rule-slack)やSendGrid(@secretlint/secretlint-rule-sendgrid)などのトークンでも実装されています。

トークン自体にprefixがついていれば、トークンを実際にサーバに投げなくてもある程度判定できるので余計な負荷が減ります。

エントロピーの問題は、GitHubでは[a-f0-9]から[A-Za-z0-9_]に増やすことと、トークンの長さを最大255文字まで増やすことで保証するようです。 また、GitHub TokenはCRC32のChecksumを実装しているそうです(これ良くわかってなくて、@secretlint/secretlint-rule-githubに実装してないので分かる人PRやIssueお願いします!)

ドキュメントの更新

Secretlint 3.0にあわせてREADMEのHusky + lint-stagedを最新のバージョンに更新しました。 セットアップ済みのサンプルは次のリポジトリとして置いてあります。

また、トークン検出についてはGitHub自体にsecret scanningという検出の仕組みが最近利用できるようになっています。 secret scanningは、リポジトリにpushした後にトークンがあるかをスキャンして知らせてくれる機能です。対応しているトークンプロバイダも多く、実際にトークンがvalidかも検証するの正確です。 しかし、Secretlintと違ってpush後の判定なのでpublic repositoryだとrevokeが間に合わない場合があります。 Secretlintはローカルでのコミット時とCIでもチェックできることが目的なので、その辺の違いをMotivationに追加してあります。

Secretlintは、プロジェクトと個人どちらでも同じように使えるようにデザインしています。 詳しい設定方法やコミットフックについてはIntegrationsを参照してください。

または、次の記事などがわかりやすいと思います。

個人的にはGit 2.9+からgit config --global core.hooksPathでグローバルなコミットフックが書けるようになったので、 リポジトリ関係なく間違えて機密情報、/Users/user-nameのようなユーザーパスが入ったファイル.envファイルなどコミットするべきじゃないものをチェックできて便利です。

こういうLintみたいのは使いやすくないと使わない気がするので、自動的にどこでも使えるグローバルなコミットフックとして入れておくのが楽なのかなと思いました。 あわせてチーム開発するようなリポジトリには、間違えて追加されないようにするためにチェックとしてCIに入れるのが良いのかなと思っています。

自分のコミットフックの設定(Zsh連携もの含む)は次のリポジトリに公開してあります。

チェックするだけなら今も設定は不要ですが、コミットフックする場合も設定不要で使えるようにしたいですね。

その他の類似するツールとの比較は次の記事にまとまっている気がします。