T-CREATOR

GitHub Copilot で機密文字列を誤提案しないための緊急対策:ポリシーと検知ルール

GitHub Copilot で機密文字列を誤提案しないための緊急対策:ポリシーと検知ルール

AI コーディング支援ツールが開発現場に浸透する中、GitHub Copilot は開発者の生産性を大きく向上させています。しかし、その便利さの裏側には、機密情報の漏洩という深刻なリスクが潜んでいることをご存知でしょうか。

API キーやパスワード、アクセストークンといった機密文字列が、意図せず Copilot の学習データに含まれてしまい、他の開発者への提案として表示される可能性があります。この記事では、そうした事態を未然に防ぐための実践的な対策を、ポリシー設定と検知ルールの両面からご紹介します。

組織の情報資産を守りながら、AI の恩恵を最大限に活用する方法を一緒に学んでいきましょう。

背景

GitHub Copilot の仕組みと機密情報のリスク

GitHub Copilot は、OpenAI の大規模言語モデルをベースにした AI コーディングアシスタントです。膨大なコード資産から学習し、開発者が書いているコードのコンテキストを理解して、次に書くべきコードを提案してくれます。

この仕組み自体は非常に優れていますが、学習データに機密情報が含まれていた場合、それが他の開発者への提案として出力されるリスクがあるのです。

以下の図は、GitHub Copilot がどのようにコードを提案するかの基本フローを示しています。

mermaidflowchart TB
  dev["開発者がコードを<br/>記述中"] -->|コンテキスト送信| copilot["GitHub Copilot<br/>AIモデル"]
  copilot -->|学習データを参照| training["学習済みデータ<br/>(公開リポジトリ等)"]
  copilot -->|コード提案| suggestion["提案コード<br/>が表示される"]
  suggestion -->|採用| dev

  style training fill:#ffe6e6
  style suggestion fill:#e6f3ff

図で理解できる要点:

  • 開発者が書いているコードのコンテキストが Copilot に送信される
  • AI モデルは学習済みデータを参照して提案を生成する
  • 学習データに機密情報が含まれていると、それが提案される可能性がある

企業での採用が進む背景

近年、GitHub Copilot の企業導入が加速しています。その理由は明確で、開発速度の向上とコード品質の改善が実証されているからですね。

Microsoft の調査によると、GitHub Copilot を使用した開発者の 88%が生産性の向上を実感しており、コーディング時間が平均 55%短縮されたという報告もあります。

しかし、この急速な普及に伴い、セキュリティ対策の整備が追いついていない組織も少なくありません。機密情報の取り扱いに関する明確なガイドラインがないまま、個々の開発者が独自の判断で利用しているケースも見られるでしょう。

課題

機密文字列が漏洩する 3 つの経路

GitHub Copilot を使用する際、機密文字列が意図せず漏洩してしまう経路は主に 3 つあります。

#漏洩経路説明リスクレベル
1コード内への直接記載API キーやパスワードをソースコードに直接書き込む★★★ 高
2コメントや変数名機密情報を含むコメントや変数名が学習される★★☆ 中
3設定ファイルの誤コミット.envconfig.json をバージョン管理に含める★★★ 高

以下の図は、機密情報漏洩のリスクフローを視覚化したものです。

mermaidflowchart LR
  code["ソースコード<br/>作成"] -->|機密情報を含む| commit["Git<br/>コミット"]
  commit -->|公開リポジトリへ| public["GitHub<br/>パブリックリポジトリ"]
  commit -->|プライベートでも| private["GitHub<br/>プライベートリポジトリ"]

  public -->|学習データとして使用| copilot_train["Copilot<br/>学習プロセス"]
  private -->|設定により除外可能| copilot_train

  copilot_train -->|他の開発者へ提案| leak["機密情報<br/>漏洩リスク"]

  style code fill:#fff4e6
  style leak fill:#ffe6e6
  style copilot_train fill:#fff0f0

