gtstudio / magento-security-audit
Magento 2 security auditing warns when you are behind on Adobe security releases and scans for injected skimmers.
Package info
github.com/gabrielgts/magento-security-audit
Type:composer-plugin
pkg:composer/gtstudio/magento-security-audit
Requires
- php: ^8.1
- composer-plugin-api: ^2.0
- magento/framework: *
- symfony/process: ^6.0 || ^7.0
Requires (Dev)
- composer/composer: ^2.2
Suggests
- gtstudio/magento-boost: AI agent tooling for Magento 2 — picks up this package's security skill automatically
- n98/magerun2-dist: Useful alongside for CLI inspection of a suspect store
README
Security auditing for Magento 2. Warns when you are behind on Adobe security releases, and checks the store for the things a compromise actually leaves behind.
Works standalone. It also ships a security-audit agent skill: install the
gtstudio/magento-boost module alongside
it and the skill is registered automatically, so an AI agent knows to run
security:audit, which severities to act on, and that "patch status unknown" is
not the same answer as "up to date".
Why this exists
composer audit does not cover Magento core. The advisory database it reads
holds 133 entries for magento/product-community-edition and they are almost all
CVE-2019 — the only recent addition is CVE-2024-34102 (CosmicSting). GitHub's
Advisory Database is worse; its newest Magento entry is from 2022. Adobe does not
publish APSB bulletins into the Composer ecosystem databases.
So a Magento store can be ten security releases behind while composer audit
reports clean. This package closes that gap by comparing your installed version
against Adobe's own release list.
Install
composer require --dev gtstudio/magento-security-audit bin/magento setup:upgrade
Composer will ask to allow the plugin. If you decline, or run in CI where nothing
can answer, the package still installs and security:audit still works — only the
automatic warning goes quiet.
To allow it explicitly:
composer config allow-plugins.gtstudio/magento-security-audit true
Two ways it runs
1. Automatically, after a dependency change
$ composer require some/package
...
magento-security-audit: magento/product-community-edition 2.4.7-p3 is behind — 2.4.7-p10 is the current security release for this branch.
Fires on composer update, composer require and composer remove. Not on a
plain composer install against a committed lock file — that is the deploy path,
and it stays silent and offline.
It prints nothing when the store is current, never changes the exit code, times out
after 3 seconds, and caches the release list for 6 hours. Silence it entirely with
MAGENTO_BOOST_SKIP_AUDIT=1.
2. On demand, with the full check suite
bin/magento security:audit
| Flag | Effect |
|---|---|
--json |
Machine-readable output |
--deep |
Also scan vendor/magento for post-install modification (slow) |
--no-cve |
Skip the NVD lookup |
--skip-signatures |
Do not invoke eComscan even if installed |
Exit code is non-zero when there are critical findings, so it works in CI.
What it checks
| Check | Needs | Looks for |
|---|---|---|
| Patch status | network | Installed version vs Adobe's release list, plus matching CVEs from NVD |
| Media shells | — | .php/.phar/.phtml under pub/media or pub/static |
| Webroot exposure | — | .git, database dumps and backup archives, and PHP entrypoints Magento does not ship, at the top of pub/ or the project root |
| Injected payloads | — | eval, base64_decode, shell_exec and friends in machine-generated PHP under generated/, var/ and pub/ |
| Package origins | — | composer.lock dist URLs pointing at hosts that are not Adobe, Packagist or a known VCS |
| Config injection | database | Skimmers in core_config_data — design/head/includes, footer HTML, analytics paths |
| Admin users | database | Accounts created recently, or active but never logged in |
| Core integrity | --deep |
Files under vendor/magento modified after install |
Media shells are worth singling out: Magento ships pub/media/.htaccess to deny
PHP execution, but nginx ignores .htaccess entirely, which is most production
stacks. An uploaded shell there is directly reachable.
Injected payloads is the same idea one directory over. generated/ and
var/view_preprocessed/ hold code Magento wrote — interceptors, proxies, compiled
templates — which is writable by the web user and read by nobody, so a backdoor
there outlives every cleanup aimed at pub/media. None of that code has any
business calling eval.
Both editions
Magento Open Source and Adobe Commerce share a version numbering and a release
feed — magento_releases.json keys on the shared version and lists
magento2-base and magento2-ee-base under it — so patch drift is detected
identically for magento/product-community-edition and
magento/product-enterprise-edition. Adobe Commerce Cloud is covered too: its
metapackage pulls product-enterprise-edition into the lock. Findings name the
edition they apply to.
The NVD lookup uses one CPE, cpe:2.3:a:adobe:commerce, for both. That is not an
oversight — Adobe files every APSB against "Adobe Commerce and Magento Open
Source" and NVD records it under that single name. For 2.4.7 it returns 151
results, while adobe:magento_open_source and the legacy magento:magento
return zero.
Signature scanning (optional)
Deterministic checks catch what is deterministic. Actual malware signatures are a threat-intelligence product, and not one worth reimplementing badly — the open source magento-malware-scanner is GPL-3.0, last updated December 2023, and ships roughly 30 KB of rules against the ~50,000 signatures in commercial tools.
So if eComscan is installed, this package shells out to it:
ecomscan --format=json --skip-dashboard <project-root>
--skip-dashboard is deliberate — the default uploads results to Sansec and
retains them for six months. On a client store that must be opt-in.
eComscan is a paid, closed-source product. Nothing of it is bundled here. Put
your key in ECOMSCAN_KEY, never in a committed file. When the binary is absent
the report says signature coverage is off rather than staying silent, because
silence would read as a clean scan.
Not a substitute for
Incident response. If this reports critical findings, you have a starting point, not a conclusion. Preserve evidence before cleaning anything — removing a payload does not remove the access that placed it.
License
MIT