From drupal-boost
Drupal security best practices, vulnerability prevention, permissions and access control, input sanitization, and the Access Policy API. Use when reviewing security, setting up permissions, or hardening a Drupal site.
npx claudepluginhub abderrahimghazali/drupal-boostThis skill is limited to using the following tools:
- `{{ variable }}` — safe, auto-escaped
Generates design tokens/docs from CSS/Tailwind/styled-components codebases, audits visual consistency across 10 dimensions, detects AI slop in UI.
Records polished WebM UI demo videos of web apps using Playwright with cursor overlay, natural pacing, and three-phase scripting. Activates for demo, walkthrough, screen recording, or tutorial requests.
Delivers idiomatic Kotlin patterns for null safety, immutability, sealed classes, coroutines, Flows, extensions, DSL builders, and Gradle DSL. Use when writing, reviewing, refactoring, or designing Kotlin code.
{{ variable }} — safe, auto-escaped{{ variable|raw }} — DANGEROUS, bypasses escaping. Only use for pre-sanitized markup{% set markup %}...{% endset %} — auto-escaped when rendered{{ variable|striptags }} — strips HTML tags$this->t() or new TranslatableMarkup() for user-facing stringsXss::filter() for user HTML that needs limited tagsHtml::escape() for plain text output#plain_text render element for untrusted textMarkup::create() with user input#markup with unsanitized content// SAFE: parameterized query
$result = $connection->select('users', 'u')
->fields('u', ['name'])
->condition('status', 1)
->execute();
// SAFE: placeholder in query()
$result = $connection->query('SELECT name FROM {users} WHERE uid = :uid', [':uid' => $uid]);
// DANGEROUS: string concatenation
$result = $connection->query("SELECT * FROM {users} WHERE name = '$name'"); // NEVER DO THIS
my_route:
path: '/admin/my-page'
requirements:
_permission: 'administer my module'
->accessCheck(TRUE) on entity queriesEntityAccessControlHandler for custom entitiesAccessResult::allowed(), ::forbidden(), ::neutral() with proper cacheability// REQUIRED in Drupal 10+
$nodes = \Drupal::entityTypeManager()
->getStorage('node')
->getQuery()
->accessCheck(TRUE) // MANDATORY
->condition('status', 1)
->execute();
# MODULE_NAME.permissions.yml
administer my module:
title: 'Administer My Module'
description: 'Full admin access to My Module settings.'
restrict access: true # Only for permissions that allow site takeover
view my content:
title: 'View My Content'
description: 'View custom content managed by My Module.'
X-CSRF-Token header/session/token endpointfile_validate_extensions()file_validate_size()private:// for sensitive files (not public://).php, .phtml, .phar extensions$_GET, $_POST, $_REQUEST directly$request->query->get('param')\Drupal::request()->get() without validation$_GET, $_POST, $_SERVER direct access|raw in Twig templatesdb_query() with string interpolationMarkup::create($user_input)accessCheck(TRUE) on entity queries_access: 'TRUE' on sensitive routesaccessCheck(TRUE)private:// schemeRead reference files for details:
reference/vulnerability-checklist.md for complete vulnerability patternsreference/access-control-patterns.md for access control implementation