Audit Overview
Audit Fields
Audit Database

This project is not covered by Drupal’s security advisory policy.

A Drupal site auditing framework that finds configuration issues, performance problems, security risks and best practice violations, and turns them into 0-100 scores with concrete recommendations. It also tracks every installed module and theme with its version and flags pending updates, including security releases.

The module is free and open source, and works completely standalone. Optionally, it can connect to DruScan, a centralized dashboard where you can see audit scores and module versions from all your Drupal projects in one place.

What you get

  • Health scores: a 0-100 score for each audit (performance, security, SEO, caching, content structure, Views, code quality and more), broken down into weighted factors that show exactly where points were lost.
  • Project Score: an overall weighted score combining all enabled audits. The weight of each audit is configurable.
  • Detailed reports per category: each submodule has its own report page with the detected issues, filterable by severity, the current configuration and specific recommendations to improve that category's score.
  • Module inventory: every installed module and theme with its current version, available updates and security releases flagged.
  • Drush commands with JSON output: run one, several or all audits from the command line, filter the findings, and fail a pipeline when a finding reaches a given severity.
  • Real-time results: audits run on demand, so reports are never stale. Only the scores are stored.
  • Room for intentional choices: acknowledge a finding next to the code with an audit-ignore comment, change the severity of a rule for some paths, accept settings that are overridden only in development environments, and use per-audit settings for decisions your site makes on purpose (allowed modules, bundles allowed to be empty, fields allowed to be hidden, ignored log entries and more). Acknowledged findings stay visible in the report but do not lower the score.

Works great as a quality gate for AI-generated code

AI coding tools are now part of many Drupal development workflows. The code they produce often works on the first run, but it does not always follow Drupal community standards, tends to use deprecated APIs, and occasionally introduces security problems that are not immediately obvious.

The Drush commands are designed to be part of that loop. An agent (or a CI job) runs the code audits on the module it just changed, reads the JSON and fixes the errors before the work is considered done:

drush audit:run phpcs,phpstan,twig --filter="module:my_module" --format=json
drush audit:run security --fail-on=error

The README includes ready-to-paste instructions for CLAUDE.md, .cursorrules or .github/copilot-instructions.md.

Typical use cases

Taking over a client project. Run a full audit before writing a single line of code. You get a scored inventory of every installed module, pending security updates, unused fields, misconfigured Views, cache configuration issues, and performance problems. You walk into the kickoff meeting with actual data instead of guesses.

Pre-deploy validation. Enable audit_phpstan, audit_phpcs, and audit_cache in your staging environment. Before every deploy, run the audits with --fail-on=error to confirm that custom code meets Drupal standards and that caching is configured correctly for production.

Keeping every environment as intended. With audit_config_checks, declare what each environment must look like (for example, CSS/JS aggregation on and Devel off in production, verbose errors allowed in development) and see at a glance when an environment drifts from it.

Ongoing maintenance across multiple projects. Install the module on every client site and connect to DruScan to see pending updates, security advisories, and health scores for your entire portfolio from one dashboard, without logging into each site individually. Add audit_health_check to let your uptime monitor alert you when a site's scores drop.

Code complexity review. Use audit_complexity and audit_duplication to identify code that has grown too complex or has been copied and pasted over time and is becoming a maintenance risk. Useful when deciding where to refactor before adding new features.

Submodules

Install only what you need.

