Tech BlogAWSツール & 技術ブログ

AI時代のAWS機密情報管理——envファイルに書かない選択肢を改めて考える

はじめに

最近、AIエージェントが .env ファイルに書かれた機密情報を読み取ってしまう、というリスクがXやブログで頻繁に話題になっています。

Claude CodeやGitHub Copilot、CursorといったAI開発ツールが普及するほど、開発者の手元にあるAPIキーやDBパスワードがAIの文脈に載ってしまう 場面が増えていきます。もちろん各ツールは除外設定やマスキング機能を提供していますが、「設定を書いたから絶対安全」と言い切れるほど単純な話ではありません。

この記事では、AI時代にAWSの機密情報をどう扱うべきか、envファイルに書かずに済ませる選択肢 を改めて整理します。

なお本記事は、EC2・ECS・Lambdaといった アプリケーション実行環境での機密情報管理 に注力します。開発者個人のローカルでのAWS CLI認証設定(プロファイルやSSOのセットアップ手順そのもの)は、ここでは副次的な扱いに留め、あくまで「envに機密情報を置かない」という観点から触れる程度にします。CLIの認証設定の細かな手順を主題にした内容ではない、という点を最初に断っておきます。


AIがenvを読んでしまう問題

何が起きているのか

AIコーディングツールは、コンテキストとしてプロジェクト内のファイルを読み込みます。開発効率を上げるためには必要な挙動ですが、.envconfig/secrets.* のような機密情報を含むファイルまで読み込まれてしまう と、AIの応答やログ、場合によっては外部の推論サーバーに情報が流れる可能性があります。

実際に以下のような問題が報告されています。

  • AIが応答の中で、誤って環境変数の値をそのまま引用してしまう
  • プロジェクトディレクトリ全体をインデックス化する際に、機密ファイルまで対象になってしまう
  • 開発者が「全部読んで要約して」と指示した結果、AIが .env まで読み込んでしまう

CLAUDE.mdやsettings.jsonでは完全に防げない

Claude Codeでは CLAUDE.md やプロジェクトの .claude/settings.json に「envファイルは読むな」というルールを書いておけば、基本的には従ってくれます。

ですが、以下の理由で これが絶対安全とは言えません

  • AIエージェントはルールを100%守るとは限らない。判断を誤って読み込む可能性がある
  • そもそも ファイルを読み取れる権限がある時点でゼロリスクではない
  • 設定ファイル自体が破損・誤設定された場合、ガードが効かない
  • チームの誰かがローカル設定を無効化していると、組織全体のルールが意味をなさない

つまり、ルールで守るのは最後のセーフティネット として考え、そもそもローカルのenvファイルに機密情報を置かない設計に変えていく方が本質的です。


envに書かない選択肢——AWSで使える方法

「そもそもローカルにシークレットを置かない」という発想で、AWSの仕組みを使って機密情報を安全に扱う方法を紹介します。

1. AWS Systems Manager パラメータストア

もっとも手軽で、EC2・ECS・Lambdaなど幅広いサービスから利用できるのが Systems Manager パラメータストア(以下パラメータストア)です。

  • SecureString タイプを使えばKMSで暗号化された状態で値が保存される
  • IAMで「このサービスだけが読める」といった細かい権限制御ができる
  • 料金は 標準パラメータなら無料枠あり(4KBまで、10,000件まで)
# 値の登録(SecureString)
aws ssm put-parameter \
  --name "/my-app/db/password" \
  --value "your-secret" \
  --type SecureString

# 値の取得
aws ssm get-parameter \
  --name "/my-app/db/password" \
  --with-decryption \
  --query "Parameter.Value" \
  --output text

アプリケーション側は起動時にこのコマンド(相当のSDK呼び出し)で値を取得し、環境変数に注入します。ローカルにenvファイルを置く必要がなくなる のが最大のメリットです。

2. AWS Secrets Manager

パラメータストアよりも高機能なのが AWS Secrets Manager です。

このブログでの意思決定軸

