cyberwoven / module_status
Exposes a lightweight, API-key protected HTTP endpoint reporting basic information about installed modules.
Package info
bitbucket.org/cyberwoven/module_status
Type:drupal-module
pkg:composer/cyberwoven/module_status
Requires
- php: >=8.1
Requires (Dev)
None
Suggests
- drush/drush: For CLI key management via module-status:set-key and module-status:key-status
Provides
None
Conflicts
None
Replaces
None
This package is auto-updated.
Last update: 2026-09-03 15:17:26 UTC
README
A standalone module. Exposes a single HTTP endpoint that reports whether a given module is installed and its version — read directly from Drupal's own module system, no SSH required.
Where this goes
Copy this whole module_status/ directory into your custom modules
directory, e.g.:
modules/custom/module_status/
Installing
drush en module_status
Set up the API key (once per site)
You can do this either from the command line or from the UI — both go through the same underlying logic, so it doesn't matter which you use.
Command line:
drush module-status:set-key
Generates a random key, stores it via Drupal's State API (not config — so it won't end up in an exported config file), and prints it once.
Admin UI:
Visit Configuration → System → Module Status API key
(/admin/config/system/module-status), gated behind the
administer module status api key permission. Click "Generate key" —
the new key is shown once, in the status message after submitting.
Either way: copy the key somewhere safe immediately. There's no way
to read it back out later — if you lose it, generate a new one and
update sites.yml (or wherever you're tracking it) to match. Generating
a new key immediately invalidates the old one.
To check whether a key is set without revealing it:
drush module-status:key-status
Usage
GET /module-status-api/check?module=webform
X-API-Key: <the key from above>
Success:
{
"module": "webform",
"status": "Enabled",
"version": "8.x-6.2"
}
status is one of:
"Enabled"— installed and turned on"Disabled"— present in the codebase but not installed"Not found"— no such module in the codebase at all
Missing/wrong API key → 401:
{ "error": "Unauthorized" }
No key configured on this site yet → 500:
{ "error": "No API key has been configured on this site. Run: drush module-status:set-key, or visit /admin/config/system/module-status." }
Missing/invalid module parameter → 400:
{ "error": "Missing or invalid \"module\" query parameter. Use lowercase letters, numbers, and underscores only." }
How it's put together
ApiKeyManager(src/ApiKeyManager.php) is the one place that generates, stores, and verifies the key. Both the drush command and the admin form call it — neither duplicates the logic.StatusControllerchecks the key viaApiKeyManager::verify()(constant-time comparison) before doing anything else, and fails closed (500) if no key has ever been set.SettingsFormis a normal Drupal form behind a real permission — follows the standard submit → redirect → GET flow, so the generated key only ever appears in a transient status message, never on a page that could be reloaded or cached with the key still showing.
Security notes
- Always call this over HTTPS in production — the API key travels in a plain header, so an HTTP connection would expose it in transit.
- The key is compared with
hash_equals()(constant-time), so a wrong guess can't be timed to leak information about the correct value. - The check endpoint's access is enforced entirely inside the controller
(
_access: 'TRUE'in routing), by design — it isn't meant to require a logged-in Drupal user, since it's called by an external script. The admin settings page is the opposite: a real permission-gated route, since that one's for you, logged in. - Rotate the key any time (CLI or UI) — no restart or deploy needed, it takes effect on the next request.
- Consider also restricting
/module-status-api/checkby IP at the web server level (Apache/Nginx config) as a second layer, if that's easy to do on your hosting — defense in depth, not a replacement for the API key.