🏠 ホーム ニュース 📖 解説記事 📚 トピック解説 🏷️ タグ一覧 ℹ️ About
ツール
💰 API料金計算機 NEW
🔍 記事を検索
カテゴリ
📡 RSSフィード
Follow
X (Twitter) 🧵 Threads
🔧 ツール
💰API料金計算機
トピック
🧠 Claude Code 🤖 AIエージェント 🎵 AIコーディング / Vibe Coding 🔌 MCP(Model Context Protocol) 🔍 RAG & ナレッジシステム 💬 LLM / ローカルAI 🔒 セキュリティ ⚙️ DevOps & 自動化 💰 Claude API & 料金 🎨 UI生成 & デザインシステム
ニュース一覧 🏷️タグから探す
Subscribe
📡 RSSフィード
ホーム security 2026.04.26

CAMPFIREのGitHub侵害から学ぶ:エンジニアが今すぐ直すべきSecret管理と最小権限設計

CAMPFIRE GitHub Breach — Secret Management & Least Privilege for Engineers
🛡️
CAMPFIREのGitHub侵害から学ぶ:エンジニアが今すぐ直すべきSecret管理と最小権限設計 - AIツール日本語解説 | AI Heartland
// なぜ使えるか
CAMPFIREのGitHub不正アクセスはソースコード閲覧から内部DBへ連鎖し22.5万件を漏洩させた。この侵害経路は.envの誤コミット・広すぎるPATスコープ・DBのパブリック露出という三つの既知の穴が重なって生じる。コード例付きで今日から修正できる対策を整理する。

2026年4月24日、CAMPFIREがGitHubアカウントへの不正アクセスを起点とした個人情報漏洩(最大225,846件・銀行口座情報約82,465件含む)を公表した。4月2日の侵入から約19日間、攻撃者はソースコードを閲覧し、4月21日には顧客管理データベースへの接続を完遂している。

GitHubアカウント1つを奪われ、3週間後に顧客DBが落ちた。この侵害経路はセキュリティ界では「既知の問題」だ。開発現場で繰り返される三つの穴——Secretの誤コミット・広すぎるトークンスコープ・DBのプライベート非隔離——が重なった結果として起きる。本記事はエンジニアがこの穴を塞ぐための実践的な対策を整理する。

今回の侵害はGitHub起点のサプライチェーン型攻撃と同じ構造を持ちます。攻撃手法の全体像は サプライチェーンセキュリティ完全ガイド2026|攻撃手法・防御ツール・実践チェックリスト で解説しています。

侵害の連鎖構造:なぜGitHub侵害がDBに波及するのか

CAMPFIREの事案で公表されている情報を元に、侵害の連鎖を推定する。GitHubへの不正アクセスを起点に内部DBへ到達するまでのステップは多くの場合、以下の流れをたどる。

