This project is not covered by Drupal’s security advisory policy.
Reports that check a Drupal site against NIST SP 800-53 Rev. 5 controls. Built for government and regulated sites that have to show assessors evidence for an ATO or an annual assessment. Each finding names its control, its severity and how to fix it. The reports only read: nothing on the site is changed. The one exception is an optional security event log, off by default, which only adds log entries.
Everything is under Reports » NIST for Gov (/admin/reports/nist) and needs the View NIST reports permission. The controls come from NIST SP 800-53 Rev. 5 (doi.org/10.6028/NIST.SP.800-53r5).
Secrets left visible (IA-5(7), SC-28)
Lists API keys, passwords and tokens stored in plain text, and never shows a value in full (length and last four characters only).
- High: in exportable configuration and committed to the sync directory, so it's in version control. Remove it and rotate it. IA-5(7).
- Medium: in exportable configuration, including Key module keys that use the
configprovider. The next export commits it. IA-5(7). - Low: in State. Not exported, but every database backup holds it. SC-28.
Each row says how to fix it: a settings.php override from an environment variable, or the Key module with the environment or file provider. Also available as drush nist:secrets, which exits non-zero while a secret is committed, so CI can stop on it. A Status report entry warns while one is committed.
The controls, from NIST SP 800-53 Rev. 5 (doi.org/10.6028/NIST.SP.800-53r5): IA-5(7) No Embedded Unencrypted Static Authenticators ("Ensure that unencrypted static authenticators are not embedded in applications or other forms of static storage."), and SC-28 Protection of Information at Rest.
Credentials left in files (IA-5(7), IA-5(2))
Lists tokens and passwords in git remote URLs (https://user:TOKEN@... in any .git/config, the site's or a cloned module's), saved logins (.netrc, .git-credentials) and SSH keys inside the web root, the files folders and next to the site repository. Private keys are never shown; tokens only by length and last four characters.
- High: a token, password or private key without a passphrase inside the web root, so it can be downloaded unless the server blocks it. Revoke or replace it.
- Medium: the same outside the web root, or a private key with a passphrase.
- Low: public keys,
authorized_keys,known_hosts: no secret, but they name servers and accounts.
Test fixtures are left out by default. Also available as drush nist:files, which exits non-zero while anything is in the web root. IA-5(2) Public Key-based Authentication: "Enforce authorized access to the corresponding private key".
Inactive accounts (AC-2(3))
Lists accounts that are not blocked but nobody has used for 90 days (configurable): no login and no page request, or never logged in since they were created.
- High: user 1, an admin role, or a role with any "restrict access" permission.
- Medium: a role that can create, edit or delete content, media or terms.
- Low (optional): any other account, for sites without public registration.
Also available as drush nist:accounts [--days=N], which exits non-zero while an administrative account is listed. AC-2(3) Disable Accounts: "Disable accounts within [time period] when the accounts: ... Have been inactive for [time period]."
Overview checks
Below the three reports, the overview has one section per smaller check, with the control as its heading:
- AC-6, AC-6(7) Least Privilege: Anonymous or Authenticated holding a "restrict access" permission; roles no active account holds.
- CM-7 Least Functionality: text formats that let content carry
<script>or<iframe>(or have no HTML filter), with who can use them; development modules enabled (Devel, Field UI, Views UI...);update_free_accessorrebuild_accessleft on. - SC-28, IA-5(7): database dumps and copies of
settings.phpor.envfiles in the web root or files folders. - SA-22 Unsupported System Components: contrib projects on dev, alpha, beta or RC releases, projects that never opted in to security advisory coverage, and projects no longer supported.
- SI-2 Flaw Remediation: Update Status disabled, release data never fetched or out of date, no address to email about security releases.
- SC-23 Session Authenticity:
trusted_host_patternsmissing or matching any host. - SC-8 Transmission Confidentiality: the site served over plain HTTP, and modules or themes whose JavaScript uses features browsers block there (location, notifications, service workers, clipboard, camera).
- AC-12, AC-11 Session Termination: idle sessions of admin and editor accounts.
- AC-7 Unsuccessful Logon Attempts: accounts and IP addresses locked out now, and the flood limits in force.
- AC-3, AC-6 Access Enforcement: contrib and custom routes whose
_permissionuses "+" (any one permission, not all), and routes open to everyone that accept POST. - AC-2, IA-5: OpenID Connect clients and OAuth consumers nobody uses; Key module keys no configuration refers to; secrets and the cron key unchanged for a year; the cron key written into settings or the sync directory.
- AU-2, AU-12, AU-11 Event Logging: no module keeping the log, a database log that only reaches back a few days, and the events Drupal core never logs.
Drupal records neither when a key was last used nor when it changed. The age checks keep a short fingerprint of each value (never the value) and count from the first time they see it.
Production secrets on a copy (IA-5, SC-28)
A development or test copy made from the production database keeps production's API keys. On production, drush nist:fingerprints > prod.json prints a short fingerprint of each secret, never a value. On the copy, drush nist:fingerprints-import prod.json stores the list (in State, so it is never exported), and the overview lists every secret on the copy that still holds a production value.
Evidence for assessments (AC-2, AC-6(7), CA-2, CA-7)
- Permission review: every role, the permissions it grants (restricted ones flagged), how many active accounts hold it and a sign-off line per role. Print it to PDF, or download it as CSV.
- Control evidence: every finding of every check in one list, tagged with its control, with the site, Drupal version and time. Print it, download it as JSON, or run
drush nist:evidence. Secrets stay masked.
Security event log (AU-2, AU-12, optional)
Drupal core keeps no record of roles granted or removed, permission changes, accounts blocked, unblocked or deleted, or configuration imports. Run drush config:set nist_gov.settings audit.log_events 1 and NIST for Gov writes each one to the nist_gov log channel, with who did it. Off by default.
Drush
drush nist:secrets,drush nist:files,drush nist:accounts [--days=N]: the three reports. Each exits non-zero on its most severe findings, so CI or a scheduled job can stop or alert on them.drush nist:fingerprints,drush nist:fingerprints-import <file>: production secrets on a copy.drush nist:evidence: every finding as JSON.
Requirements
Drupal 10.3 or 11. No other modules. The release coverage check uses the core Update Status module's data when it is enabled.
More Modules
- Uninstall Impact: Shows what uninstalling a module deletes, before you do it.
Related sites
Project information
- Project categories: Developer tools
- Created by trigve hagen on , updated
This project is not covered by the security advisory policy.
Use at your own risk! It may have publicly disclosed vulnerabilities.