図で理解できる要点:

  • パブリックリポジトリのコードは確実に学習データに含まれる
  • プライベートリポジトリも設定次第で学習対象になりうる
  • 一度学習されると、他の開発者への提案として出力される可能性がある

実際に発生した問題事例

2023 年には、ある企業で GitHub Copilot が AWS のアクセスキーを提案として表示し、そのキーが実際に有効なものだったという事例が報告されました。

また、別のケースでは、データベースの接続文字列が提案に含まれており、内部的なサーバー情報が露出する事態も発生しています。これらは氷山の一角に過ぎないでしょう。

開発者個人では防ぎきれない理由

個々の開発者が注意を払っていても、以下のような理由から完全に防ぐことは困難です。

まず、コーディング中は機能実装に集中しており、機密情報のチェックまで意識が回らないことが多いですね。また、チーム開発では他のメンバーがコミットしたコードに機密情報が含まれている可能性もあります。

さらに、過去にコミットされた機密情報は、後から削除しても Git の履歴に残り続けてしまいます。個人の努力だけでは限界があるため、組織レベルでの対策が不可欠なのです。

解決策

多層防御アプローチによるセキュリティ対策

機密文字列の漏洩を防ぐには、複数の対策を組み合わせた多層防御アプローチが効果的です。一つの対策だけに頼るのではなく、それぞれの段階で異なる仕組みを導入することで、リスクを大幅に軽減できます。

以下の図は、セキュリティ対策の全体像を示しています。

mermaidflowchart TB
  subgraph prevention["予防層"]
    policy["組織ポリシー<br/>の策定"]
    education["開発者教育"]
    env["環境変数の<br/>徹底使用"]
  end

  subgraph detection["検知層"]
    precommit["Pre-commit<br/>フック"]
    scanning["シークレット<br/>スキャニング"]
    review["コードレビュー"]
  end

  subgraph exclusion["除外層"]
    gitignore[".gitignore<br/>設定"]
    copilot_exclude["Copilot Content<br/>Exclusion"]
  end

  prevention --> detection
  detection --> exclusion

  style prevention fill:#e6f3ff
  style detection fill:#fff4e6
  style exclusion fill:#e6ffe6

図で理解できる要点:

  • 予防層:そもそも機密情報をコードに書かない文化を作る
  • 検知層:万が一書いてしまった場合も、コミット前に検知する
  • 除外層:Copilot の学習対象から機密ファイルを除外する

ポリシー設定:組織レベルでの対策

GitHub Copilot の組織設定

GitHub Organization または Enterprise を使用している場合、管理者は Copilot の動作を組織レベルで制御できます。

まず、Settings から Copilot の設定画面にアクセスしましょう。

typescript// 組織設定で制御できる主要項目
interface CopilotOrgSettings {
  // パブリックコードの提案を許可するか
  allowPublicCodeSuggestions: boolean;

  // Copilot による学習を許可するか(プライベートリポジトリ)
  allowCopilotToLearnFromCode: boolean;

  // 組織外のユーザーとのコード共有を許可するか
  allowSharingCodeWithOtherOrgs: boolean;
}

特に重要なのは allowCopilotToLearnFromCode の設定です。これを false に設定することで、組織のプライベートリポジトリのコードが Copilot の学習データとして使用されることを防げます。

設定手順は以下の通りです。

bash# GitHub CLI を使用した組織設定の確認
gh api \
  -H "Accept: application/vnd.github+json" \
  /orgs/{org}/copilot/settings

# 出力例
# {
#   "allow_public_code_suggestions": true,
#   "allow_copilot_to_learn_from_code": false
# }

Content Exclusion の設定

GitHub Copilot Content Exclusion は、特定のファイルやディレクトリを Copilot の提案対象から除外する機能です。2024 年に正式リリースされ、機密情報を含むファイルを明示的に除外できるようになりました。

リポジトリのルートに .github​/​copilot-exclusions.json ファイルを作成します。