flowchart LR A["GitHubアカウント
乗っ取り"] --> B["リポジトリ内の
.env / config
ファイル閲覧"] B --> C["DB接続文字列
APIキー
Internal URLの取得"] C --> D["プライベートDB
or内部APIへ
直接接続"] D --> E["顧客データ
大量取得"] style A fill:#c0392b,color:#fff style E fill:#c0392b,color:#fff B:::vuln C:::vuln D:::vuln classDef vuln stroke:#e74c3c,stroke-width:2px

この連鎖を断ち切るには、それぞれのステップに対する独立した防御が必要だ。どれか一つだけを直しても「多段防御」にならない。

侵害ステップ 根本原因 対策カテゴリ
GitHubアカウント乗っ取り 2FA未設定・PATの過剰スコープ 認証強化・最小権限
リポジトリ内のSecret漏洩 .envの誤コミット・ハードコード Secret管理
内部DBへの直接接続 DBがパブリック公開・Security Group開放 ネットワーク隔離
データ大量取得 検知・ログ不足・IAMの過剰権限 ロギング・監視

対策①:Secretをリポジトリから追い出す

最初に塞ぐべき穴は「ソースコードにSecretが混入しているか」だ。

.envファイルの誤コミットを防ぐ

.gitignoreに追加するだけでは不十分だ。すでにコミット履歴に入ってしまっているケースを想定した二重の防壁が必要となる。

# .gitignoreに追加(最低限)
echo ".env" >> .gitignore
echo ".env.local" >> .gitignore
echo ".env.*.local" >> .gitignore
echo "*.pem" >> .gitignore
echo "credentials.json" >> .gitignore
echo ".aws/credentials" >> .gitignore

# git-secretsでコミット前チェックを強制する(推奨)
brew install git-secrets
git secrets --install   # hooksをローカルリポジトリに設置
git secrets --register-aws  # AWS系のパターンを自動検出

# pre-commitフレームワークを使う場合
pip install pre-commit
# .pre-commit-config.yaml(リポジトリルートに置く)
repos:
  - repo: https://github.com/Yelp/detect-secrets
    rev: v1.4.0
    hooks:
      - id: detect-secrets
        args: ['--baseline', '.secrets.baseline']
  - repo: https://github.com/gitleaks/gitleaks
    rev: v8.18.0
    hooks:
      - id: gitleaks

すでにコミット履歴に入ってしまったSecretを削除する

# git filter-repo を使ったSecret履歴削除(BFGより推奨)
pip install git-filter-repo

# 対象ファイルをすべてのコミット履歴から削除
git filter-repo --path .env --invert-paths

# または特定の文字列をコミット履歴から置換
git filter-repo --replace-text replacements.txt
# replacements.txt の内容: AKIAIOSFODNN7EXAMPLE==>REMOVED_AWS_KEY

# 完了後、force push(チームに事前周知が必要)
git push origin --force --all
git push origin --force --tags
Secretの削除とローテーションは必ずセットで行う
コミット履歴からSecretを削除しても、過去にリポジトリをクローンした人のローカルコピーには残ります。漏洩が疑われる場合は削除と同時にSecretを無効化し、新しいキーを発行してください。「削除したから安全」ではありません。

truffleHogで既存リポジトリを全スキャンする

# truffleHogで全コミット履歴をスキャン
pip install trufflehog
trufflehog git https://github.com/your-org/your-repo --only-verified

# ローカルリポジトリをスキャン
trufflehog filesystem /path/to/repo

# GitHub Organization全体をスキャン
trufflehog github --org=your-org --token=ghp_xxxx

Gemini APIキーが不正利用される仕組みと防止策でも解説しているが、一度コミットされたSecretはスキャナーによって秒単位で検出される。truffleHogをCI/CDに組み込み、プッシュのたびに全履歴をスキャンする体制が理想だ。


対策②:GitHub権限を最小化する

GitHubアカウントが侵害されたとき、攻撃者が「何にアクセスできるか」は付与されている権限の幅に依存する。

Classic PATを廃止してFine-grained PATへ移行する

Classic Personal Access Tokenはスコープが粗く、一つのトークンで組織全体のリポジトリに対してrepo権限を持ってしまう。Fine-grained PATではリポジトリ単位・操作種別単位でスコープを絞れる。

# Fine-grained PATの作成手順(GitHub CLI経由)
# GitHub CLIでリポジトリ指定・権限限定のトークンを作成
gh auth refresh -s admin:org

# または GitHub Web UI: Settings > Developer settings > 
#   Personal access tokens > Fine-grained tokens > Generate new token
# - Repository access: Selected repositories のみ
# - Permissions: 必要な最小権限だけ選択
#   (例: Contents: Read-only, Pull requests: Read and write)
PATの種類 スコープ粒度 リポジトリ指定 推奨用途
Classic PAT スコープ単位(repoで全リポジトリ) 不可 廃止推奨
Fine-grained PAT 権限種別×リポジトリ単位 可能 個人・Bot用途全般
GitHub Apps Installationスコープ Org/Repo単位 CI/CD・自動化
GITHUB_TOKEN ワークフロー単位 実行リポジトリのみ GitHub Actions

GitHub OrganizationのSSO・SCIM・2FAを強制する

# .github/settings.yml(branch protection rules の例)
# GitHub Managed User / Enterprise でSAML SSOを強制するには
# OrganizationのSecurity設定から有効化

# ブランチ保護ルール(GitHub REST API での設定)
# PUT /repos/{owner}/{repo}/branches/{branch}/protection
{
  "required_status_checks": {
    "strict": true,
    "contexts": ["ci/security-scan"]
  },
  "enforce_admins": true,
  "required_pull_request_reviews": {
    "required_approving_review_count": 1,
    "dismiss_stale_reviews": true
  },
  "restrictions": null,
  "required_linear_history": true,
  "allow_force_pushes": false,
  "allow_deletions": false
}
Organization設定で有効にすべき項目
Settings > Security: Two-factor authentication requirement(全メンバーに2FA強制)、SAML SSO(Enterprise)
Settings > Actions > General: Fork pull requestsのワークフロー実行を制限、third-party Actionの許可リスト制御

対策③:GitHub OIDCで静的キーを排除する

GitHub ActionsからAWSやGCPにアクセスするとき、静的なアクセスキー(AWS_ACCESS_KEY_ID等)をSecretsに保存するのはリスクが高い。Secretsに保存されたキーはワークフローのログや環境変数ダンプから露出する可能性がある。

GitHub OIDC + AWS IAMの構成では、ワークフローごとにOIDCトークンが発行され、AWSが検証した上で一時的な認証情報を払い出す。静的キーをGitHubに保存する必要がなくなる。

sequenceDiagram participant GHA as GitHub Actions participant OIDC as GitHub OIDC Provider participant STS as AWS STS participant AWS as AWS Resource GHA->>OIDC: OIDCトークンを要求 OIDC-->>GHA: JWTトークン(sub: repo:org/repo:ref:refs/heads/main) GHA->>STS: AssumeRoleWithWebIdentity(JWTトークン + RoleARN) STS->>OIDC: トークン検証 OIDC-->>STS: 検証OK STS-->>GHA: 一時認証情報(有効期限付き) GHA->>AWS: 一時認証情報でAPIコール
# .github/workflows/deploy.yml — OIDC認証の実装例
name: Deploy
on:
  push:
    branches: [main]

permissions:
  id-token: write   # OIDCトークン発行に必要
  contents: read

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683  # v4.2.2

      - name: Configure AWS credentials (OIDC)
        uses: aws-actions/configure-aws-credentials@e3dd6a429d7300a6a4c196c26e071d42e0343502  # v4.0.2
        with:
          role-to-assume: arn:aws:iam::123456789012:role/GitHubActionsDeployRole
          aws-region: ap-northeast-1
          # AWS_ACCESS_KEY_ID は不要。静的キーをSecretsに保存しない

      - name: Deploy to S3
        run: aws s3 sync ./dist s3://my-bucket/
# Terraform — GitHub OIDC用 IAMロールの設定
resource "aws_iam_role" "github_actions" {
  name = "GitHubActionsDeployRole"

  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [{
      Effect = "Allow"
      Principal = {
        Federated = "arn:aws:iam::${data.aws_caller_identity.current.account_id}:oidc-provider/token.actions.githubusercontent.com"
      }
      Action = "sts:AssumeRoleWithWebIdentity"
      Condition = {
        StringEquals = {
          "token.actions.githubusercontent.com:aud" = "sts.amazonaws.com"
        }
        StringLike = {
          # mainブランチからのワークフローのみ許可
          "token.actions.githubusercontent.com:sub" = "repo:your-org/your-repo:ref:refs/heads/main"
        }
      }
    }]
  })
}

