关于 drupal-security
drupal-security 是面向 Drupal 开发与代码审查的安全技能。它指出 SQL 注入、XSS、访问控制缺失和文件处理不安全等常见风险,并提供安全写法与提交前检查清单。
主要功能
- 01识别 SQL 注入风险
- 02防止渲染输出中的 XSS
- 03检查权限与 CSRF 控制
- 04审查文件上传验证
- 05发现凭据暴露和不安全代码
适用场景
- 01审查 Drupal 表单和控制器
- 02检查用户输入与数据库处理
- 03审计路由和访问权限
- 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 注入 | 使用查询构建器 |
使用变量的 #markup | XSS | 使用 #plain_text |
accessCheck(FALSE) | 绕过访问控制 | 使用 accessCheck(TRUE) |
路由中缺少 _permission | 未经授权的访问 | 添加权限 |
Twig 中的 {{ var|raw }} | XSS | 移除 |raw |
| 硬编码的密码/密钥 | 凭据泄露 | 使用环境变量 |
eval() 或 exec() | 代码注入 | 完全避免使用 |
对用户数据调用 unserialize() | 对象注入 | 使用 JSON |
安全审查提示词
审查代码时,始终询问:
- “这些数据来自哪里?”(用户输入 = 不可信)
- “这些数据会去往哪里?”(输出 = 需要转义)
- “谁应该有权访问?”(需要权限)
- “如果其中包含恶意输入会怎样?”(验证/净化)
快速安全检查清单
提交任何代码之前:
- 验证/净化所有用户输入
- 正确转义所有输出
- 路由设有权限要求
- 实体查询使用
accessCheck(TRUE) - 没有硬编码的凭据
- 文件上传同时验证类型和扩展名
- 表单使用 Form API(自动防护 CSRF)
- 不记录敏感数据
资源
评论
支持 Markdown