どちらを選ぶかは、扱う値の性質で考えると整理しやすいです。判断軸は大きく2つあります。

  • 単なる設定値・環境変数か:エンドポイントURLや機能フラグ、まれにしか変わらないトークンのような「置いておくだけ」の値であれば、無料枠のあるパラメータストアで十分なことが多いです。
  • ローテーションが要るDB認証情報か:RDSのパスワードのように定期的な入れ替えが前提の値であれば、ローテーション機能を持つSecrets Managerが向いています。

以下の表は、この2つの軸で両者を比べたものです。

項目 パラメータストア Secrets Manager
暗号化 KMSで暗号化(SecureString) KMSで暗号化
自動ローテーション 未対応 対応(RDS等と連携)
料金 標準は無料枠あり 1シークレットあたり月0.40 USD程度
用途 設定値・環境変数 DB認証情報・APIキー

RDSのパスワードを定期的にローテーションしたい、といった用途なら Secrets Manager 、設定値程度のものなら パラメータストア と使い分けるのが一般的です。

3. CodePipeline + CodeBuildの環境変数

CI/CDに CodePipeline を使っているなら、CodeBuild内の環境変数 を利用することで、envファイルに値を直接書かずに済みます。

CodeBuildプロジェクトの環境変数は、以下のタイプを選べます。

  • Plaintext(推奨しない)
  • Parameter Store(パラメータストアの値を参照)
  • Secrets Manager(Secrets Managerの値を参照)

たとえば buildspec.yml で以下のように書くと、ビルド時にパラメータストアから値が注入されます。

version: 0.2

env:
  parameter-store:
    DB_PASSWORD: /my-app/db/password
    API_KEY: /my-app/api/key
  secrets-manager:
    STRIPE_KEY: my-app/stripe:SECRET_KEY

phases:
  build:
    commands:
      - echo "DB接続テスト中..."
      - ./scripts/deploy.sh

ECS(Fargate含む)へのデプロイの場合、CodeBuildで取得した値をそのままECSのタスク定義の環境変数として渡せるため、ほぼ追加作業なしで機密情報をenvに書かずに運用できます。

EC2の場合 は少し手順が必要です。CodeDeployやユーザーデータスクリプトで、インスタンス起動時にパラメータストアから値を取得してアプリケーションに渡す、といった実装が必要になります。

4. IAMロール(instance profile / task role)

EC2・ECS・Lambdaから使う場合、IAMロール を割り当てることで アクセスキーをコードに書く必要すら無くなります

  • EC2: instance profile経由でメタデータサービスから一時認証情報を取得
  • ECS: task roleで同様に一時認証情報が取得できる
  • Lambda: 実行ロールが自動的にセットされる

この仕組みを使うと、AWS SDKは自動的にこの一時認証情報でAPIを呼び出すため、アプリケーション側のコードにAWSの認証情報を持つ必要がありません

5. その他の選択肢

場面に応じて以下も検討できます。

  • HashiCorp Vault: マルチクラウドや、より高度なアクセス制御が必要な場合
  • SOPS + KMS: gitリポジトリに暗号化した状態でファイルを置きたい場合
  • External Secrets Operator: Kubernetes環境でパラメータストアやSecrets ManagerをSecretリソースとして扱いたい場合
  • GitHub Actions Secrets / GitLab CI Variables: CI/CDの範囲で閉じるなら、各プラットフォームのシークレット機能

使い分けの目安

実務で迷いがちなポイントを整理しておきます。

シーン 推奨する仕組み
開発者ローカル環境 IAM Identity Centerで一時認証、Parameter Storeから都度取得
EC2上のアプリ instance profile + Parameter Store
ECS/Fargate上のアプリ task role + Parameter Store or Secrets Manager
Lambda 実行ロール + Parameter Store(頻繁に呼ぶなら環境変数に展開)
CI/CD(CodePipeline) CodeBuildのenvでParameter StoreかSecrets Managerを参照
RDSのパスワード Secrets Managerでローテーション設定

このブログでの扱い方

このブログは現在、Next.jsの静的サイトを Cloudflare Pages でホスティングしています。デプロイは git push を契機にCloudflare PagesのGit連携が自動でビルド・公開する構成で、ローカルからAWSの認証情報を使ってデプロイする経路は持っていません。