AWS Secrets ManagerとParameter Storeの使い分け

OIDCでAWSにアクセスできるようになったら、DBパスワードやAPIキーはAWS Secrets Managerで管理する。ランタイムでSecretを取得し、コードにもCI/CDにもキーを置かない構成が理想だ。

# Python — ランタイムでAWS Secrets Managerからキーを取得
import boto3
import json

def get_secret(secret_name: str, region: str = "ap-northeast-1") -> dict:
    client = boto3.client("secretsmanager", region_name=region)
    response = client.get_secret_value(SecretId=secret_name)
    return json.loads(response["SecretString"])

# 使用例: DBパスワードをコードに書かず、実行時に取得
db_secret = get_secret("prod/myapp/db")
DATABASE_URL = f"postgresql://{db_secret['username']}:{db_secret['password']}@{db_secret['host']}/mydb"
サービス 用途 自動ローテーション コスト
AWS Secrets Manager DBパスワード・APIキーなど機密度の高い値 あり(RDS自動ローテーション対応) $0.40/シークレット/月
AWS Parameter Store (Standard) 設定値・非機密のパラメータ なし 無料(標準)〜
AWS Parameter Store (Advanced) 機密度中程度の設定値 あり $0.05/パラメータ/月
HashiCorp Vault マルチクラウド・オンプレ環境 あり(動的シークレット) OSS無料〜Enterprise有料

対策④:DBをプライベートネットワークに隔離する

GitHubからDBへの直接接続を防ぐ最も確実な手段は、DBをパブリックインターネットから完全に切り離すことだ。

AWS RDS/Auroraのプライベート配置

# Terraform — RDSをプライベートサブネットに配置する最小構成
resource "aws_db_subnet_group" "private" {
  name       = "myapp-private-db-subnet"
  subnet_ids = aws_subnet.private[*].id  # プライベートサブネットのみ
}