json{
  "version": "1.0",
  "exclusions": [
    {
      "path": "**/.env*",
      "reason": "環境変数ファイルには機密情報が含まれるため"
    },
    {
      "path": "**/config/secrets/**",
      "reason": "機密設定ファイルのディレクトリ"
    },
    {
      "path": "**/*credentials*.json",
      "reason": "認証情報を含むJSONファイル"
    },
    {
      "path": "**/keys/**",
      "reason": "暗号化キーや証明書のディレクトリ"
    }
  ]
}

この設定により、指定したパターンにマッチするファイルは Copilot が読み込まないようになります。パスにはグロブパターンを使用でき、柔軟な指定が可能ですね。

組織レベルで適用する場合は、Organization の設定から一括で適用できます。

typescript// TypeScript での設定管理例
interface ExclusionRule {
  path: string; // グロブパターン
  reason: string; // 除外理由(ドキュメント用)
}

const standardExclusions: ExclusionRule[] = [
  {
    path: '**/.env*',
    reason: '環境変数ファイル',
  },
  {
    path: '**/secrets/**',
    reason: '機密情報ディレクトリ',
  },
  {
    path: '**/*secret*.*',
    reason: '機密を示すファイル名',
  },
];

検知ルール:コミット前の自動チェック

Git フックによる機密情報検知

Pre-commit フックを使用すると、Git コミット前に自動的に機密情報をチェックできます。ここでは pre-commit フレームワークを使った実装を紹介しましょう。

まず、pre-commit をインストールします。

bash# Homebrew を使用する場合
brew install pre-commit

# pip を使用する場合
pip install pre-commit

次に、リポジトリのルートに .pre-commit-config.yaml ファイルを作成します。

yaml# Pre-commit の設定ファイル
repos:
  # detect-secrets を使用した機密情報検知
  - repo: https://github.com/Yelp/detect-secrets
    rev: v1.4.0
    hooks:
      - id: detect-secrets
        args: ['--baseline', '.secrets.baseline']
        exclude: package-lock.json

detect-secrets は、様々なパターンの機密情報を検知できる優れたツールです。初回実行時にベースラインファイルを作成しましょう。

bash# ベースラインファイルの作成
detect-secrets scan > .secrets.baseline

# Pre-commit フックのインストール
pre-commit install

これで、コミット時に自動的に機密情報がチェックされるようになります。

カスタム検知ルールの実装

より細かい制御が必要な場合は、カスタムスクリプトを作成できます。以下は Node.js での実装例です。

javascript// scripts/check-secrets.js
const fs = require('fs');
const path = require('path');

