mcpField
D
drupal-security

drupal-security

github.com/madsnorgaardセキュリティ49842 回インストール6 週間前に更新
リポジトリ

drupal-security について

drupal-security は、Drupal のコードを作成・レビューする開発者向けのセキュリティスキルです。SQL インジェクション、XSS、アクセス制御の不足、安全でないファイル処理などを指摘し、安全な実装例とコミット前のチェックリストを示します。

主な機能

  1. 01SQL インジェクションリスクの特定
  2. 02レンダリング出力での XSS 防止
  3. 03権限と CSRF 対策の確認
  4. 04ファイルアップロード検証のレビュー
  5. 05認証情報の露出や危険なコードの検出

活用シーン

  1. 01Drupal のフォームとコントローラーのレビュー
  2. 02ユーザー入力とデータベース処理の確認
  3. 03ルートとアクセス権限の監査
  4. 04コミット前のファイルアップロードコード確認

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/madsnorgaard/drupal-agent-resources --skill drupal-security

インストール後、Claude Code で/drupal-securityを入力して読み込まれたか確認します。

詳細

Drupal セキュリティエキスパート

コードを書いている段階で、脆弱性を事前に特定します。コードが完成してからではありません。

この機能が有効になる場面

  • フォーム、コントローラー、プラグインの作成または編集
  • ユーザー入力やクエリパラメーターの処理
  • データベースクエリの作成
  • ユーザーが提供したコンテンツのレンダリング
  • アクセス制御の実装

重要なセキュリティパターン

SQL インジェクションの防止

クエリにユーザー入力を絶対に連結しないでください:

// VULNERABLE - SQL injection
$query = "SELECT * FROM users WHERE name = '" . $name . "'";
$result = $connection->query($query);

// SAFE - parameterized query
$result = $connection->select('users', 'u')
  ->fields('u')
  ->condition('name', $name)
  ->execute();

// SAFE - placeholder
$result = $connection->query(
  'SELECT * FROM {users} WHERE name = :name',
  [':name' => $name]
);
XSS の防止

出力は必ずエスケープしてください。レンダーシステムを信頼してください:

// VULNERABLE - raw HTML output
return ['#markup' => $user_input];
return ['#markup' => '<div>' . $title . '</div>'];

// SAFE - plain text (auto-escaped)
return ['#plain_text' => $user_input];

// SAFE - use proper render elements
return [
  '#type' => 'html_tag',
  '#tag' => 'div',
  '#value' => $title,  // Escaped automatically
];

// SAFE - Twig auto-escapes
{{ variable }}  // Escaped
{{ variable|raw }}  // DANGEROUS - only for trusted HTML

管理者専用のコンテンツの場合:

use Drupal\Component\Utility\Xss;

// Filter but allow safe HTML tags
$safe = Xss::filterAdmin($user_html);
アクセス制御

必ず権限を確認してください:

// In routing.yml
my_module.admin:
  path: '/admin/my-module'
  requirements:
    _permission: 'administer my_module'  # Required!

// In code
if (!$this->currentUser->hasPermission('administer my_module')) {
  throw new AccessDeniedHttpException();
}

// Entity queries - check access!
$query = $this->entityTypeManager
  ->getStorage('node')
  ->getQuery()
  ->accessCheck(TRUE)  // CRITICAL - never FALSE unless intentional
  ->condition('type', 'article');
CSRF の防止

フォームには CSRF トークンが自動的に含まれます。カスタム AJAX の場合:

// Include token in AJAX requests
$build['#attached']['drupalSettings']['myModule']['token'] =
  \Drupal::csrfToken()->get('my_module_action');

// Validate in controller
if (!$this->csrfToken->validate($token, 'my_module_action')) {
  throw new AccessDeniedHttpException('Invalid token');
}
ファイルアップロードのセキュリティ
$validators = [
  'file_validate_extensions' => ['pdf doc docx'],  // Whitelist extensions
  'file_validate_size' => [25600000],  // 25MB limit
  'FileSecurity' => [],  // Drupal 10.2+ - blocks dangerous files
];

// NEVER trust file extension alone - check MIME type
$file_mime = $file->getMimeType();
$allowed_mimes = ['application/pdf', 'application/msword'];
if (!in_array($file_mime, $allowed_mimes)) {
  // Reject file
}
機密データ
// NEVER log sensitive data
$this->logger->info('User @user logged in', ['@user' => $username]);
// NOT: $this->logger->info('Login: ' . $username . ':' . $password);

// NEVER expose in error messages
throw new \Exception('Database error');  // Generic
// NOT: throw new \Exception('Query failed: ' . $query);

// Use environment variables for secrets
$api_key = getenv('MY_API_KEY');
// NOT: $api_key = 'hardcoded-secret-key';

注意すべき危険なパターン

以下のパターンを見つけたら、すぐに警告してください:

パターンリスク対策
SQL での文字列連結SQL インジェクションクエリビルダーを使用する
変数を含む #markupXSS#plain_text を使用する
accessCheck(FALSE)アクセス制御の回避accessCheck(TRUE) を使用する
ルートに _permission がない不正アクセス権限を追加する
Twig の {{ var|raw }}XSS|raw を削除する
パスワードやキーのハードコード認証情報の漏えい環境変数を使用する
eval() または exec()コードインジェクション完全に避ける
ユーザーデータへの unserialize()オブジェクトインジェクションJSON を使用する

セキュリティレビューの確認事項

コードをレビューする際は、必ず以下を確認してください:

  1. 「このデータはどこから来ていますか?」(ユーザー入力は信頼できません)
  2. 「このデータはどこへ渡されますか?」(出力はエスケープします)
  3. 「誰がアクセスすべきですか?」(権限が必要です)
  4. 「悪意のある入力が含まれていたらどうなりますか?」(検証・サニタイズします)

セキュリティのクイックチェックリスト

コードをコミットする前に確認してください:

  • すべてのユーザー入力が検証・サニタイズされている
  • すべての出力が適切にエスケープされている
  • ルートに権限要件が設定されている
  • エンティティクエリで accessCheck(TRUE) を使用している
  • 認証情報をハードコードしていない
  • ファイルアップロードで種類と拡張子の両方を検証している
  • フォームで Form API を使用している(CSRF 対策が自動で行われる)
  • 機密データをログに記録していない

リソース

コメント