resource "aws_security_group" "rds" {
  name   = "rds-sg"
  vpc_id = aws_vpc.main.id

  # アプリケーションのSGからのみ接続を許可
  ingress {
    from_port       = 5432
    to_port         = 5432
    protocol        = "tcp"
    security_groups = [aws_security_group.app.id]  # CIDRブロックではなくSGを指定
  }

  # アウトバウンドは制限しない(必要に応じて絞る)
  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

resource "aws_db_instance" "main" {
  identifier        = "myapp-db"
  engine            = "postgres"
  instance_class    = "db.t3.medium"
  db_subnet_group_name = aws_db_subnet_group.private.name
  vpc_security_group_ids = [aws_security_group.rds.id]

  # 重要: パブリックアクセスを明示的に禁止
  publicly_accessible = false

  # 削除保護を有効化
  deletion_protection = true

  # 自動バックアップ(7日)
  backup_retention_period = 7
}

開発者がローカルからアクセスする方法

DBをプライベートにすると「開発者がローカルからアクセスできなくなる」問題が生じる。SSHトンネルやSSM Session Managerで安全にアクセスできる。

# AWS SSM Session Managerでポートフォワードする(推奨)
# SSHキーが不要でAuditログも残る

# EC2インスタンス経由でRDSにポートフォワード
aws ssm start-session \
  --target i-0123456789abcdef0 \
  --document-name AWS-StartPortForwardingSessionToRemoteHost \
  --parameters '{
    "host": ["myapp-db.xxxxxx.ap-northeast-1.rds.amazonaws.com"],
    "portNumber": ["5432"],
    "localPortNumber": ["5432"]
  }'

