セキュリティについて僕らは学ぶ必要がある。

目次アイコン目次
  • 😰 AIが書いたコードでも、責任は開発者にある
  • 🤖 AIに聞いてみた:コーディングで気をつけるべきセキュリティの観点
  • 🔍 1. 入力値の検証とサニタイゼーション
  • 🔐 2. 認証・認可の適切な実装
  • 🔑 3. 暗号化とハッシュ化
  • 📝 4. エラーハンドリングとログ
  • 📦 5. 依存関係の管理
  • 💭 ここから得られる考察
  • 🚀 今後の自分の動き
  • 📝まとめ

😰 AIが書いたコードでも、責任は開発者にある

最近、AIにコードを書いてもらう機会が増えました。Claude、ChatGPT、Gemini、GitHub Copilotなど、これらのツールは開発効率を大幅に向上させてくれます。

これらの生成されたコードの責任は誰が取るのでしょうか
答えは明確です。それは私たち開発者自身です。

AIが生成したコードに脆弱性が潜んでいた場合、それを見逃した開発者の責任になります。
開発者は楽しいところを奪われて、責任だけ負わされる悲しい立場となってしまいましたね(笑)

AI時代の中で、セキュリティの観点から以下のような課題が出てくることが予想されます:

  • 古いセキュリティプラクティスを参照して実装することがある
  • コンテキストを完全に理解できないため、不適切な実装をすることがある
  • 一見動作するが、セキュリティホールがあるコードを生成することがある

このような状況で、私たちはどのようにセキュリティを確保すればよいのでしょうか。

🤖 AIに聞いてみた:コーディングで気をつけるべきセキュリティの観点

実際にどのような観点でレビューすべきか、AIに質問してみました。

「コーディングにおいて、脆弱性を埋め込まないために気をつけるべき代表的な観点を教えてください」

🔍 1. 入力値の検証とサニタイゼーション

# ❌ 危険な例
def search_user(name)
  User.where("name = '#{name}'")
end

# ✅ 安全な例
def search_user(name)
  User.where(name: name)
end

理由:SQLインジェクションやXSSなど、多くの攻撃はユーザー入力を悪用します。Railsのようなフレームワークが提供する安全なメソッドを使用することが重要です。

🔐 2. 認証・認可の適切な実装

# ❌ 危険な例
def destroy
  post = Post.find(params[:id])
  post.destroy
  redirect_to posts_path
end

# ✅ 安全な例
def destroy
  post = current_user.posts.find(params[:id])
  post.destroy if can?(:destroy, post)
  redirect_to posts_path
end

理由:権限のないユーザーが他人のデータを操作できてしまうと、重大なセキュリティ問題となります。

🔑 3. 暗号化とハッシュ化

# ❌ 危険な例
class User < ApplicationRecord
  def set_password(password)
    self.password = password
    save
  end
end

# ✅ 安全な例  
class User < ApplicationRecord
  has_secure_password

  # またはbcryptを直接使用
  def set_password(password)
    self.password_digest = BCrypt::Password.create(password)
    save
  end
end

理由:パスワードやセンシティブな情報は絶対に平文で保存してはいけません。

📝 4. エラーハンドリングとログ

# ❌ 危険な例
def process_payment
  Payment.create!(params[:payment])
rescue => e
  render json: { error: e.message, backtrace: e.backtrace }
end

# ✅ 安全な例
def process_payment
  Payment.create!(payment_params)
rescue ActiveRecord::RecordInvalid => e
  Rails.logger.error "Payment processing failed: #{e.message}"
  render json: { error: "決済処理に失敗しました" }, status: :unprocessable_entity
end

private

def payment_params
  params.require(:payment).permit(:amount, :currency)
end

理由:詳細なエラー情報は攻撃者にシステムの内部構造のヒントを与えてしまいます。

📦 5. 依存関係の管理

# Gemfile
source 'https://rubygems.org'

gem 'rails', '~> 7.0.4'  # 脆弱性のないバージョンを使用
gem 'puma', '~> 6.0'     # 定期的にアップデート

group :development do
  gem 'bundler-audit'  # 脆弱性チェックツール
end

理由:古いライブラリには既知の脆弱性が含まれている可能性があります。

💭 ここから得られる考察

AIにセキュリティの観点を聞いてみて、いくつか大切な気づきがありました。

1. 基本的な内容だが、実践は意外と難しい

上記の内容は、多くの開発者が「知識として知っている」ことです。しかし、AIが生成したコードをレビューする際、これらすべてを漏れなくチェックできているでしょうか。

2. AIは必ずしもセキュアなコードを書いているわけではない

AIは依頼した要件を実現してくれるコードは書いてくれますが、要件として書いていないことを満たしてくれるかはブラックボックスです。
あなたはAIにコードを書いてもらうとき、セキュリティ要件をもれなく正しく書いていますか?書いていない場合、AIも考慮して書いていないかもしれないです。

3. 自分だけが気を付けていればいいわけではない

自分が常にセキュリティ観点を意識していても、チームとして意識していかねば、どこかで脆弱性が紛れ込んでしまう可能性が高そうです。

🚀 今後の自分の動き

この気づきを踏まえて、以下のアクションを実践していこうと思います。

1. セキュリティチェックリストの作成

AIが生成したコードをレビューする際のチェックリストを作成します:

## AIコードレビューチェックリスト
- [ ] 入力値はすべて検証されているか
- [ ] SQLクエリはパラメータ化されているか
- [ ] 認証・認可は適切か
- [ ] センシティブ情報は暗号化されているか
- [ ] エラーメッセージは適切か
- [ ] 依存関係は最新か

2. 定期的なセキュリティ知識のアップデート

  • OWASP Top 10を定期的に確認
  • Rails Security Guideの読み返し
  • セキュリティ関連のカンファレンスや勉強会への参加

3. AIへのプロンプトの工夫

最初からセキュアなコードを生成してもらうために:

「〇〇の機能をRailsで実装してください。
セキュリティを考慮し、Strong Parameters、
SQLインジェクション対策、適切なエラーハンドリングを
含めてください。」

4. チームでの知識共有

個人の知識だけでなく、チーム全体でセキュリティ意識を高めることが重要です。定期的な勉強会やペアプログラミングを通じて、知識を共有していきます。

5.仕組で解決

そもそもセキュリティ要件をAIが必ず読み込むようにすることで、依頼者側が特にプロンプトとして指定せずにコードの重要な部分に集中することができます。
この方法が一番効果的かもしれないですね!

📝まとめ

AI時代において、開発者はより一層セキュリティに意識を向ける必要があります。AIは素晴らしいツールですが、最終的な責任は開発者にあるということを忘れてはいけません。

最も忘れてはならないのは、攻撃者もまた、AIという素晴らしいツールを用いて攻撃をしてくることです。これからの時代はセキュリティめっちゃ重要だと思っています。

今日からAIが生成したコードをレビューする際は、セキュリティの観点を意識してみてはいかがでしょうか。小さな気づきが、大きなインシデントを防ぐかもしれません。

一緒に、安全なコードを守っていきましょう 🛡️✨