Context Engineering / Agentic Coding / Secure Development
事前準備の確認(インストールは事前作業として完了済み)2分
git clone し、starter/ フォルダを VSCode で開いているpython app.py でサーバーが起動し http://localhost:5000 にアクセスできるターミナル(OS のターミナルでも VSCode のターミナルでも可)で clone します。
git clone https://github.com/nozoyoshida/gca-handson.git
gca-handson/starter/ フォルダを開いてください(gca-handson/ ルートではありません)。GEMINI.md は VSCode で開いているフォルダ(ワークスペースルート)から読み込まれます。開くフォルダを間違えると、Ch.2 以降で Gemini がプロジェクトの規約を読み込めず、演習の効果が得られません。
以降のコマンドは VSCode の統合ターミナル(Ctrl+`)で実行してください。starter/ を開いているので、ターミナルは最初から starter/ にいます。
# 1. Python 仮想環境を作成・有効化 python3 -m venv .venv source .venv/bin/activate # Windows: .venv\Scripts\activate # 2. 依存パッケージをインストール pip install -r requirements.txt
# 0. uv のインストール(未インストールの場合) curl -LsSf https://astral.sh/uv/install.sh | sh # macOS/Linux # Windows: powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex" # 1. uv で仮想環境作成 + 依存インストール uv venv uv pip install -r requirements.txt # 2. 仮想環境を有効化 source .venv/bin/activate # Windows: .venv\Scripts\activate
python app.py
# http://localhost:5000 にアクセスできればOK
Flask + SQLite で構築したシンプルなチケット管理 REST API です。
| Method | Path | 説明 |
|---|---|---|
GET | /tickets | チケット一覧取得(status, priority でフィルタ可) |
GET | /tickets/<id> | チケット詳細取得 |
POST | /tickets | チケット作成 |
PUT | /tickets/<id> | チケット更新 |
PATCH | /tickets/<id>/status | ステータス変更 |
GET | /tickets/search?q= | チケット検索 |
python app.py で Address already in use エラーが出る場合は、代わりに flask run -p 5001 で起動してください。以降のガイドで localhost:5000 と記載されている箇所は localhost:5001 に読み替えてください。
コード補完・チャットパネル・インラインチャットの3つのインタラクション 10分
app.py をエディタで開き、ファイル末尾(if __name__ の直前)に移動します。
@app.route('/health') def
jsonify の使い方、レスポンス形式など)に合わせた提案になっていることを確認してみてください。
@ ファイル参照
4分
@ を入力すると、ファイル一覧のドロップダウンが表示されます。app.py を選択してください。
@ を入力すると、ファイルだけでなくフォルダも指定できます。複数のファイルを @ で指定することで、Gemini に適切なコンテキストを与えることができます。
app.py の get_tickets() 関数内にカーソルを置きます。
get_tickets() を直接編集する差分を提案します。提案内容を確認したら、Decline してください。
GEMINI.md でプロジェクトの規約を AI に伝え、出力品質を劇的に変える 15分
現在のコードはたまたま snake_case で書かれていますが、明示的なルールとして定義されていません。GEMINI.md がない状態では、Gemini が ticketId (camelCase) と ticket_id (snake_case) を混在させるコードを生成する可能性があります。
バラバラで不十分です:
get_ticket() | 'Ticket not found' と英語 |
create_ticket() | エラーハンドリングが一切ない — 空の title でも 201 が返る |
search_tickets() | エラーハンドリングが一切ない |
update_status() | 任意の文字列("hacked" 等)をステータスとして受け付ける |
また、request.get_json() が None を返すケース(Content-Type ヘッダーなし等)への対処もなく、AttributeError がそのまま 500 エラーとして露出します。
安全なクエリと危険なクエリが混在しています:
| 関数 | 方式 | 安全性 |
|---|---|---|
create_ticket() | ? プレースホルダー | 安全 |
get_ticket() | ? プレースホルダー | 安全 |
get_tickets() フィルタ | f-string f"...'{status}'" | SQLi 脆弱性 |
search_tickets() | f-string f"...'%{q}%'" | SQLi 脆弱性 |
統一されたルールがないため、同じ開発者(や AI)が書いたコード内でも安全性にばらつきが生じています。
全14関数のうち、docstring がある関数は 0 個です。関数の目的、引数、戻り値、どのステータス遷移が許可されるか等が一切文書化されていません。
GEMINI.md で規約を明示することで、AI の出力を一貫してコントロールできるようになります。
GEMINI.md(空ファイルが用意されています)を開き、以下の内容をコピーしてください:
# お問い合わせ管理 API ## プロジェクト概要 Flask と SQLite を使用したチケット管理 REST API です。 顧客からのお問い合わせをチケットとして管理し、 ステータス管理・検索・集計機能を提供します。 ## コーディング規約 ### 命名規則 - 変数名・関数名: snake_case - 定数: UPPER_SNAKE_CASE - HTTPステータスコード: 定数で定義せず数値リテラルを使用 ### ドキュメント - 全ての関数に Google Style の docstring を記述すること - 複雑なロジックには日本語でコメントを付けること - API エンドポイントの docstring には HTTP メソッドとパスを含めること ### エラーハンドリング - API レスポンスは必ず JSON 形式で返すこと - エラー時は {"error": "説明"} の形式で適切な HTTP ステータスコードを返す - 400: バリデーションエラー、404: リソース未検出、500: サーバーエラー ### データベース - SQL クエリには必ずパラメータ化クエリ(? プレースホルダー)を使用 - f-string や % 演算子で SQL を組み立てることは禁止 - データベース接続は使用後に必ず close すること ### バリデーション - 全てのユーザー入力に対してバリデーションを実施すること - 文字列フィールドには最大長制限を設けること - ステータスは許可された値のみ受け付けること(enum パターン) ### セキュリティ - 秘密鍵やパスワードをハードコードしてはならない - 本番環境では debug モードを無効にすること
~/.gemini/GEMINI.md(グローバル)、プロジェクトルートの GEMINI.md、サブディレクトリの GEMINI.md の順に読み込まれます。会社全体の規約をグローバルに、プロジェクト固有のルールをプロジェクトルートに置くことで、チーム全体で一貫した AI 出力を得られます。
GEMINI.md があるだけで出力品質が劇的に変わります。GEMINI.md は、プロジェクトに追加できる最もレバレッジの高いファイルです。一度書けば、チームメンバー全員の AI インタラクションが改善されます。
.gemini/styleguide.md(空ファイルが用意されています)を開き、以下の内容をコピーしてください:
.gemini/ フォルダが見えない場合は、ターミナルから直接開いてください:code .gemini/styleguide.md。または、エクスプローラー上部の ... メニュー →「Show Hidden Files」で表示できます。
# コードレビュー スタイルガイド ## 必須チェック項目 ### セキュリティ - SQL クエリにユーザー入力を直接埋め込んでいないか - 入力バリデーションが実装されているか - 秘密情報がハードコードされていないか ### コード品質 - 関数に docstring が記述されているか - エラーハンドリングが適切か - 変数名が snake_case で命名されているか ### Flask 固有 - レスポンスが jsonify() で返されているか - HTTP ステータスコードが適切か - データベース接続が適切にクローズされているか
flowchart TD
A["Developer
git push"] --> B["Pull Request 作成"]
B --> C{"Gemini Code Review
自動起動"}
C --> D["styleguide.md
ルールに基づく検査"]
C --> E["コード差分分析
バグ・品質の指摘"]
C --> F["セキュリティチェック
SQLi, CSRF 等の検出"]
D --> G["PR にレビューコメント投稿"]
E --> G
F --> G
style A fill:#e8f0fe,stroke:#4285f4,color:#202124
style B fill:#e8f0fe,stroke:#4285f4,color:#202124
style C fill:#fff3e0,stroke:#f9ab00,color:#202124
style D fill:#e6f4ea,stroke:#34a853,color:#202124
style E fill:#e6f4ea,stroke:#34a853,color:#202124
style F fill:#fce8e6,stroke:#ea4335,color:#202124
style G fill:#e8f0fe,stroke:#1a73e8,color:#202124
.gemini/styleguide.md を配置styleguide.md がない場合でも一般的なベストプラクティスに基づいてレビューされますが、プロジェクト固有のルールを定義することでレビュー精度が大幅に向上します。
| ファイル | 用途 | 読み込みタイミング |
|---|---|---|
GEMINI.md | プロジェクトの規約・コンテキスト | 全てのプロンプトで自動 |
.gemini/styleguide.md | コードレビュールール | PR レビュー時 |
@ ファイル参照 | 特定ファイルのコンテキスト追加 | プロンプトで明示指定時 |
GEMINI.md を追加してみてください。10分の投資で、チーム全体の AI 出力品質が向上します。
Agent モードで複数ファイルにまたがる機能を一気に実装する 18分
completed/app.py を参照してください。
completed/app.py を開いて完成形のコードを確認しておくと、Agent の出力と比較しやすくなります。
responses テーブルに is_internal カラムが含まれているかticket_id に外部キー制約が設定されているか{"error": "..."} 形式か# ターミナルで実行
python app.py
# 対応履歴を追加 curl -X POST http://localhost:5000/tickets/1/responses \ -H "Content-Type: application/json" \ -d '{"responder": "鈴木", "message": "パスワードリセットのリンクを送信しました", "is_internal": false}' # 内部メモを追加 curl -X POST http://localhost:5000/tickets/1/responses \ -H "Content-Type: application/json" \ -d '{"responder": "山田", "message": "原因調査中。認証基盤側の障害の可能性あり", "is_internal": true}'
# 対応履歴を追加 curl -X POST http://localhost:5000/tickets/1/responses ` -H "Content-Type: application/json" ` -d "{\"responder\": \"鈴木\", \"message\": \"パスワードリセットのリンクを送信しました\", \"is_internal\": false}" # 内部メモを追加 curl -X POST http://localhost:5000/tickets/1/responses ` -H "Content-Type: application/json" ` -d "{\"responder\": \"山田\", \"message\": \"原因調査中。認証基盤側の障害の可能性あり\", \"is_internal\": true}"
脆弱性を検出し、修正し、ルールとして定着させる 13分
starter/app.py には、教育目的で以下の脆弱性が意図的に埋め込まれています。これらは本番コードでは絶対に使用してはなりません。
| 脆弱性 | 場所 | 内容 |
|---|---|---|
| SQLi | search_tickets() | f-string で SQL を組み立て |
| SQLi | get_tickets() フィルタ | status パラメータを直接 SQL に埋め込み |
| Validation | update_status() | 任意の文字列をステータスとして受け付ける |
| Config | app.run() | debug=True でデバッガー露出 |
| Secrets | app.secret_key | 秘密鍵がハードコード |
search_tickets() のコードが以下のように変わっていることを確認:
sql = f"SELECT * FROM tickets
WHERE title LIKE '%{q}%'"
db.execute(sql)
sql = "SELECT * FROM tickets
WHERE title LIKE ?"
db.execute(sql, (f'%{q}%',))
.gemini/styleguide.md を開き、以下のセキュリティルールを先頭に追加します:
## セキュリティ(最優先) ### SQL インジェクション防止 - f-string、% 演算子、.format() を SQL 文で絶対に使用しないこと - 必ずパラメータ化クエリ(? プレースホルダー)を使用すること ### 入力バリデーション - 全てのユーザー入力に対してバリデーションを実施すること - 文字列フィールドには最大長制限を設けること - HTML タグやスクリプトタグを除去またはエスケープすること - ステータス等の列挙値は許可リストで検証すること ### 設定 - 秘密鍵は環境変数から読み込むこと - 本番環境で debug=True を使用しないこと - エラーメッセージに内部情報(スタックトレース等)を含めないこと
styleguide.md に書いたルールは、GitHub 上で Pull Request が作成されるたびに自動的にチェックされます。
Gemini Code Assist のセキュリティ機能に加え、Google Cloud にはAI を安全に活用するためのエコシステムがあります。
| 機能 | 説明 |
|---|---|
| PR 自動レビュー | GitHub 連携時、PR 作成で自動的にセキュリティ観点のレビューを実施(SQLi, CSRF, IDOR, 不安全なデータ処理を検出) |
| styleguide.md | 自然言語で定義したルールに基づく自動コードレビュー |
| Snyk MCP 連携 | MCP サーバーとして Snyk を接続し、コード生成時にリアルタイムで脆弱なパターンを検出 |
/security:analyze コマンド — git diff を対象にハードコードされた秘密情報、インジェクション脆弱性、アクセス制御の問題を検出
flowchart TB
A1["Gemini CLI"] --> B1["Gemini Model\nコマンド生成"]
B1 --> C1["ホスト OS 上で\n直接実行"]
C1 --> D1["rm -rf /\n意図しない削除"]
C1 --> E1["機密ファイル読取\n~/.ssh/*, .env"]
C1 --> F1["外部送信\ncurl attacker.com"]
style A1 fill:#e8f0fe,stroke:#4285f4,color:#202124
style B1 fill:#e6f4ea,stroke:#34a853,color:#202124
style C1 fill:#fce8e6,stroke:#ea4335,color:#202124
style D1 fill:#fce8e6,stroke:#ea4335,color:#202124
style E1 fill:#fce8e6,stroke:#ea4335,color:#202124
style F1 fill:#fce8e6,stroke:#ea4335,color:#202124
flowchart TB
A2["Gemini CLI"] --> B2["Gemini Model\nコマンド生成"]
B2 --> SB
subgraph SB["gVisor Sandbox — 隔離されたユーザースペースカーネル"]
direction TB
G2["全 syscall を仲介"] --> D2["プロジェクト内\nファイル操作 ✓"]
G2 --> E2["許可されたコマンド\n実行 ✓"]
end
G2 --x|"ブロック"| F2["ホスト OS\nスコープ外アクセス拒否"]
style A2 fill:#e8f0fe,stroke:#4285f4,color:#202124
style B2 fill:#e6f4ea,stroke:#34a853,color:#202124
style SB fill:#fef7e0,stroke:#f9ab00,color:#202124
style G2 fill:#fef7e0,stroke:#f9ab00,color:#202124
style D2 fill:#e6f4ea,stroke:#34a853,color:#202124
style E2 fill:#e6f4ea,stroke:#34a853,color:#202124
style F2 fill:#fce8e6,stroke:#ea4335,color:#202124
flowchart LR
A["User Input"] --> B
subgraph B["Model Armor - 入力"]
direction TB
B1["Prompt Injection 検出"]
B2["PII マスキング"]
B3["不正 URL ブロック"]
end
B --> C["Gemini\nCode Assist"]
C --> D
subgraph D["Model Armor - 出力"]
direction TB
D1["有害コンテンツ検出"]
D2["機密データ除去"]
end
D --> E["Response"]
style A fill:#e8f0fe,stroke:#4285f4,color:#202124
style C fill:#e6f4ea,stroke:#34a853,color:#202124
style E fill:#e8f0fe,stroke:#4285f4,color:#202124
style B fill:#fce8e6,stroke:#ea4335,color:#202124
style D fill:#fce8e6,stroke:#ea4335,color:#202124
2分
| Chapter | 学んだこと | 持ち帰りアクション |
|---|---|---|
| Ch.1 基本操作 | Tab補完 / チャット / インラインチャットの使い分け | 日常のコーディングで使い始める |
| Ch.2 Context Engineering | GEMINI.md で AI の出力品質を制御 | 明日、自分のプロジェクトに GEMINI.md を追加 |
| Ch.3 Agentic Coding | Agent モードで複雑な機能を自律実装 | フィーチャーブランチで Agent モードを試す |
| Ch.4 セキュア開発 | 脆弱性検出 → 修正 → ルール化 | styleguide.md にセキュリティルールを追加 |
「エージェントが成功するか失敗するかを決める最大の要因は、モデルの性能ではなくコンテキストの質である。ほとんどのエージェントの失敗は、もはやモデルの失敗ではなくコンテキストの失敗だ」
GEMINI.md のような小さな追加が、精度と信頼性に大きな改善をもたらします。今日体験したように、同じプロンプトでもコンテキスト次第で出力品質が劇的に変わります。
Sources: Martin Fowler / Anthropic / Google Cloud
AI 生成コードは人間のコードと比較して 1.7 倍の問題を含み、45% にセキュリティ欠陥が存在するという調査結果があります。開発者の AI 提案の採用率は約 30% — 残り 70% は人間が却下しています。
AI は開発者を「コードを書く人」から「設計し、レビューし、判断する人」に変えます。ドメイン知識、アーキテクチャ設計力、セキュリティの目利きは、AI 時代にこそ重要になります。
Sources: CodeRabbit 2025 / Qodo / GitHub Blog
AI サイバー攻撃は前年比 72% 増加し、87% の組織が AI ベースの攻撃を経験しています。脆弱性が公開されてから悪用されるまでの期間は、2020年の 700 日超から 2025年にはわずか 5 日にまで短縮されました。
今日体験した styleguide.md によるセキュリティルールの自動チェック、AI によるコードレビューは「あれば便利」ではなく、攻撃速度に対抗するための必須の防御手段です。
Sources: Google Cloud / DeepStrike / Deep Instinct