# 別ターミナルで接続(ローカルの5432に転送されている)
psql -h localhost -U dbuser -d mydb
flowchart LR subgraph Internet["インターネット"] Dev["開発者
ローカル PC"] Attacker["攻撃者
(GitHub経由)"] end subgraph VPC["VPC(プライベート)"] subgraph PublicSubnet["パブリックサブネット"] Bastion["Bastion
or SSM Endpoint"] end subgraph PrivateSubnet["プライベートサブネット"] App["アプリケーション
(ECS/Lambda)"] RDS[("RDS
publicly_accessible=false")] end end Dev -->|"SSM Port Forward"| Bastion Bastion --> RDS App --> RDS Attacker -->|"❌ 直接接続不可"| RDS style Attacker fill:#c0392b,color:#fff style RDS fill:#27ae60,color:#fff

対策⑤:GitHub Actionsのシークレット漏洩パターンを塞ぐ

CI/CDパイプラインはSecret管理の弱点になりやすい。GitHub Actionsで発生するシークレット漏洩の主なパターンを整理する。

パターン1:echoでSecretがログに露出する

# NG: こう書くとSecretがGitHubのActionsログに出力される
- name: Deploy
  run: |
    echo "Deploying with key: $"  # ← ログに残る
    curl -H "Authorization: $API_KEY" https://api.example.com/deploy

# OK: Secretは環境変数経由で渡し、echoしない
- name: Deploy
  env:
    API_KEY: $
  run: |
    curl -H "Authorization: $API_KEY" https://api.example.com/deploy

パターン2:フォークPRワークフローでのSecret漏洩

# NG: pull_request_targetイベントで外部コードを実行するとSecretが漏洩する
on:
  pull_request_target:  # ← フォーク元のSecretsにアクセスできてしまう
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          ref: $  # ← フォーク先のコードを実行
      - run: npm test  # フォーク先の悪意あるpackage.jsonが実行される

# OK: フォークPRには最小権限のみ付与
on:
  pull_request:  # pull_request はSecretsにアクセスできない
jobs:
  test:
    runs-on: ubuntu-latest
    permissions:
      contents: read  # 必要最小限
    steps:
      - uses: actions/checkout@v4
      - run: npm test

パターン3:サードパーティActionのタグ固定をしていない

# NG: タグ(v4)はいつでも書き換えられる。タグハイジャック攻撃が成立する
- uses: actions/checkout@v4

# OK: コミットハッシュで固定する(イミュータブル)
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683  # v4.2.2

Renovate・Dependabotを悪用したサプライチェーン攻撃の仕組みと防御策でも解説しているように、サードパーティの依存関係を信頼しすぎることがサプライチェーン攻撃の起点になる。

GITHUB_TOKENのデフォルト権限を制限する

# .github/workflows/ci.yml — ワークフロー全体で最小権限を宣言
name: CI
on: [push, pull_request]

# デフォルトのpermissionsをread-onlyに設定
permissions:
  contents: read

jobs:
  test:
    runs-on: ubuntu-latest
    # ジョブ単位でも最小権限を宣言(ワークフロー宣言を上書き)
    permissions:
      contents: read
      checks: write  # テスト結果のAnnotationを書くために必要
    steps:
      - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
      - run: npm ci && npm test
# Organization設定でデフォルト権限を制限する(Settings > Actions > General)
# "Workflow permissions" を "Read repository contents and packages permissions" に設定
# これでGITHUB_TOKENのデフォルトはread-onlyになる

対策⑥:GitHub Actionsセキュリティのチェックリスト

上記の対策を実施状況で整理する。

# actionlintでワークフローファイルの静的解析
brew install actionlint
actionlint .github/workflows/*.yml

# OpenSSF ScorecardでリポジトリのセキュリティスコアをチェックCSS
docker run -e GITHUB_AUTH_TOKEN=ghp_xxx \
  gcr.io/openssf/scorecard:stable \
  --repo=github.com/your-org/your-repo \
  --show-details
チェック項目 コマンド・設定場所 重要度
Classic PATの廃止確認 Settings > Developer settings > Classic tokens 🔴 高
Org全メンバーに2FA強制 Org Settings > Security > Require 2FA 🔴 高
リポジトリにSecretが混入していないか trufflehog git <repo> 🔴 高
DBのpublicly_accessible=falseを確認 AWS Console / Terraform tfstate 🔴 高
GitHub OIDC導入(静的AWSキーの削除) GitHub Secrets一覧 + IAMロール確認 🟡 中
サードパーティActionのコミットハッシュ固定 ワークフローファイル目視 or actionlint 🟡 中
GITHUB_TOKENのデフォルト権限をread-only Org Settings > Actions > Permissions 🟡 中
pre-commitでSecretスキャン .pre-commit-config.yaml 🟡 中
ブランチ保護ルールでforce push禁止 リポジトリ Settings > Branches 🟢 低
Dependabotでサードパーティ更新を自動化 .github/dependabot.yml 🟢 低

対策⑦:侵入後に「何をされたか」を把握できる体制を作る

侵入を防ぐ対策と同じくらい重要なのが、侵入された後に何が起きたかを正確に追跡できるようにしておくことだ。CAMPFIREの事案では4月2日の侵入から4月21日のDB接触確認まで約19日間かかった。もしDB監査ログが有効でなければ、攻撃者が「何を読んだか・何を変えたか」の特定はさらに困難になる。

侵入は必ず起きる前提でログを設計する。インシデント対応(DFIR: Digital Forensics and Incident Response)では「ログの不在」が被害範囲の不明確化につながり、報告義務の履行を遅らせる最大の要因になる。

DB監査ログの有効化

AWS RDS/Aurora(PostgreSQL)

-- PostgreSQLの監査拡張: pgauditを有効化
-- RDSパラメータグループに以下を設定:
-- shared_preload_libraries = pgaudit
-- pgaudit.log = 'read,write,ddl,role'
-- pgaudit.log_catalog = on
-- pgaudit.log_parameter = on

-- 有効化確認
SHOW pgaudit.log;
-- 出力例: read,write,ddl,role

-- 記録されるイベントの例
-- SESSION:  接続・切断
-- READ:     SELECT文(誰がどのテーブルを読んだか)
-- WRITE:    INSERT/UPDATE/DELETE
-- DDL:      CREATE/ALTER/DROP
-- ROLE:     GRANT/REVOKE
# RDSパラメータグループをAWS CLIで設定
aws rds modify-db-parameter-group \
  --db-parameter-group-name myapp-pg-params \
  --parameters \
    "ParameterName=shared_preload_libraries,ParameterValue=pgaudit,ApplyMethod=pending-reboot" \
    "ParameterName=pgaudit.log,ParameterValue=read\,write\,ddl\,role,ApplyMethod=immediate"

# RDSのログをCloudWatch Logsにエクスポート
aws rds modify-db-instance \
  --db-instance-identifier myapp-db \
  --cloudwatch-logs-export-configuration EnableLogTypes=postgresql,upgrade

AWS RDS(MySQL)

-- MySQL: general_log と audit_log プラグインの有効化
-- RDSパラメータグループで設定:
-- general_log = 1
-- slow_query_log = 1
-- long_query_time = 1  (1秒以上のクエリを記録)

-- audit_logプラグイン(MySQL Enterprise / Percona)
INSTALL PLUGIN audit_log SONAME 'audit_log.so';
SET GLOBAL audit_log_policy = 'ALL';
SET GLOBAL audit_log_format = 'JSON';

-- 接続ログの確認
SELECT * FROM mysql.general_log ORDER BY event_time DESC LIMIT 20;

CloudTrailとCloudWatch Logsで証跡を保全する

RDSへのAPIコール(設定変更・スナップショット・パラメータ変更等)はCloudTrailで自動的に記録される。これに加えてCloudWatch Logsへのログ転送とアラートを設定する。

# Terraform — CloudTrail + S3 Object Lock でログ改竄防止
resource "aws_cloudtrail" "main" {
  name                          = "myapp-cloudtrail"
  s3_bucket_name                = aws_s3_bucket.cloudtrail_logs.id
  include_global_service_events = true
  is_multi_region_trail         = true
  enable_log_file_validation    = true  # ログファイルの整合性検証を有効化

  event_selector {
    read_write_type           = "All"
    include_management_events = true

    # S3へのデータアクセスも記録(オプション)
    data_resource {
      type   = "AWS::S3::Object"
      values = ["arn:aws:s3:::myapp-prod-*/*"]
    }
  }
}

