GH-500(GitHub Advanced Security:GHAS)学習記録
全体
GHAS三大要素
- シークレットスキャン
- コードスキャン
- Dependabot
ライセンス
- Github Secret Protection
- Github Code Security
無料で使える機能もある。パブリックリポジトリであれば大体の機能は無料で使える。プライベートリポジトリでも無料で使える機能がある(Dependabot系の一部の機能)
シークレットスキャン
シークレット スキャンは、ソース コード内で API キーやトークンなどの機密情報が誤って公開されるのを識別し、防止する
- すべてのパブリックリポジトリで無料で利用可能
2つのシークレットスキャン
リポジトリに対するシークレットスキャン(Secret Protection、シークレット保護)
既にリポジトリ内にあるコードに対して、シークレットが含まれていないかチェックする。
プッシュに対するシークレットスキャン(push protection、プッシュ保護)
プッシュされるタイミングで、コードにシークレットが含まれていたらプッシュをブロックできる(=リポジトリに格納される前に、ブロックできるのでよりセキュア)
★GithubサイトGUI上でリポジトリ内のファイルを編集して、コミットを実施する操作もプッシュ操作と見なされるため、プッシュ保護が機能する(GUI上のコミットは、GUI上で編集したファイルを保存するという意味も含まれる)
たとえば、GUIの操作により、ファイルに対してシークレット情報を追記してコミットすると、以下のような画面が出て、コミット操作が一旦ブロックされます

特定のファイルをシークレットスキャンの対象外とする方法
例えば、コードの中に、ランダムに生成される文字列を含まないといけないような場合は、シークレットスキャンが誤検知してしまう可能性があるため、そもそも対象外にしたいようなケースがある。
■手順
.github/secret_scanning.yml ファイルをリポジトリに作成。
以下のように除外するパスを指定する