Production-ready audits (all included in audit_all)

  • audit_status: PHP and database versions and configuration (OPcache, memory limits, MySQL/MariaDB variables), Drupal status report requirements, and cron and update status.
  • audit_cron: Whether cron runs on time, queue backlogs, and the hook_cron implementations of the site.
  • audit_modules: Development or risky modules enabled on the site, modules and themes that look unused or removable, duplicated module copies, UI-only modules, redundant themes, and recommended modules missing for the type of site.
  • audit_updates: Pending security and regular updates for Drupal core, modules and themes, the health of the update system, and compatibility with the next major Drupal version.
  • audit_security: Risky permissions, text formats, file system protection, trusted hosts, account creation, the admin account, Views access, upload extensions, security headers and error display, plus a static scan of custom code for code injection, SQL injection, XSS and access control patterns.
  • audit_performance: Page cache and CSS/JS aggregation settings, production settings such as error display and Twig debug, development modules, the cache modules suited to your audience (including BigPipe), and cache and debug anti-patterns in custom code.
  • audit_cache: Cache backends and bins (database versus Redis or Memcache), page cache settings, cache tag usage in custom code, and how often cache tags are invalidated.
  • audit_database: Database and table sizes, tables without primary keys, fragmentation, orphaned field tables, cache bins stored in the database, and the logging setup.
  • audit_entity: Content volume by entity type, bundle and language: empty or unpublished-only bundles, revision bloat, revision table size and translation gaps.
  • audit_fields: Unused and hidden fields, orphaned field storage, bundles with too many fields, view modes or form modes, and fields without a description.
  • audit_views: View displays without caching or with generic cache tags, displays with too many relationships, administration displays open to anonymous users, and Search API views that load fields from the database.
  • audit_twig: Template anti-patterns (debug code, database queries, render array drilling, unsafe |raw usage, inline CSS), entity templates that break cache bubbling, fields rendered versus the display configuration, external libraries, theme suggestions and preprocess anti-patterns.
  • audit_images: The Responsive Image module, image fields shown without an image style or without responsive images, lazy loading, and unused image styles.
  • audit_blocks: Block cache configuration, disabled block placements and custom block types.
  • audit_menu: Menu depth, disabled menu links and empty menus.
  • audit_seo: Essential SEO modules (Metatag, Pathauto, Simple XML Sitemap, Redirect), URL alias patterns for each bundle, image alt text and robots.txt.
  • audit_url: Redirect loops, redirects to broken destinations and duplicated redirects, plus duplicated aliases, aliases that shadow routes or point to missing content, and conflicts between aliases and redirects.
  • audit_i18n: Multilingual modules, interface translation coverage per language, and hreflang tags.
  • audit_watchdog: The database log by recency (last 24 hours, last week, older): PHP errors, other errors, 404 pages, failed logins and SQL errors, and overall log health.
  • audit_config_checks: Scores the environment against the configuration values and modules you declare for it, with a summary block and an indicator in the Navigation bar.
  • audit_all: Enables all of the audits above in a single step. Convenient for a first audit of an unfamiliar project.

Optional

  • audit_search_api: Search API server availability and index status. Requires Search API.
  • audit_health_check: A /audit/health endpoint for uptime monitors and load balancers. It answers 200 while the selected audits reach their minimum scores and the database, cron, files and cache checks pass, and 503 otherwise. Always protected by a secret.

Development-only audits

  • audit_phpstan: Runs PHPStan with Drupal support on custom code. Catches type errors, deprecated APIs and undefined references before they appear at runtime.
  • audit_phpcs: Checks custom code against the Drupal and DrupalPractice coding standards with PHP_CodeSniffer, the same standards the community applies to contributed modules.
  • audit_phpunit: Analyzes the test structure of custom modules and themes. It does not execute tests (that belongs in your CI/CD pipeline) but shows which modules have no unit tests at all.
  • audit_complexity: Measures cyclomatic complexity, maintainability index and Drupal anti-patterns in custom code, and flags functions that have grown too complex to change safely.
  • audit_duplication: Detects copy-paste clones in custom PHP, Twig, JavaScript and CSS, including Drupal's .module, .install, .theme and .inc files.

Installation

Requires Drupal 10.3 or later, 11 or 12.

composer require drupal/audit
drush en audit

Common setup for agencies managing client sites:

drush en audit audit_updates audit_security audit_performance audit_cache audit_seo

Full audit of an inherited project:

drush en audit_all

Code quality submodules for development and staging environments:

drush en audit_phpstan audit_phpcs audit_phpunit audit_complexity audit_duplication

After enabling the module, go to Reports > Audit (/admin/reports/audit) to see your first report.

Production use

Most submodules run fine on production. They perform read-only inspections and do not modify files, configuration, or content. The exceptions are the development-only audits (audit_phpstan, audit_phpcs, audit_phpunit, audit_complexity and audit_duplication): most of them need external tools (PHPStan, PHP_CodeSniffer, phploc or jscpd) and they can be resource-intensive, so enable them only in development or staging environments, for example through a Config Split.

Optional: connect to DruScan dashboard

If you manage multiple Drupal projects, checking audit results site by site gets old fast. DruScan is a centralized dashboard where you can see all your projects together. The main advantage is having a single place to check which projects have pending module updates, which ones have security patches waiting, and how each project scores across all audit categories.

Once configured, cron recalculates the audits and sends the results at most once a day. Only summary data is sent: the score of each audit and of its factors, the number of issues by severity, the installed modules with their versions and update status, and the Drupal, PHP, web server and database versions. No code, content, user data, configuration values or individual findings ever leave your server. The full audit report stays on your Drupal installation.

Registration is free and supports unlimited projects. For more details on available plans, visit druscan.com.

Does this replace a professional audit?

No. The module automates detection of common issues and saves hours of manual work, but it does not replace a senior developer reviewing custom code and architectural decisions. Think of it as a thorough first pass that catches the most common problems and gives you a structured baseline to work from.

Supporting organizations: 

Project information

Releases