Security & Module Risk

Magento 2 Core File Integrity Checks on 2.4.x

Magento 2 has no built-in checksum tool. Here is the diff-against-clean-install method we use to catch hand-edited vendor code during an audit.

Jason Schuman · December 1, 2025

Vendor code that has been hand-edited is no longer vendor code

Every Magento 2.4.x store installs core code through Composer into vendor/magento/*. That code is supposed to be immutable between releases: you upgrade it, you patch it, you never open a file in vendor/magento/module-checkout and change a line by hand.

In practice, hand-edited vendor files still show up in stores we audit.

This article shows how to check for it directly, without guessing based on version numbers or changelog entries.

Why "integrity" means something specific in a Composer install

Magento 2 does not ship a built-in checksum tool the way Magento 1 did with its admin file integrity checker. There is no bin/magento core:file:verify command.

What you have instead is a Composer install that is fully reproducible. Every package version pulled into composer.lock corresponds to an exact, publicly available set of files.

So the integrity check comes down to a diff. The question is whether production matches a fresh Composer install for the same version and patch level.

If a file inside vendor/magento differs from a clean install of the same package version, someone edited core code directly. There is no other explanation.

The diff-against-clean-install method

This is the approach we use during a forensic audit, and it works the same way on any 2.4.x store.

  • Pull the exact version string with composer show -a magento/product-community-edition (or magento/product-enterprise-edition).
  • In a scratch directory, run a clean Composer install pinned to that exact version and the same composer.lock if you have it.
  • Run diff -rq vendor/magento production/vendor/magento between the clean install and the production copy.
  • Every file the diff flags is a candidate for review. It either changed intentionally in a patch release you missed, or someone modified it directly.

A recursive diff on a full vendor/ tree is noisy the first time you run it. Narrow it to vendor/magento first, since that is where direct core edits do the most damage.

What to exclude before you trust the results

Not every discrepancy is tampering. Build artifacts and generated code will always differ between a clean install and a running store.

Exclude these directories from the comparison entirely:

  • generated/code and generated/metadata, because interceptors and factories are built at compile time
  • pub/static, because it contains deployed static content
  • var/, because it contains cache, session, and log data
  • any file with a modified timestamp that predates the current package version, which usually just means your filesystem preserved mtimes across a deployment

Once those are out of the picture, whatever remains inside vendor/magento/module-* is worth reading line by line.

What agency hand-offs actually look like on disk

The most common pattern is not malware. It is a developer under deadline pressure who needed to change checkout or shipping behavior and opened the vendor file instead of writing a plugin.

That edit works until the next composer update. Composer has no record of the hand edit, so it overwrites the file with the package version.

The store then regresses in production with no corresponding code change in version control, because the "fix" never existed anywhere Git could see it.

Direct vendor edit

A line inside vendor/magento/module-sales/Model/Order.php was changed by hand. Invisible to git log if vendor is gitignored, and reverted on the next Composer update.

Missed proper override

The correct fix was a plugin or preference in a custom module. It was skipped because it takes longer to scaffold than opening the file directly.

Injected backdoor

A single obfuscated line added to pub/index.php or a framework bootstrap file after a compromised admin credential or unpatched extension.

Disguised file drop

A PHP file placed in pub/media with an image-like name. Diffing vendor/magento will not catch this, so check writable upload directories separately.

Automated checks worth running alongside the manual diff

The manual diff is the ground truth, but two automated tools catch different classes of problems and take minutes to run.

Magento Security Scan Tool (magento.com/security/tools/scan) checks a public-facing store URL against a database of known malware signatures and disclosed core vulnerabilities. It will not see hand-edited files that don't match a known signature, but it is free and catches the compromises that follow a documented pattern.

Composer audit checks your composer.lock for installed packages with disclosed CVEs. Run composer audit with Composer 2.4 or later. This checks known vulnerabilities in dependency versions, not file-level tampering, so treat it as a separate signal from the diff.

Neither tool replaces the diff. They cover known threats; the diff catches anything unique to your store.

What this means for a 2.4.x store you did not build from scratch

If you inherited a store through an agency hand-off, an acquisition, or years of contractor turnover, you cannot assume vendor/magento matches what Composer thinks it installed. The only way to know is to diff it.

Run the comparison once as a baseline, then again after every core upgrade and every incident response. It takes an afternoon and it answers a question that otherwise sits as an open assumption in your platform's risk profile.

Knowing whether your core files match what Composer says you installed is the first fact in any real security review. Patch cadence, extension review, and access control all depend on that fact being true.