// 検知したい機密パターン
const secretPatterns = [
  {
    name: 'AWS Access Key',
    pattern: /AKIA[0-9A-Z]{16}/g,
    severity: 'HIGH',
  },
  {
    name: 'GitHub Token',
    pattern: /ghp_[a-zA-Z0-9]{36}/g,
    severity: 'HIGH',
  },
  {
    name: 'Generic API Key',
    pattern:
      /api[_-]?key['\"]?\s*[:=]\s*['\"]([a-zA-Z0-9_-]{20,})['\"]?/gi,
    severity: 'MEDIUM',
  },
];

パターンマッチングの実装部分です。

javascript// ファイルをスキャンする関数
function scanFile(filePath) {
  const content = fs.readFileSync(filePath, 'utf8');
  const findings = [];

  // 各パターンでチェック
  secretPatterns.forEach(({ name, pattern, severity }) => {
    const matches = content.matchAll(pattern);

    for (const match of matches) {
      findings.push({
        file: filePath,
        type: name,
        severity: severity,
        line: getLineNumber(content, match.index),
        preview: getContextPreview(content, match.index),
      });
    }
  });

  return findings;
}

ヘルパー関数の実装です。

javascript// 行番号を取得
function getLineNumber(content, index) {
  return content.substring(0, index).split('\n').length;
}

// コンテキストプレビューを取得
function getContextPreview(
  content,
  index,
  contextLength = 50
) {
  const start = Math.max(0, index - contextLength);
  const end = Math.min(
    content.length,
    index + contextLength
  );
  return content.substring(start, end).replace(/\s+/g, ' ');
}

module.exports = { scanFile, secretPatterns };

このスクリプトを pre-commit フックから呼び出すように設定します。

yaml# .pre-commit-config.yaml に追加
repos:
  - repo: local
    hooks:
      - id: check-secrets
        name: Check for secrets
        entry: node scripts/check-secrets.js
        language: node
        files: \.(js|ts|json|yaml)$

GitHub Actions による継続的なスキャン

CI/CD パイプラインにもシークレットスキャンを組み込むことで、より強固な防御が可能です。

yaml# .github/workflows/secret-scan.yml
name: Secret Scanning

on:
  push:
    branches: ['**']
  pull_request:
    branches: [main, develop]

jobs:
  scan:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout code
        uses: actions/checkout@v4
        with:
          fetch-depth: 0 # 全履歴を取得

      - name: Run Gitleaks
        uses: gitleaks/gitleaks-action@v2
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

Gitleaks は、Git リポジトリ全体を高速にスキャンできる強力なツールです。設定ファイルで検知ルールをカスタマイズできますね。

toml# .gitleaks.toml
title = "機密情報検知設定"

[[rules]]
id = "aws-access-key"
description = "AWS Access Key ID"
regex = '''AKIA[0-9A-Z]{16}'''
tags = ["aws", "credentials"]

[[rules]]
id = "private-key"
description = "Private Key"
regex = '''-----BEGIN (RSA|DSA|EC|OPENSSH) PRIVATE KEY-----'''
tags = ["key", "credentials"]

[[rules]]
id = "jwt-token"
description = "JWT Token"
regex = '''eyJ[A-Za-z0-9-_=]+\.eyJ[A-Za-z0-9-_=]+\.[A-Za-z0-9-_.+/=]*'''
tags = ["jwt", "token"]

検出時のアクション設定も重要です。

yaml# GitHub Actions での検出時の処理
- name: Run Gitleaks
  uses: gitleaks/gitleaks-action@v2
  env:
    GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- name: Notify on detection
  if: failure()
  uses: slackapi/slack-github-action@v1
  with:
    payload: |
      {
        "text": "⚠️ 機密情報が検出されました",
        "blocks": [
          {
            "type": "section",
            "text": {
              "type": "mrkdwn",
              "text": "リポジトリ: ${{ github.repository }}\nブランチ: ${{ github.ref }}"
            }
          }
        ]
      }
  env:
    SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }}

具体例

実践シナリオ:Next.js プロジェクトでの完全な設定

実際の開発プロジェクトで、これまでの対策をどのように組み合わせるか見ていきましょう。Next.js を使った Web アプリケーション開発を例に、ステップバイステップで設定していきます。

以下の図は、検知ルール適用のフローを示しています。

mermaidflowchart TB
  start["コード記述"] --> local_check["ローカルチェック<br/>(Pre-commit)"]
  local_check -->|検出| alert1["警告表示<br/>コミット中止"]
  local_check -->|OK| commit["Git Commit"]

  commit --> push["Git Push"]
  push --> ci_check["CI/CDチェック<br/>(GitHub Actions)"]

  ci_check -->|検出| alert2["PR ブロック<br/>通知送信"]
  ci_check -->|OK| merge["マージ可能"]

  alert1 --> fix["機密情報を<br/>環境変数化"]
  alert2 --> fix
  fix --> start

  style alert1 fill:#ffe6e6
  style alert2 fill:#ffe6e6
  style merge fill:#e6ffe6

図で理解できる要点:

  • ローカルとリモートの二段階でチェックすることで、漏洩リスクを最小化
  • 検出時は即座に警告し、修正を促す
  • 環境変数化することで、機密情報をコードから分離

ステップ 1:プロジェクトの初期設定

まず、プロジェクトに必要な開発依存パッケージをインストールします。

bash# プロジェクトディレクトリに移動
cd your-nextjs-project

# 必要なパッケージをインストール
yarn add -D @types/node dotenv-cli
yarn add -D husky lint-staged