シークレットのカスタムパターン
組織で利用しているシークレットの形式が、Github既定のシークレットスキャンで検出されない場合に、独自に定義して検出させることができる。
■作成できるカスタムパターンの上限
・組織またはエンタープライズ単位:最大500
・プライベートリポジトリ単位:最大100(そもそも、パブリックリポジトリではカスタムパターン使えない)
■定義方法
Hyperscanの正規表現で定義する必要がある
Hyperscanの正規表現とは、拘束に大量の文字列をスキャンするための表現。普通の正規表現の一部だけサポートされている(スキャン高速化のために簡素化された正規表現というイメージ)
シークレットをリポジトリに載せてしまった場合
まずは、そのシークレットをサービス側で無効にする。
さらにリスクを減らすために、リポジトリ上からシークレット(無効済のもの)を削除しておくとよいでしょう。その際に、以下が注意点です。
■単純にリポジトリ上のコードからシークレットを消せばよいという訳ではない。
コミット履歴にもシークレット情報が残ってしまう。
また、チームメンバがそのリポジトリをローカルリポジトリにクローンしていた場合、再プッシュされることで、再度シークレットがリポジトリにアップロードされてしまう可能性があるため、チームメンバのローカルリポジトリ側の対応も必要(コミット履歴削除等)
コードスキャン
コードの脆弱性やエラーを検出する機能。スキャンするタイミングは、色々設定できる(定期的に実施、PR時、プッシュ時等)
CodeQL
コード解析エンジン。コードスキャンで使われる
CodeQLによる解析の流れ(ユーザの目に触れないところで行われている)
・コードをデータとして抽出(★)して、専用のリレーショナルデータベースが作られる
・そのデータベースに対して、CodeQLクエリを実行して問題を見つける
(★)抽出器によって実施される。抽出器はCodeQLの機能の一部。ソースコードを解析してデーターベース形式に変換するための専用プログラム(言語毎に用意されている)
CodeQLを使ったコードスキャンの実施方法3つ
①既定の方法(スキャンするタイミングとか決まっている)
- GitHub Actionsが使われる
- この方法だと、DB作成、クエリによる分析/SARIF作成、SARIFのGithubへアップロードが、裏側で勝手に行われる(ユーザの目に触れない)
②カスタムの方法(CodeQLクエリをカスタマイズできたりする)
- GitHub Actionsが使われる
- この方法だと、DB作成、クエリによる分析/SARIF作成、SARIFのGithubへアップロードが、裏側で勝手に行われる(ユーザの目に触れない)
- クエリのカスタマイズは、「.github/workflows/*yml」の中に直接、定義可能(小規模向け)し、別ファイルを用意して、「.github/workflows/*yml」から参照させることも可能(大規模向け。クエリを繰り返し使いたいときにも有効)
③外部CIからCodeQLを利用
- Github Actionsを使わない方法
- 既にGithub以外でCI基盤を使っている場合の選択肢
- 外部のCI基盤にCodeQL CLIをインストールして、実行する
- CodeQLクエリによる分析によって作成されたSARIFファイル(分析の結果)をGithubにアップロード(CodeQL CLIのコマンドによりコードスキャンAPIに送信される)することで、分析結果をGitHubに取り込むことができる(Github上でのアラート発出につなげられる)
サードパーティCIの機能で作成されたSARIFをGithubにアップロードすることも可能
SARIFは標準仕様なので、コードスキャン自体のエンジンとしてCodeQLを利用せずに、別のエンジンでコードスキャンを実施して、SARIFを作れれば、それをGithubにアップロードすることは可能
コードスキャンがあれば人によるレビューは不要か(以下は、ChatGPT回答)
人によるレビューは必要。コードスキャンによって、定型的な脆弱性など一定の検出は可能。ただし、業務ロジックに関わるコードなどコードスキャンでは善悪が判断できなものもある。
コンパイル言語に対するコードスキャン
コンパイル言語においては、単純にコードをスキャンするだけでは、脆弱性の発見できないケースがある。そのため、GHASのコードスキャンではビルドのプロセスを観測する。
★インタプリタ言語(コンパイル不要の言語)のコードスキャンは、そのままコードに対して実施される。
GitHub Actionsで、コードスキャンが実施される場合、以下の3つのアクションが使われる。
①github/codeql-action/init、②github/codeql-action/autobuild、③github/codeql-action/analyze
①③は、コンパイル言語/インタプリタ言語の両方で利用されるアクションだが、
②は、コンパイル言語でのみ利用されるアクション(②はビルドするためのアクションのため、ビルドという概念がないインタプリタ言語は関係のないアクション)
コードスキャン未対応の言語
PHPなど、未対応の言語があるので、要注意。
以下は、対応言語の一覧。
CodeQLの強み
単純なパターンマッチだけではなく、データの流れまで解析できる。「ユーザからの入力が安全でない形で使われる」ようなコードになっている場合、脆弱性として検出できる。
Dependabot
リポジトリの依存関係の管理を自動化する GitHub ツール
依存関係における脆弱性の抽出
SBOMとAdvisory Databeseが突合され、脆弱性が抽出され、Dependabot Alertsが発出されるという流れ
■SBOMとは
Software Bill of Materials(ソフトウェアの部品表)
業界標準の ソフトウェア パッケージ データ交換 (SPDX) 形式で、Githubからエクスポート可能(UI or REST API)
■SBOMが作成される流れ
ロックファイル/マニフェスト
→
Depedency Graph(ロックファイル/マニフェストから作られる)
→
SBOM(ソフトウェアを構成する部品(ライブラリ・モジュール・依存関係)の一覧表(Dependency Graphから作られる)
★業界標準の ソフトウェア パッケージ データ交換 (SPDX) 形式で、Githubからエクスポート可能(UI or REST API)
■Advisory Databaseとは
オープンソフトウェアの脆弱性情報を集約した、GH公式の脆弱性データベース
Dependabot 自動トリアージルール
一定の条件(影響度が低い場合等)に一致するDependabotアラートを自動的に却下する機能(アラート疲れ防止などのために)
ルールは2種類ある
①GitHub プリセットルール
②カスタム自動トリアージルール(プリセットルールでは要件満たさないときに使う)
2つの更新管理
時間の経過とともに、①新たなセキュリティ脆弱性が見つかったり、②利用しているライブラリが古くなってしまった際に、通知してくれる機能
① Dependabot セキュリティ更新プログラム
・脆弱な依存関係が見つかった際に、それを自動的に更新するためのプルリクエストを作成してくれる(Dependabotアラートが裏側では使われており、Dependabotアラートをトリガーに、このプルリクエストが走るイメージ)
② Dependabot バージョンの更新
・脆弱性がなかったとしても、依存ライブラリを最新に保つための機能(古くなったら、PR要求を出してくれる機能)
・有効化には dependabot.yml (.githubディレクトリに配置)が必要
依存関係レビュー
プルリクエストで導入されようとしているライブラリをプレビューし、安全でない依存関係がマージされることを防止できる
レビューにはGithubアクションを利用
依存関係レビューは、Githubアクションの機能が必要にある。
YAMLファイルに定義した条件(危険なPKGが含まれている等)に合致しているかチェックする。
条件の定義の仕方は以下の2種類
①.github/workflows/*.yml に直接記載
Githubアクションのワークフローファイルに直接記載。小規模向け
②別の.ymlファイルに記載
Githubアクションのワークフローファイルの中で、そのYAMLファイルを指定する。複数のGithubアクションのワークフローファイルから参照できるので、大規模向け(組織の共通ルールとして利用できる)
ブランチ保護規則
条件に合致した場合に、実際にどうするか(ブロックするか)を決めるのは、「ブランチ保護規則」の設定に依存
GHAS関連その他
セキュリティポリシー
SECURITY.mdファイルに記載する(リポジトリ直下や、「.github」フォルダに配置する)
システム的に何かを制御するためのファイルというよりは、単純にリポジトリ(または組織)内のルール(脆弱性の報告方法等)を明文化したもの
リポジトリのルールセット
ルールセットを使うことで、リポジトリのセキュリティ性を向上させることができる
以下が、実現できることの例です。
・署名付きコミットを要求する(コミット改ざん対策)
・強制プッシュの禁止
・プッシュできるユーザの制限
ログの保存期間
Enterprise Cloud での 90 日間。Enterprise Server で 120 日
期間が限定的なので、長期的な分析が必要な場合は、外部へのエクスポート&保管が必要
GHASを学習する上で知っておくべきこと
ソフトウェア開発関連の基礎知識
マニフェストファイルとロックファイル
どちらもプロジェクトがどんなライブラリに依存しているかを記録しているファイル。
マニフェストファイルの方が抽象度が高め。ファイル名は各エコシステム毎(Node.jsのマニフェストファイル名はpackage.json等)に固定で決まっている。npm等のツールは固定されたファイル名を前提に自動検出するため。
■マニフェストファイル
「このプロジェクトは何のライブラリを使いたいか」宣言するファイル。設計図・希望リストのようなイメージ。人間が読むことを想定されて作られているファイルというイメージ。
例:Node.jsのpackage.json
ファイル中身の中身は以下(18系ならOKという意味。あいまいに書かれることが多い)
react: ^18.0.0
■ロックファイル
実際にインストールされた“正確なバージョン”を記載するファイル。
ロックファイルにより、推移的な依存関係をGHASは把握できます(=正しいdependabot Graphが作成できるイメージ)
例:Node.jsのpackage-lock.json
ファイル中身の中身は以下(完全に確定したバージョン が書かれる)
react 18.2.0
react-dom 18.2.0
scheduler 0.23.0
■推移的な依存関係とは?
あるアプリがライブラリAを使っている。ライブラリAが別のライブラリBを使っている。ライブラリBがまた別のライブラリCを使っている。
この場合、ライブラリA、ライブラリB、ライブラリCは推移的な依存関係がある
GHAS観点でいうと、アプリが直接的に利用しているライブラリAの脆弱性をチェックするだけでは不足しているので、推移的な依存関係にある、ライブラリB、ライブラリCもチェックしないといけない。推移的な依存関係を、把握するためにロックファイルが使われる。
■GHASとの関連
Depadabot Graphは、マニフェストファイルやロックファイルをもとに作成される
CI/CDツールを使ったデプロイにおいて、コンパイルされるタイミング
コンパイルは、CI/CDツールの中で実行されるのが一般的(開発者のデバイスでコンパイルした後の実行ファイルをCI/CDに乗せるということは一般的ではない)
コンパイルをビルドのプロセスを、CI/CDツールが観測できないと、コードの脆弱性を正確に把握することができない。
pipでインストールしたライブラリ自体が、他のライブラリ(lib②とする)を使っている場合は、lib②もpipを実行したPCにダウンロードされるか
ダウンロードされる
pipは、インストールしようとしているライブラリの依存ライブラリを調べ、必要なものをすべて再帰的にダウンロードします。
Github関連の基礎知識
全体像
以下の図が分かりやすい(引用元:https://envader.plus/article/68)

- 「ブランチを切る」とは、あるブランチから、別のブランチを作成すること(元のブランチをコピーして、別の名前を付けるイメージ)
フォーク
他人のGithubリポジトリを、自分のGithub環境にコピーすること(あくまでGithub内の話)。
OSSに貢献したい場合や、他人のリポジトリのコンテンツを使って自由に検証したいときなどに使う
★クローンとの違い
クローンは、Githubリポジトリを、ローカルPCにコピーすること
プル
既に存在しているローカルリポジトリを、最新の状態更新(リモートリポジトリの状態に合わせる)すること
★クローンとの違い
クローンは、ローカルリポジトリがない状態で、リモートリポジトリを丸ごとコピーする操作です(「更新」ではない)
チェックアウト
ローカルリポジトリにおいて、作業するリポジトリを切り替える操作
コミット
ブランチ内(ローカルリポジトリの場合もあるし、リモートリポジトリの場合もある)で、変更を履歴として保存すること
プルリクエスト(=マージしてもらうための申請)に対する承認とマージ
承認を実施したら、即マージされるわけではありません。
①承認した上で、②マージを実施することでマージが完了します。
①承認

②マージ

Github Actionsの仕組み
.github/workflow/配下にあるYAMLファイル(ワークフローファイルと呼ばれる)を実行します。
実行するタイミングや具体的にどのようなActionを実行するかも、このYAMLファイルに記載します。
Github Actionsのランナーとは
Github Actionsのジョブを実際に実行するマシン(実行環境)。
たとえば、本番環境にデプロイしようとしているコードを、このランナー上で動かしテストしたりできる。
Github Enterprise Server
オンプレ版のGithub。
GitHub Connectを使うことで、Github(クラウド)と連携ができるようになり、クラウド側(Dependabotアラート等)を利用できるようになる
githubディレクトリ(.github/)
githubディレクトリは、Githubが参照する設定ファイル(CI、セキュリティ等に関する)が保存されている場所
Gitフック
Git操作の特定のタイミングで実行されるスクリプトのこと。Gitを操作しているローカルPCにおいて利用できる機能。
実行したいスクリプトは、ローカルリポジトリの.git/hooks/配下に配置する。
ローカルリポジトリにおけるコミット前に、”コードにシークレットが含まれていないか”をチェックしてくれるようなスクリプトを動かしたりできる。
個人アカウントレベルで、シークレットのプッシュを防ぐ機能
複数のパブリックリポジトリで作業をしているような場合で、そのパブリックリポジトリでプッシュ保護が有効でない場合、プッシュ操作によりシークレットがパブリックリポジトリにアップされてしまう可能性がある。
そんな状況を防ぎたい場合、個人のGitHubアカウント設定で「Push Protection for youself」を有効にすることで対処が可能。
パブリックリポジトリへのプッシュは、GitHub上で認証が完了している前提で実施できる操作。そのため、この「Push Protection for youself」を有効にしておくことで、間違ってシークレットを含むコードをプッシュしてしまった場合でも、GitHubがブロックしてくれる。
個人アカウントに紐づく通知受信箱
Githubからの通知を確認できる機能(メールの受信ボックスみたいなもの)
以下のURLからアクセス可能(’Githubログインした後の画面から遷移する方法は不明)
https://github.com/notifications
その他
演習
MS learnに演習問題が用意されています。実際に操作確認できるので、理解が進むと思います。1演習あたり20分~30分程度です。github個人アカウントがあれば大丈夫です。
■depandabot
(演習内容)
ロックファイルを編集します。脆弱性を含むライブラリが存在することを、dependabotが検出しアラートが欲出されます。PRも自動で作成されます。
■シークレットスキャン
(演習内容)
コードの中に、シークレット情報を意図的に追記します。アラートが上がります。次にプッシュ保護についても動作確認します。
■コードスキャン
https://learn.microsoft.com/ja-jp/training/modules/configure-code-scanning/5-exercise
(演習内容)
コードの中にSQLインジェクション脆弱性を含む内容を追記します。mainブランチにPRすると、コードスキャンが機能します。mainブランチ側でマージが完了すると、アラートが上がります。
注意点メモ
- リポジトリを自分の環境にフォークすることで演習ができます。
- フォークした後、少し時間がたつと(30秒くらい)、「コード」タブの内容が更新されます。「演習を開始する」というようなボタンが出てきます。
- 演習内容通りに進めれば、画面がどんどん更新されていきます。たまにコメント欄に「●●と記載して」というような指示がありますが、演習内容が書かれているページのコメント欄(画面の下の方)に、その内容をそのまま記載します(Github Actionsで、コメント欄に記載された内容をトリガーに画面更新が進むようになっている箇所があるようです)









ディスカッション
コメント一覧
まだ、コメントがありません