Claude Skills セキュリティベストプラクティス
Skills が実際のコードを実行する場合、セキュリティは重要。システムを保護するためにこれらのプラクティスに従う。
重要なセキュリティ原則
1. 入力検証
常に入力を検証しサニタイズ:
python1def process_file(filepath): 2 # ファイルが存在することを検証 3 if not os.path.exists(filepath): 4 raise ValueError("ファイルが見つかりません") 5 6 # ファイルタイプを確認 7 allowed_extensions = ['.pdf', '.docx', '.txt'] 8 if not any(filepath.endswith(ext) for ext in allowed_extensions): 9 raise ValueError("無効なファイルタイプ") 10 11 # ファイルサイズを確認 12 if os.path.getsize(filepath) > 10 * 1024 * 1024: # 10MB 13 raise ValueError("ファイルが大きすぎます")1def process_file(filepath): 2 # ファイルが存在することを検証 3 if not os.path.exists(filepath): 4 raise ValueError("ファイルが見つかりません") 5 6 # ファイルタイプを確認 7 allowed_extensions = ['.pdf', '.docx', '.txt'] 8 if not any(filepath.endswith(ext) for ext in allowed_extensions): 9 raise ValueError("無効なファイルタイプ") 10 11 # ファイルサイズを確認 12 if os.path.getsize(filepath) > 10 * 1024 * 1024: # 10MB 13 raise ValueError("ファイルが大きすぎます")
2. サンドボックス化
信頼できないコードを分離環境で実行:
python1import subprocess 2 3def run_sandboxed(script_path): 4 result = subprocess.run( 5 ['docker', 'run', '--rm', '-v', f'{script_path}:/app', 'python:3.9', 'python', '/app/script.py'], 6 capture_output=True, 7 timeout=30 8 ) 9 return result.stdout1import subprocess 2 3def run_sandboxed(script_path): 4 result = subprocess.run( 5 ['docker', 'run', '--rm', '-v', f'{script_path}:/app', 'python:3.9', 'python', '/app/script.py'], 6 capture_output=True, 7 timeout=30 8 ) 9 return result.stdout
3. シークレット管理
機密データをハードコードしない:
python1import os 2 3# ✅ 良い: 環境変数を使用 4API_KEY = os.getenv('API_KEY') 5 6# ❌ 悪い: ハードコードされたシークレット 7# API_KEY = "sk-1234567890abcdef"1import os 2 3# ✅ 良い: 環境変数を使用 4API_KEY = os.getenv('API_KEY') 5 6# ❌ 悪い: ハードコードされたシークレット 7# API_KEY = "sk-1234567890abcdef"
4. 最小権限の原則
最小限の権限を要求:
markdown## 必要な権限 - ファイル読み取り: /data/input/ - ファイル書き込み: /data/output/ - ネットワーク: なし## 必要な権限 - ファイル読み取り: /data/input/ - ファイル書き込み: /data/output/ - ネットワーク: なし
5. コードレビュー
デプロイ前に Skills を監査:
bash# 危険なパターンを確認 grep -r "eval(" skill/ grep -r "exec(" skill/ grep -r "subprocess.call" skill/# 危険なパターンを確認 grep -r "eval(" skill/ grep -r "exec(" skill/ grep -r "subprocess.call" skill/
一般的な脆弱性
パス traversal
python1# ❌ 脆弱 2def read_file(filename): 3 return open(filename).read() 4# 攻撃: read_file("../../etc/passwd") 5 6# ✅ 安全 7import os 8def read_file(filename): 9 base_dir = "/safe/directory" 10 filepath = os.path.join(base_dir, filename) 11 if not filepath.startswith(base_dir): 12 raise ValueError("無効なパス") 13 return open(filepath).read()1# ❌ 脆弱 2def read_file(filename): 3 return open(filename).read() 4# 攻撃: read_file("../../etc/passwd") 5 6# ✅ 安全 7import os 8def read_file(filename): 9 base_dir = "/safe/directory" 10 filepath = os.path.join(base_dir, filename) 11 if not filepath.startswith(base_dir): 12 raise ValueError("無効なパス") 13 return open(filepath).read()
コマンドインジェクション
python# ❌ 脆弱 os.system(f"convert {filename} output.pdf") # ✅ 安全 subprocess.run(['convert', filename, 'output.pdf'], check=True)# ❌ 脆弱 os.system(f"convert {filename} output.pdf") # ✅ 安全 subprocess.run(['convert', filename, 'output.pdf'], check=True)
任意コード実行
python1# ❌ 危険 2eval(user_input) 3exec(user_code) 4 5# ✅ 安全な代替を使用 6import ast 7ast.literal_eval(user_input) # リテラルのみ1# ❌ 危険 2eval(user_input) 3exec(user_code) 4 5# ✅ 安全な代替を使用 6import ast 7ast.literal_eval(user_input) # リテラルのみ
セキュリティチェックリスト
- [ ] すべての入力を検証
- [ ] ファイルパスをサニタイズ
- [ ] コマンドはリスト引数で subprocess を使用
- [ ] ハードコードされたシークレットなし
- [ ] すべての操作にタイムアウト
- [ ] エラーメッセージは機密情報を漏洩しない
- [ ] 依存関係は信頼できるソースから
- [ ] 定期的なセキュリティ監査
監視
セキュリティ関連のイベントをログ:
pythonimport logging logging.info(f"スキル実行: {skill_name} by {user_id}") logging.warning(f"無効な入力試行: {input_data}") logging.error(f"セキュリティ違反: {error_details}")import logging logging.info(f"スキル実行: {skill_name} by {user_id}") logging.warning(f"無効な入力試行: {input_data}") logging.error(f"セキュリティ違反: {error_details}")
リソース
読書時間: 4分
著者: ClaudeSkills Team