# S3 Object Lock(ログの改竄・削除を防ぐ)
resource "aws_s3_bucket_object_lock_configuration" "cloudtrail" {
  bucket = aws_s3_bucket.cloudtrail_logs.id

  rule {
    default_retention {
      mode = "GOVERNANCE"  # 管理者でも指定期間は削除不可
      days = 365
    }
  }
}
ログの保存先は本番アカウントとは別のAWSアカウントにする
本番アカウントが侵害された場合、同アカウント内のCloudTrailログも改竄・削除される可能性があります。ログ専用のAWSアカウント(Security/Log Archive Account)に転送することで、攻撃者によるログの消去を防ぎます。AWS Organizationsのマルチアカウント構成が理想です。

インシデント発生時のフォレンジック手順

侵害を検知してから「タイムラインの再構成」と「影響範囲の特定」を進める手順を整理する。

# 1. CloudTrailからRDS関連の操作ログをJSONで取得
aws cloudtrail lookup-events \
  --lookup-attributes AttributeKey=ResourceType,AttributeValue=AWS::RDS::DBInstance \
  --start-time "2026-04-01T00:00:00Z" \
  --end-time "2026-04-25T00:00:00Z" \
  --max-results 100 \
  | jq '.Events[] | {EventTime, EventName, Username: .CloudTrailEvent | fromjson | .userIdentity.arn}'

# 2. RDSのPostgreSQLログからCloudWatch Logsで特定期間のクエリを検索
aws logs filter-log-events \
  --log-group-name "/aws/rds/instance/myapp-db/postgresql" \
  --start-time 1743465600000 \  # Unixタイムスタンプ (ms)
  --end-time 1745884800000 \
  --filter-pattern "ERROR" \
  | jq '.events[].message'

# 3. 異常な接続元IPを特定
aws logs filter-log-events \
  --log-group-name "/aws/rds/instance/myapp-db/postgresql" \
  --filter-pattern '"connection received"' \
  | jq '.events[].message' | sort | uniq -c | sort -rn | head -20

# 4. 特定テーブルへのSELECT(pgaudit有効時)を抽出
aws logs filter-log-events \
  --log-group-name "/aws/rds/instance/myapp-db/postgresql" \
  --filter-pattern '"AUDIT: SESSION" "users" "READ"'