次に、環境変数管理のテンプレートを作成しましょう。

bash# .env.example ファイルの作成
# (実際の値は含めず、変数名のみを記載)

.env.example ファイルの内容です。

bash# .env.example
# データベース接続情報
DATABASE_URL=postgresql://user:password@localhost:5432/dbname

# 外部 API キー
NEXT_PUBLIC_GOOGLE_MAPS_API_KEY=your_api_key_here
STRIPE_SECRET_KEY=sk_test_xxxxx

# AWS 認証情報
AWS_ACCESS_KEY_ID=your_access_key
AWS_SECRET_ACCESS_KEY=your_secret_key
AWS_REGION=ap-northeast-1

# JWT シークレット
JWT_SECRET=your_jwt_secret_here

実際の .env ファイルは .gitignore に追加し、絶対にコミットしないようにします。

bash# .gitignore に追加する内容
.env
.env.local
.env.*.local
.env.development.local
.env.test.local
.env.production.local

# その他の機密ファイル
secrets/
*.key
*.pem
credentials.json

ステップ 2:環境変数の安全な使用方法

Next.js で環境変数を使用する際の実装例です。まず、型定義を作成して TypeScript の恩恵を受けられるようにしましょう。

typescript// types/env.d.ts
declare namespace NodeJS {
  interface ProcessEnv {
    // データベース
    DATABASE_URL: string;

    // API キー(クライアント側で使用可能)
    NEXT_PUBLIC_GOOGLE_MAPS_API_KEY: string;

    // サーバーサイドのみで使用
    STRIPE_SECRET_KEY: string;
    AWS_ACCESS_KEY_ID: string;
    AWS_SECRET_ACCESS_KEY: string;
    AWS_REGION: string;
    JWT_SECRET: string;
  }
}

環境変数を検証するユーティリティ関数を作成します。

typescript// lib/env.ts
// 環境変数の存在チェックと型安全なアクセス
export function getEnv(
  key: keyof NodeJS.ProcessEnv
): string {
  const value = process.env[key];

  if (!value) {
    throw new Error(
      `環境変数 ${key} が設定されていません。` +
        `.env ファイルを確認してください。`
    );
  }

  return value;
}

// 使用例
export const config = {
  database: {
    url: getEnv('DATABASE_URL'),
  },
  stripe: {
    secretKey: getEnv('STRIPE_SECRET_KEY'),
  },
  aws: {
    accessKeyId: getEnv('AWS_ACCESS_KEY_ID'),
    secretAccessKey: getEnv('AWS_SECRET_ACCESS_KEY'),
    region: getEnv('AWS_REGION'),
  },
} as const;

API ルートでの安全な使用方法です。

typescript// pages/api/payment.ts
import type { NextApiRequest, NextApiResponse } from 'next';
import { config } from '@/lib/env';

// Stripe SDK の初期化(環境変数を使用)
import Stripe from 'stripe';
const stripe = new Stripe(config.stripe.secretKey, {
  apiVersion: '2023-10-16',
});

export default async function handler(
  req: NextApiRequest,
  res: NextApiResponse
) {
  // API キーは環境変数から取得され、コードには直接書かれていない
  const paymentIntent = await stripe.paymentIntents.create({
    amount: 1000,
    currency: 'jpy',
  });

  res.status(200).json(paymentIntent);
}

ステップ 3:Pre-commit フックの設定

Husky と lint-staged を使って、コミット前の自動チェックを設定します。

bash# Husky の初期化
yarn husky install

# Pre-commit フックの作成
yarn husky add .husky/pre-commit "yarn lint-staged"

package.json に lint-staged の設定を追加します。

json{
  "scripts": {
    "prepare": "husky install",
    "check:secrets": "node scripts/check-secrets.js"
  },
  "lint-staged": {
    "*.{js,jsx,ts,tsx}": [
      "yarn check:secrets",
      "eslint --fix"
    ],
    "*.{json,yaml,yml}": ["yarn check:secrets"]
  }
}

