← Back to blog

How to Audit Third Party Magento 2 Extensions

Rodrigo Biazzi

A typical Magento store runs dozens of third party modules. Some were installed for a campaign that ended years ago. Some come from vendors that no longer exist. Some add a plugin to every product load for a feature used on one page. Each one is code with full access to the database and the request, written by someone you never reviewed.

An extension audit answers three questions for each module: do we still need it, is it safe, and what does it cost in performance and upgrade effort. This is the process I follow. It works for Magento Open Source and Adobe Commerce.

Step 1: build the inventory

Start with a full list of what is installed and where it came from:

bin/magento module:status
composer show --direct
ls app/code/*/
grep -h '"name"' app/code/*/*/composer.json 2>/dev/null

Put the result in a spreadsheet with one row per module: name, vendor, source (Composer or app/code), installed version, latest version, enabled or disabled, and who in the business uses it. Leave Magento core and Adobe modules out. The last column is the one that takes time, because the answer often lives in someone's memory. Ask the people who run the store, not only the developers.

Modules that are disabled but still installed belong on the list too. They are still in the code base, still loaded by Composer, and still need to be compatible on the next upgrade.

Step 2: check maintenance status

composer outdated --direct
composer audit

composer audit checks installed packages against public security advisories. composer outdated shows how far behind each package is. For each extension, also check:

  • When the vendor last released a version
  • Whether the vendor declares support for your Magento version and PHP version
  • Whether the vendor publishes security notices and a changelog
  • Whether you have an active license if updates require one

An extension with no release in two or three years, on a platform that moves this fast, is a risk even if it works today. It will block your next PHP or Magento upgrade, as described in the PHP 8 compatibility guide.

Step 3: look for security red flags

You do not need to read every line. Focus on the code that receives input from outside.

Public web API routes

Check each module's etc/webapi.xml for routes that anyone can call:

grep -rn 'ref="anonymous"' vendor/*/*/etc/webapi.xml app/code/*/*/etc/webapi.xml

Anonymous routes are sometimes correct, for example a public store locator. A route that returns order data, customer data or changes something without authentication is a serious problem.

Admin controllers without ACL

Admin controllers extend Magento\Backend\App\Action and should define an ADMIN_RESOURCE constant or override _isAllowed(). Without that, any admin user, whatever their role, can call the action. List controllers in Adminhtml folders and check each one.

Frontend controllers that change data

A frontend controller that saves or deletes something should only accept POST. The framework validates the form key on POST requests, and implementing HttpPostActionInterface makes the action reject other HTTP methods. Controllers that change data on GET are open to CSRF. Also look for controllers that implement CsrfAwareActionInterface and turn validation off, and make sure there is a good reason.

Dangerous patterns

grep -rnE "unserialize\(|eval\(|shell_exec\(|exec\(|system\(|move_uploaded_file\(" \
    vendor/somevendor app/code --include=*.php
  • SQL built by concatenating request values instead of using bound parameters
  • unserialize() on data that comes from a request or cookie
  • File uploads that do not restrict extensions or that write inside the web root
  • Outgoing calls to the vendor's servers, for license checks or "statistics", that send store data
  • Encoded or obfuscated PHP. You cannot audit code you cannot read.

Each hit needs a human look. The goal is to find the few places worth a careful review, not to reject a module for using exec in a CLI command.

Step 4: measure the performance cost

Extensions slow stores down in a few predictable ways.

Plugins on hot paths

A plugin on a method called hundreds of times per request, like product loading, price calculation or URL generation, multiplies its cost. See every plugin and preference on a class with:

bin/magento dev:di:info "Magento\Catalog\Model\Product"
bin/magento dev:di:info "Magento\Quote\Model\Quote"

Around plugins deserve extra attention. They add a closure call and, if written carelessly, can skip the original method or other plugins. The tradeoffs between plugins, observers and preferences are covered in this comparison.

Observers on frequent events

grep -rln -E "controller_action_predispatch|catalog_product_load_after|catalog_product_collection_load_after|layout_load_before" \
    vendor/*/*/etc/ app/code/*/*/etc/ --include=events.xml

An observer on controller_action_predispatch runs on every request. One that makes a database query or an HTTP call there costs every visitor.

Frontend weight

Check which modules add JavaScript and CSS to every page through default.xml layout files, and which add RequireJS mixins. A chat widget, a popup and a review badge each loading their own library adds up quickly on mobile.

Cron and database

Look at each module's crontab.xml for jobs that run every minute, and at the tables the module creates. Log tables that grow without cleanup are common.

The most reliable measure is a comparison. On staging, profile a category page, a product page and the checkout, then disable one suspect module and profile again. A profiler like Blackfire or New Relic shows exactly which plugin or observer costs time.

Step 5: decide

FindingAction
Nobody uses the featureRemove the module
Used, maintained, no issuesKeep, update to the latest version
Used, outdated but vendor activeUpdate, test, keep
Used, vendor gone or code unsafeReplace with core, another vendor or custom code
Small feature, heavy moduleReplace with a small custom module

Removing is often the cheapest choice, but it has to be done carefully because of database tables, attributes and configuration the module left behind. See how to remove a Magento module safely.

Make it a habit

Run a short version of this audit before every upgrade and once a year in between. Add a rule for new extensions: before installing, check the vendor, the last release date, the webapi.xml, the plugins it declares and whether it ships readable code. Preventing a bad module is much cheaper than removing it later.

FAQ

How many extensions is too many for Magento 2?

There is no fixed number. What matters is what each one does on every request and whether it is maintained. A few heavy modules on hot paths hurt more than many small admin tools.

How can I see all plugins on a Magento class?

Run bin/magento dev:di:info with the class name. It lists the preference, constructor arguments and every plugin with its sort order and type.

Is it safe to use extensions with encoded PHP?

It is a risk, because you cannot review or patch the code. If you must use one, keep it updated and limit its access where you can.

What does composer audit check?

It compares the installed package versions against known security advisories and reports the affected packages. It does not review code that has no published advisory.

I am available for freelance Magento and Adobe Commerce work, including extension audits and replacements. If you need help with this, get in touch.

Related articles