flowchart TD A["侵害検知"] --> B["初動対応
(Secretローテーション・
アカウント停止)"] B --> C["タイムライン再構成"] C --> D["CloudTrailで
APIコール履歴を確認"] C --> E["RDS監査ログで
クエリ履歴を確認"] C --> F["GitHubAudit Logで
リポジトリ操作を確認"] D & E & F --> G["影響範囲の特定
(何のデータを・いつ・どれだけ)"] G --> H["個人情報保護委員会への
報告(72時間以内)"] G --> I["被害者への通知"] style A fill:#c0392b,color:#fff style H fill:#e67e22,color:#fff style I fill:#e67e22,color:#fff

SIEM連携:ログを集約して異常を早期検知する

複数のログソースを一元管理し、相関分析で侵害の兆候を早期に発見する。

# OpenSearch(ELK)へのCloudWatch Logsサブスクリプション設定例
# または Amazon Security Lakeを使う場合

# CloudWatch Logs → Kinesis Data Firehose → OpenSearch
# の構成でリアルタイムログ集約

# 検知すべき異常パターンの例
alert_rules:
  - name: "RDS異常接続"
    condition: >
      RDSアクセス元IPが通常のアプリケーションサーバーSG以外から来ている
    action: SNS通知 → PagerDuty

  - name: "深夜の大量SELECT"
    condition: >
      業務時間外(22:00-06:00 JST)に大量のSELECT文(>10,000行)が実行された
    action: SNS通知 → SlackアラートChannel

  - name: "GitHubからの直接DB接続"
    condition: >
      RDSのVPC Flow Logsで、GitHub ActionsのIPレンジからの接続が確認された
    action: 即座にアラート + 自動遮断
ログソース 保存先 保存期間 改竄防止
CloudTrail(APIコール) S3 + Object Lock 1年以上 Object Lock (GOVERNANCE)
RDS監査ログ(pgaudit) CloudWatch Logs → S3 90日〜1年 別アカウントS3
VPC Flow Logs CloudWatch Logs or S3 90日 別アカウントS3
GitHub Audit Log GitHub Enterprise or外部SIEM 180日(GitHub側) SIEM転送
アプリケーションログ CloudWatch Logs 30〜90日 ロール制限

インシデント発生時の初動:エンジニアが今すぐやること

自社システムでGitHub不正アクセスやSecret漏洩が疑われる場合の初動を整理する。

「調査してから対処」では遅すぎる
GitHub侵害が判明した時点でまず「影響を受けた可能性のあるすべてのSecretをローテーションする」を優先してください。調査と並行してローテーションを進め、漏洩有無の確定を待たないことが重要です。
緊急対応チェックリスト(発覚後24時間以内):

[ ] GitHubアカウントのパスワードをすぐに変更し、全セッションを失効させる
[ ] すべてのPersonal Access Tokenを失効させる(Settings > Developer settings)
[ ] 不審なOAuthアプリ認証を失効させる(Settings > Applications > Authorized OAuth Apps)
[ ] 影響を受けた可能性のあるAPIキー・DBパスワード・認証情報をすべてローテーション
[ ] AWSであれば CloudTrail でアクセスログを確認(想定外のAPIコールがないか)
[ ] GitHubのAudit Log(Organization)で不審な操作がないか確認
[ ] 個人情報保護委員会への報告要否を確認(規模・内容によって義務あり)
[ ] 警察への相談(不正アクセス禁止法違反の被害届)

GitHubのAudit Logの確認方法

# GitHub CLIでOrganizationのAudit Logを確認
gh api \
  -H "Accept: application/vnd.github+json" \
  "/orgs/{org}/audit-log?phrase=action:repo.access&per_page=100" \
  | jq '.[] | {created_at, action, actor, repo}'

# 確認すべきアクション
# repo.access         : リポジトリへのアクセス
# repo.download       : リポジトリのダウンロード(zip export)
# hook.create/destroy : Webhookの変更(データ外部送信の可能性)
# org.add_member      : 不審なメンバー追加
# repo.create         : 見知らぬリポジトリの作成

よくある質問

Q. Secret Scanningをリポジトリで有効にすれば十分ですか?

GitHub Secret Scanningは既知のパターン(AWSキー、GitHubトークン等)を自動検出しますが、カスタムのDBパスワードや社内APIキーは検出できません。Secret Scanningは「最後の砦」であり、プッシュ前のpre-commitスキャン(gitleaks・detect-secrets)と組み合わせる必要があります。

Q. HashiCorp VaultとAWS Secrets Managerはどちらを選ぶべきですか?

AWSのみを使用しているなら Secrets Manager が低運用コストでおすすめです。マルチクラウドやオンプレ環境が混在する場合はVaultが適しています。VaultはOSSとして自己ホストできますが運用負荷が高いため、小規模チームにはSecretsManagerが現実的です。

Q. プライベートリポジトリなら.envをコミットしても大丈夫ですか?

大丈夫ではありません。プライベートリポジトリへのアクセス権を持つアカウント(チームメンバー・Bot・GitHub App)が侵害された場合、リポジトリ内のSecretも全て漏洩します。今回のCAMPFIREの事案はまさにこのパターンです。

Q. Fine-grained PATへの移行でCIが壊れませんか?

CI/CDでClassic PATを使っている場合、Fine-grained PATへ移行する際にスコープを絞る必要があるため、必要な権限を一つずつ確認する手間が発生します。ただしGitHub ActionsではGITHUB_TOKENやGitHub Appsを使う方が管理しやすいため、CIはGITHUB_TOKENやOIDCに移行し、Fine-grained PATは手動操作用に限定するのが現実的なアプローチです。


参照ソース

B!
B! この記事をはてブに追加
よくある質問
Fine-grained PATとClassic PATの違いは何ですか?
Classic PATはリポジトリ横断でスコープが効き、一つのトークンで組織全体のリポジトリを読み書きできてしまいます。Fine-grained PATはリポジトリ単位・権限種別単位でスコープを絞れるため、漏洩しても被害範囲を最小化できます。2023年以降GitHub公式もFine-grained PATへの移行を推奨しています。
GitHub OIDCを使うとAWSのキーが不要になる仕組みは?
GitHub ActionsがワークフローごとにOIDCトークンを発行し、AWSのIAMロール(AssumeRoleWithWebIdentity)がそのトークンを検証してセッション認証情報を一時払い出しします。静的なAWS_ACCESS_KEY_IDをGitHubに保存する必要がなくなるため、キー漏洩リスクそのものを排除できます。
AWS RDSをプライベートに配置するとアプリからどうアクセスするのですか?
アプリケーション(ECS・Lambda・EC2)を同じVPC内のプライベートサブネットかパブリックサブネットに配置し、Security GroupでアプリのSGからのみ3306/5432ポートを許可します。開発者がローカルからアクセスする際はSSMセッションマネージャーを使ったSSHトンネルやSession Managerのポートフォワード機能を使います。
git historyにコミットしてしまったSecretはどう完全削除できますか?
git filter-repo(推奨)またはBFG Repo Cleanerを使ってコミット履歴から対象ファイルを削除し、force pushします。ただし削除しても過去にクローンしたコピーには残るため、Secretは必ず即座にローテーション(無効化→再発行)してください。削除と無効化は必ずセットで行います。
サードパーティのGitHub Actionはどのように監査すればいいですか?
まず利用しているActionをリストアップし、コミットハッシュで固定していない場合はfull commit SHAでピン留めします(例: uses: actions/checkout@v4 → uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683)。その後OpenSSF Scorecardやdependabot(GitHub Actions用)でサプライチェーンリスクを定期スキャンします。
🔒
セキュリティ
サプライチェーン攻撃、CVE分析、APIキー管理、セキュリティツール →
広告
役に立ったらシェアをお願いします
🔔 AI速報、毎日Xで配信中
Claude Code・MCP・AIエージェントの最新ニュースをいち早くお届け
@peaks2314 をフォロー
記事の信頼性について
AI Heartland エディトリアルポリシーに基づき作成
複数ソース照合
公式情報・報道等を突き合わせて確認
ファクトチェック済
ソースURLの内容を検証
参照ソース明記
記事末尾に引用元を掲載
関連記事
🛡️ OWASP APTS:AIエージェント時代の自律型ペネトレーションテスト基準を読む
OWASP APTSは自律型ペネトレーションテストプラットフォームのガバナンス基準。Tier 1〜3の173要件を全ドメイン解説。Claude Code・Cursor等が準拠できるか、セキュリティ界隈の懐疑論も踏まえ現実を検証。
2026.04.23
🕵️ BISSA Scanner解析:AI支援の大規模脆弱性スキャンと.envクレデンシャル窃取の仕組み
DFIR ReportがBISSA Scannerを解析。CVE-2025-55182を悪用してNext.jsに大規模スキャンを実行し、.envから3万件超のAPIキー・クラウド認証情報を窃取。Claude CodeをAI支援に組み込んだ攻撃プラットフォームの技術構造と防御策を解説。
2026.04.23
🛡️ 「人間かボットか」を超えて:CloudflareのPrivacy Pass・Web Bot Auth・Agent Registryで変わるアクセス制御
CloudflareがAIエージェント時代のアクセス制御を再設計。1日数十億トークンを処理するPrivacy Pass・Web Bot Auth・Agent RegistryとARC匿名認証の技術を解説。「人間 vs ボット」二分法がなぜ限界かを実例で示す。
2026.04.22
💉 GitHubコメントがAIエージェントを乗っ取る:「Comment and Control」攻撃の仕組みと防御策
GitHubのPR・IssueコメントにAIへの命令を隠す「Comment and Control」攻撃を解剖。Claude Code(CVSS 9.4)・Gemini CLI・GitHub CopilotがAPIキーを流出させる仕組みと、CI/CD環境での実践的防御策をコード例付きで解説。
2026.04.22
Popular
#1 POPULAR
🎨 Claude Design使い方・料金・v0/Figma比較 — テキストだけでプロトタイプを作るAnthropicのAIデザインツール
Anthropicが2026年4月に公開したClaude DesignはPro月額$20から追加費用なしで使えるAIデザインツール。テキスト指示だけでプロトタイプ・スライド・LPを生成できる。料金・Figma/v0/Lovable比較・オンボーディング手順・実践プロンプト例まで、デザイン知識ゼロから使い始める方法をまとめた。
#2 POPULAR
🎨 awesome-design-md:DESIGN.mdでAIにUI生成させる方法【58ブランド対応】
DESIGN.mdをプロジェクトに置くだけでAIエージェントが一貫したUI生成を実現。Vercel・Stripe・Claudeなど58ブランドのデザイン仕様をnpx 1コマンドで導入する方法と、実際の出力差を検証した結果を解説。
#3 POPULAR
📊 TradingView MCP:Claude CodeからTradingViewを完全操作する78ツールのMCPサーバー
TradingView MCPはClaude CodeからTradingView Desktopを直接操作できる78ツール搭載のMCPサーバー。チャート分析、Pine Script開発、マルチペイン、アラート管理、リプレイ練習まで自然言語で実行。導入手順を解説
#4 POPULAR
🔍 last30days-skill完全ガイド|Reddit・X・YouTube横断AIリサーチスキルの使い方2026年版
last30days-skillはReddit・X・YouTube・TikTokなど10+ソースを横断して最新30日のトレンドをAIで分析するClaude Codeスキル。使い方・設定・活用例を解説。
#5 POPULAR
🚨 Composer 脆弱性 CVE-2026-40261 PerforceドライバRCE、2.9.6/2.2.27で修正
PHP Composerの脆弱性CVE-2026-40261(CVSS 8.8)はPerforce未インストールでも任意コード実行が成立。composer install/requireでRCEリスク。修正版2.9.6/2.2.27へ今すぐcomposer self-updateで更新。全PHP開発者・CI環境が影響対象。
← 個人ブログのオーガニック検索比率が1ヶ月で62%になった話:自動化パイプラインと失敗の全記録