Drupal 10/11 Contrib Security Pitfalls: A Hardening Checklist for Maintainers
Source: Dev.to
The Problem
Contrib maintainers usually do not get breached by exotic 0‑days. They get burned by small, repeatable mistakes under release pressure:
- Querying entities without explicit access intent.
- Exposing privileged routes with weak permission or CSRF coverage.
- Letting untrusted data hit output without strict escaping/sanitization.
- Shipping releases without a structured security review checkpoint.
On modern Drupal, these gaps are avoidable, but only if the checklist is explicit and enforced in CI/review.
The Solution
| Pitfall | Hardening action for D10/D11 | How to verify quickly |
|---|---|---|
| Implicit access behavior in entity queries | Always call ->accessCheck(TRUE) (or FALSE only with a documented reason) on entity queries. | rg "entityQuery\\(" and confirm paired accessCheck(...) in each path. |
| Weak route protection | Require route permissions and add CSRF protection for state‑changing routes. | Review *.routing.yml for _permission and CSRF requirements where applicable. |
| XSS through rendering shortcuts | Prefer render arrays/Twig auto‑escaping; do not output untrusted HTML directly. Avoid casual raw usage in templates. | Search for ` |
| SQL injection risk in custom queries | Use Drupal DB API placeholders and never concatenate untrusted input into SQL. | rg "->query\\(" and ensure placeholders are used. |
| Upload/extension abuse | Restrict allowed extensions/MIME, validate uploads, and enforce destination/access rules. | Review upload validators and file field constraints in form/entity handlers. |
| Missing release‑time security gate | Add a pre‑release checklist item for security advisories, access regressions, and deprecation impact. | Gate release tags on checklist completion in issue template/CI workflow. |
flowchart TD
A[Code change] --> B[Access review]
B --> C{Route or entity access changed?}
C -->|Yes| D[Add tests + explicit accessCheck]
C -->|No| E[Proceed]
D --> F[Output and input sanitization review]
E --> F
F --> G[Security advisory + deprecation check]
G --> H[Tag release]
Deprecation‑Aware Security Notes
- Older code paths that relied on implicit entity query behavior are now unsafe from a maintenance perspective; modern Drupal requires explicit access intent.
- Legacy patterns from older Drupal generations (e.g., raw SQL string building) should be treated as migration debt, not “good enough” compatibility code.
- Keep dependency and API usage current to avoid silent drift into unsupported patterns during D10 → D11 transitions.
Warning
Do not mark a release “security reviewed” unless you can point to concrete checks in code or CI. Checklist theater is not hardening.
For adjacent upgrade planning and change tracking, see:
What I Learned
- Enforcing explicit access intent is one of the highest ROI safeguards for contrib maintainers.
- Route‑level permission and CSRF checks catch many “small” mistakes before they become advisories.
- Security hardening is most reliable when embedded in release operations, not left as ad‑hoc reviewer memory.
- Deprecated and legacy coding patterns are not just upgrade problems; they are security risk multipliers over time.