先ほど紹介した機密情報チェックスクリプトを拡張します。

javascript// scripts/check-secrets.js
#!/usr/bin/env node

const fs = require('fs');
const path = require('path');

// 検知パターンの定義
const secretPatterns = [
  {
    name: 'AWS Access Key',
    pattern: /AKIA[0-9A-Z]{16}/g,
    severity: 'HIGH',
    errorCode: 'SEC-001'
  },
  {
    name: 'AWS Secret Key',
    pattern: /aws_secret_access_key\s*=\s*['\"]?([A-Za-z0-9/+=]{40})['\"]?/gi,
    severity: 'HIGH',
    errorCode: 'SEC-002'
  },
  {
    name: 'Stripe Secret Key',
    pattern: /sk_(live|test)_[0-9a-zA-Z]{24,}/g,
    severity: 'HIGH',
    errorCode: 'SEC-003'
  },
  {
    name: 'Generic Password',
    pattern: /password\s*[:=]\s*['\"]([^'\"]{8,})['\"](?!.*process\.env)/gi,
    severity: 'MEDIUM',
    errorCode: 'SEC-004'
  }
];

スキャン実行部分の実装です。

javascript// ファイルをスキャンして結果を返す
function scanFiles(filePaths) {
  let hasSecrets = false;
  const findings = [];

  filePaths.forEach((filePath) => {
    if (!fs.existsSync(filePath)) return;

    const content = fs.readFileSync(filePath, 'utf8');
    const lines = content.split('\n');

    secretPatterns.forEach(
      ({ name, pattern, severity, errorCode }) => {
        let match;
        while ((match = pattern.exec(content)) !== null) {
          const lineNum = content
            .substring(0, match.index)
            .split('\n').length;

          findings.push({
            errorCode,
            file: filePath,
            line: lineNum,
            type: name,
            severity,
            context: lines[lineNum - 1]?.trim(),
          });

          hasSecrets = true;
        }

        // グローバルフラグをリセット
        pattern.lastIndex = 0;
      }
    );
  });

  return { hasSecrets, findings };
}

エラー表示と終了処理です。

javascript// メイン処理
const args = process.argv.slice(2);
if (args.length === 0) {
  console.error('Error: ファイルパスを指定してください');
  process.exit(1);
}

const { hasSecrets, findings } = scanFiles(args);

if (hasSecrets) {
  console.error('\n❌ 機密情報が検出されました:\n');

  findings.forEach(
    ({
      errorCode,
      file,
      line,
      type,
      severity,
      context,
    }) => {
      console.error(`[${errorCode}] ${severity}: ${type}`);
      console.error(`  ファイル: ${file}:${line}`);
      console.error(`  内容: ${context}`);
      console.error('');
    }
  );

  console.error('💡 解決方法:');
  console.error('  1. 機密情報を .env ファイルに移動');
  console.error('  2. process.env.VARIABLE_NAME で参照');
  console.error(
    '  3. .env ファイルが .gitignore に含まれていることを確認\n'
  );

  process.exit(1);
}

console.log('✅ 機密情報は検出されませんでした');
process.exit(0);

ステップ 4:GitHub Actions の CI/CD 設定

最後に、GitHub Actions でのチェックを設定します。

yaml# .github/workflows/security-check.yml
name: Security Check

on:
  push:
    branches: ['**']
  pull_request:
    types: [opened, synchronize, reopened]

jobs:
  secret-scan:
    name: Scan for Secrets
    runs-on: ubuntu-latest

    steps:
      - name: Checkout Repository
        uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Run Gitleaks
        uses: gitleaks/gitleaks-action@v2
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          GITLEAKS_LICENSE: ${{ secrets.GITLEAKS_LICENSE }}

カスタムスクリプトによるチェックも追加します。

yaml- name: Setup Node.js
  uses: actions/setup-node@v4
  with:
    node-version: '20'
    cache: 'yarn'

- name: Install Dependencies
  run: yarn install --frozen-lockfile

- name: Run Custom Secret Check
  run: |
    find . -type f \
      -name "*.ts" -o -name "*.js" -o -name "*.json" \
      | grep -v node_modules \
      | xargs node scripts/check-secrets.js

チェック失敗時の通知設定です。

yaml- name: Post Comment on PR
  if: failure() && github.event_name == 'pull_request'
  uses: actions/github-script@v7
  with:
    script: |
      github.rest.issues.createComment({
        issue_number: context.issue.number,
        owner: context.repo.owner,
        repo: context.repo.repo,
        body: '⚠️ **機密情報が検出されました**\n\n' +
              'コミットに機密情報が含まれている可能性があります。\n' +
              '以下を確認してください:\n\n' +
              '- [ ] API キーやパスワードを環境変数に移動\n' +
              '- [ ] .env ファイルが .gitignore に含まれているか確認\n' +
              '- [ ] 過去のコミット履歴に機密情報が含まれていないか確認\n\n' +
              '詳細は Actions のログを確認してください。'
      })

ステップ 5:チーム全体での運用ルール

技術的な対策だけでなく、チーム全体で運用ルールを共有することも重要です。SECURITY.md を作成して、セキュリティガイドラインを明文化しましょう。

markdown<!-- SECURITY.md -->

# セキュリティガイドライン

# 機密情報の取り扱い

## 禁止事項

以下の情報は**絶対に**ソースコードに直接記載しないでください:

- API キー、トークン
- データベースのパスワード
- 暗号化キーやシークレット
- AWS アクセスキーなどのクレデンシャル
- プライベート証明書やキーファイル

## 推奨事項

1. **環境変数を使用する**

   - すべての機密情報は `.env` ファイルで管理
   - `.env.example` でテンプレートを提供

2. **Pre-commit フックを有効化**

   ```bash
   yarn husky install
   ```

3. **定期的なスキャン**
   - CI/CD で自動スキャンが実行されます
   - 検出時は必ず修正してから再プッシュ

## エラー対応

### Error SEC-001: AWS Access Key detected

**発生条件**: AWS のアクセスキーがコード内に検出された

**解決方法**:

1. `.env` ファイルに移動

   ```bash
   AWS_ACCESS_KEY_ID=your_key_here
   ```

2. コードで環境変数を参照

   ```typescript
   const accessKeyId = process.env.AWS_ACCESS_KEY_ID;
   ```

3. 検出されたキーをローテーション(無効化して新規作成)

まとめ

GitHub Copilot は開発生産性を大きく向上させる素晴らしいツールですが、機密情報の取り扱いには細心の注意が必要です。

本記事では、機密文字列の漏洩を防ぐための包括的な対策をご紹介しました。重要なポイントを振り返りましょう。

ポリシー設定の重要性

組織レベルでの設定により、個々の開発者に依存しない仕組みを構築できます。GitHub Copilot の学習設定を制御し、Content Exclusion で機密ファイルを除外することで、第一の防衛線を張ることができますね。

検知ルールの多層防御

Pre-commit フックによるローカルチェック、GitHub Actions による CI/CD チェックを組み合わせることで、万が一の見落としも防げるでしょう。カスタムスクリプトで組織特有のパターンを検知できる柔軟性も持たせられます。

環境変数の徹底使用

機密情報はコードから完全に分離し、環境変数として管理する文化を定着させることが根本的な解決策です。.env.example でテンプレートを提供し、チーム全体で統一されたアプローチを取りましょう。

これらの対策を組み合わせることで、AI の恩恵を享受しながらも、セキュリティを犠牲にすることなく開発を進められます。

最も重要なのは、技術的な対策だけでなく、チーム全体でセキュリティ意識を高めることです。定期的な教育や、インシデント発生時の迅速な対応フローを整備することで、より強固なセキュリティ体制を構築できるでしょう。

今日から実践できる対策ばかりですので、ぜひ自分のプロジェクトに取り入れてみてください。安全で生産的な開発環境を一緒に作っていきましょう。

関連リンク

;