はじめに
こんにちは、京セラコミュニケーションシステム 金井(@kccs_natsuki-kanai)です。
今回は GitHub, GitLab で CI/CD を行う際、とくに CI のセキュリティスキャンの部分で使える機能を調べていきたいと思います。
この記事は2026年8月時点の情報をもとに作成しています。
GitHub/GitLab で多少の比較はしますが、優劣をつける内容ではありません。
CI で主にやるべきこと
基本的に以下のような内容を実施していると思います。
- 静的解析・コード品質チェック
- Lint(文法チェック)
- フォーマットチェック
- 型チェック
- セキュリティスキャン
- ビルド検証
- アプリケーションがエラーなくコンパイル・パッケージ化(Docker イメージ化など)できるか確認。
- 自動テスト
- 単体テスト (Unit Test)
- 統合テスト (Integration Test)
- テストカバレッジ計測
Linter や単体テストツールは各開発言語に対応したものがありますが、セキュリティスキャンは概ね複数の言語をカバーするものが多いです。
サードパーティの製品や OSS を使う方法もありますが、今回は GitHub, GitLab 組み込みのセキュリティスキャン機能を見ていきたいと思います。
セキュリティスキャンのおおまかな区分
SAST(Static Application Security Testing: ソースコード静的解析)
検出するリスク: SQL インジェクション、XSS、暗号化の実装ミスなど
SCA(Software Composition Analysis: ソフトウェア構成分析)
検出するリスク: サードパーティ製ライブラリの既知の脆弱性(CVE)
Secret Detection
検出するリスク: APIキー、トークン、パスワードのコミット(漏洩)
Container Scanning
検出するリスク: Docker イメージ内の OS パッケージ等の脆弱性
GitHub, GitLab のセキュリティスキャン機能
公式ドキュメントベースで標準機能として提供されているものをまとめてみました。
| 種別 | GitHub | GitLab |
|---|---|---|
| SAST | CodeQL | GitLab SAST(Semgrep), IaC Scan |
| SCA | Dependabot | Dependency scanning |
| Secret Detection | Secret Scanning / Push Protection | Secret Detection |
| Container Scanning | - | Container scanning(Trivy) |
GitHub の機能を触ってみる
まずは GitHub の機能から見ていこうと思います。(記事が長くなってしまったので、GitLab については 第2回に分けて書いていきます)
CodeQL
CodeQL は、セキュリティ チェックを自動化するために GitHub が開発した、コード分析エンジンです。 CodeQL を使用してコードを分析し、結果を code scanning アラートとして表示することができます。
CodeQL は、コードをデータのように扱うプログラミング言語および関連ツールです。 これは、コードの分析を容易にし、従来の静的アナライザーよりも信頼度の高いコード内の潜在的な脆弱性を見つけられるように、明示的に作成されました。
パブリックリポジトリでは無料です。プライベートリポジトリではアクティブコミッター数によって費用がかかります。
言語は
C/C++, C#, Go, Java/Kotlin, JavaScript/TypeScript, Python, Ruby, Rust, Swift, GitHub Actions workflows
がサポートされています。
(Terraform とかもサポートしてくれないですかね...コミュニティのカスタムエクストラクタはあるようですが...)
次のような GitHub Actions で試してみました。
スキャン対象のソースコード (src/vulnerable.js) には次のような内容を含めています。
- コマンド・コードインジェクション可能なコード
- 使用していない変数
name: "CodeQL Analysis"
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
jobs:
analyze:
name: Analyze JavaScript/TypeScript
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: [ 'javascript-typescript' ]
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
# 必要に応じてクエリパックを指定(デフォルトでも十分な検出が可能)
queries: security-extended,security-and-quality
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
with:
category: "/language:${{matrix.language}}"
CodeQL 結果
しっかり検出されていますね! Missing rate limiting など、脆弱性以外の推奨事項も出力してくれています。
UI でも問題のある部分がわかりやすく指示されています。優秀!
なお、スキャンレポート(SARIF形式)をダウンロードしたい場合、上記の Actions のように単純に CodeQL を実行しただけだとダウンロードできないので、解析ステップの後にアーティファクトをアップロードするステップを個別に追加する必要があります。
また、REST API でもアラートの詳細を取得することができますが、こちらは SARIF 形式ではなく GitHub 独自の形式となっています。
Dependabot
Dependabot は、依存関係の管理に役立つ 3 つの異なる機能で構成されています。
- Dependabot alerts: リポジトリで使われている依存関係の脆弱性についてユーザーに通知します。
- Dependabot security updates: 使われている依存関係のうち、既知のセキュリティ脆弱性があるものを更新するための pull request を自動的に生成します。
- Dependabot version updates: 依存関係を最新に保つための pull request を自動的に生成します。
こちらも、パブリックリポジトリでは完全無料です。プライベートリポジトリでも基本無料で使用できますが、カスタム自動トリアージルールを設定するには CodeQL 同様にアクティブコミッター数による追加費用が必要なようです。
自動でプルリクエストまで作成してくれるのはありがたいですね。
試しに、脆弱性を含むパッケージを package.json に追加してみました。
{
"name": "dependabot-test",
"version": "1.0.0",
"description": "",
"main": "src/vulnerable.js",
"scripts": {
"start": "node src/vulnerable.js"
},
"dependencies": {
"express": "4.16.0", # 脆弱性を含むバージョン
"lodash": "4.17.15" # 脆弱性を含むバージョン
}
}
Dependabot の設定ファイルは次のように作成しました。
version: 2
updates:
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: "daily"
Dependabot 結果
期待通りの脆弱性が検出され、プルリクエストも作成されています!優秀!
GitHub Actions に組み込んでプルリクエストのカスタマイズや自動承認・自動マージもできるらしいので、メンテナンスコストが大幅に削減できそうです。(きちんと自動テストとかも組み合わせないと怖いですが)
Secret Scanning / Push Protection
これはそもそも機密性の高いデータをリモートリポジトリに登録させないための機能です。
パブリックリポジトリでは無料 & デフォルトで有効、プライベートリポジトリではアクティブコミッター数による費用がかかります。
試しにコードに Slack API Token をハードコードして Push しようとしてみたら、次のように怒られました。
単に最新コードをスキャンしているだけでなく、コミット履歴に含まれる情報もスキャンしてくれています。
$ git push -u origin main
remote: error: GH013: Repository rule violations found for refs/heads/main.
remote:
remote: - GITHUB PUSH PROTECTION
remote: —————————————————————————————————————————
remote: Resolve the following violations before pushing again
remote:
remote: - Push cannot contain secrets
remote:
remote:
remote: (?) Learn how to resolve a blocked push
remote: https://docs.github.com/code-security/secret-scanning/working-with-secret-scanning-and-push-protection/working-with-push-protection-from-the-command-line#resolving-a-blocked-push
remote:
remote:
remote: —— Slack API Token ———————————————————————————————————
remote: locations:
remote: - commit: 54804a1dd6518aae86c654f244bce0ff41c90812
remote: path: src/vulnerable.js:37
remote:
remote: (?) To push, remove secret from commit(s) or follow this URL to allow the secret.
remote: https://github.com/xxxxx/my-repo/security/secret-scanning/unblock-secret/3ILuvbKINlsxHyTd5U9Tt7Jx6na
remote:
remote:
remote:
To github.com:xxxxx/my-repo.git
! [remote rejected] main -> main (push declined due to repository rule violations)
error: failed to push some refs to 'github.com:xxxxx/my-repo.git'
メッセージに出ている通り、このエラーを無視させて無理やり Push することもできますが、アラートが検出されます。
パスワードやトークンやアクセスキーなどを Git に保存してはいけないというのは皆さんご存知だと思うんですが、社内のプライベートリポジトリだと往々にして保存されていることが多くてヒヤヒヤするので、しない・させない・許さない が機能としてあるのは安心です。ダメ、絶対。
おわりに
パブリックリポジトリではほとんどの機能が使えて、GitHub はやっぱり OSS に優しいなぁというのを感じました。それでもサプライチェーン攻撃などの被害はしばしば耳にするので、100%安全にはならないですけどね...
CodeQL や Dependabot などサードパーティツールではなく独自製品なのも魅力です。世界最大の OSS コミュニティ強し。
これからは GitHub の OSS のリポジトリを見るとき、Security and quality タブも覗いてみようと思います。
引き続き、第2回で GitLab の機能を見ていこうと思います!