もともとはS3 + CloudFront構成で、ローカルの deploy.sh(AWS SSOログイン → ビルド → S3同期 → CloudFront無効化)を手動実行してデプロイしていました。その移行の詳細は別記事 個人技術ブログを S3+CloudFront から Cloudflare Pages に移行した記録 に書いていますが、Cloudflare Pagesへ移った結果、この deploy.sh 自体が不要になり、ローカルからAWS認証情報を使うデプロイ経路そのものが無くなりました。デプロイのたびにローカルでAWSの一時認証情報を取得する必要もなくなった、ということです。

一方で、ローカル開発でAWSを触る場面(パラメータストアの値を確認する、検証用にリソースを操作するなど)は引き続きあり得ます。その場合も方針は変えておらず、以下を守っています。

  • AWSを触るときはIAM Identity Centerの一時認証情報を使う
  • .env にはAWSの認証情報を一切書かない

Claude Codeに「このディレクトリ全部読んで」と指示しても、そもそも機密情報がどこにも無い 状態にしておくことが、AIとの安全な付き合い方の基本だと考えています。


まとめ——「envに書かない」を当たり前に

  • AIが .env を読むリスクは現実のものになっている
  • CLAUDE.mdやsettings.jsonのルールは 最後のセーフティネット 。それだけに頼らない
  • ファイルが存在して読める権限がある時点でゼロリスクではない
  • Parameter Store、Secrets Manager、CodeBuildの環境変数、IAMロール——AWSには既にenvに書かずに済ませる選択肢が揃っている
  • Parameter Storeは無料枠もあり、導入のハードルは低い

これらの手法は新しいものではなく、以前から存在していたベストプラクティス です。ただAI時代になり、「envファイルに平文で書く」ことのリスクが顕在化しました。

改めて、機密情報をどこに、どう残すか をあらゆる場面で考え直す時期が来ています。最後に、読者が手元のプロジェクトで動き出すための手引きをまとめておきます。

envに書いている値の棚卸しチェックリスト

まずは現状把握から。手元の .env を開いて、1つずつ次の観点で仕分けしてみてください。

  • その値は 機密情報 か(パスワード、APIキー、トークンなど)。単なる公開設定値なら優先度は下がる
  • AWS上の実行環境(EC2/ECS/Lambda)から使う値か。そうなら パラメータストアやSecrets Managerに移せる候補
  • 定期的な ローテーション が必要か(DB認証情報など)。必要なら移し先はSecrets Manager寄り
  • そもそも IAMロールで代替できないか(AWSアクセスキーなら、ロール付与でenvから消せる可能性が高い)
  • CI/CDの中だけで使う値か。そうなら CodeBuildの環境変数参照 で閉じられないか

Parameter Store導入の3ステップ

設定値をパラメータストアに移す場合、一般的には次の3ステップで進められます(各APIの仕様に基づく一般手順です)。

  1. 登録aws ssm put-parameterSecureString タイプとして値を登録する(本記事のコマンド例を参照)
  2. アプリ側実装:起動時にSDK(または aws ssm get-parameter --with-decryption)で値を取得し、プロセスの環境変数に注入する。あわせて実行環境のIAMロールに該当パラメータの読み取り権限を付与する
  3. 検証:実際に値が復号して取得できること、権限を持たないロールからは取得できないこと(最小権限になっていること)を確認する

どこから始めるか(推奨)

すべてを一気に移そうとすると挫折しやすいので、私としては次の順をおすすめします。あくまで提案なので、自分の構成に合わせて取捨選択してください。

  1. まず IAMロールで消せるAWSアクセスキー から手を付ける。コード変更が少なく、効果が大きい
  2. 次に DB認証情報など機密性の高い値 をSecrets Manager(ローテーション不要ならパラメータストア)へ
  3. 最後に その他の設定値 をパラメータストアへ寄せ、.env を限りなく空に近づける

まずは手元のプロジェクトで「envに書いている値のうち、Parameter Storeに移せるものはないか」と棚卸しするところから始めてみてはいかがでしょうか。