Security & Module Risk

Core Overrides That Block Security Patches

A patch you applied may not protect you if an override runs instead of the fixed code. Here is how overrides neutralize patches and how to verify coverage.

Jason Schuman · February 27, 2026

A patch can be applied without protecting the store

Applying a security patch feels like closing a hole. In Magento, that is true only when the patched code is the code the store actually runs. A custom module can replace a core class. A plugin can change what a core method receives or whether that method runs. A hand-edited vendor file can prevent a DIFF from applying cleanly.

Magento can report a patch as applied while vulnerable behavior still runs through code the patch never changed. That creates a dangerous false signal: the deployment record looks clean, but requests still reach the old logic.

This article explains how core overrides block patches, the forms those overrides take, how to find them, and how to confirm that a patch protects the running code. An execution path is the route a request takes through classes and methods. That route is the thread we will follow.

Leftover core overrides Blocking patches. The old overrides win. The new patches will never load.

How an override blocks a patch

Security patches change Magento core code. If a custom module replaced the core class, or a plugin wraps the exact method being fixed, the patch changes code that may no longer run in the normal way.

The patched file can still be present in the vendor Directory while the request flows through an override. The fix exists on disk, but the request never reaches it. The code is patched, and the vulnerable behavior is still active.

Consider a patch that adds an input check to a core validator class. If the store has a preference that sends Magento to a custom version of that validator, Magento uses the custom class when the request arrives. The new check sits in the original core file, while the custom class still follows its old logic.

That is the difference between "we applied the patch" and "we are protected." Both statements are true only when the patched logic is part of the execution path.

A preference can replace the class Magento patched

A preference is a dependency injection setting. In a module's di.xml file, it tells Magento to use one class whenever code asks for another class. The first class is the core class. The second class is the custom replacement.

When Magento builds an object for that core class, the preference sends it to the custom class instead. The custom class then handles requests that would normally reach the original class.

A preference on a class Magento just patched means the patch may have fixed a class that no longer runs. The security fix sits in the original file while the replacement, which may still contain the vulnerable logic, handles the request.

If the vulnerable logic lived in the replaced class, the custom class must be reviewed and updated with the same security change. Patch tools usually change files in the vendor Directory. They cannot safely guess how to add that fix to a custom class with different code.

This is a common source of confusion. The preference can be valid application design, and the patch can be validly applied. The running code can still be missing the fix because those two pieces of code are different.

A plugin can change the patched method's behavior

A plugin is custom code that Magento runs around a public method in another class. A before plugin runs first and can change the method's inputs. An after plugin runs after the original method and can change its result. An around plugin receives a way to call the original method, so it can call it, change its inputs or output, or skip it completely.

That last case is easy to understand. If a security patch adds a check inside a core method, an around plugin can return its own result without calling the patched method. The patched check never runs.

A before plugin can also change the inputs that reach a new check. An after plugin can change the result after the check finishes. These plugins do not need to edit the patched file to change the security result.

Read the plugins attached to every class and method named by the security advisory. A plugin that looked harmless before the patch can become a security gap once the method it wraps is the method being fixed. The patch changed the method, but the plugin still controls part of the path around it.

Hand-edited vendor files can reject a DIFF

The simplest case is a core file edited by hand. Security patches are often distributed as a DIFF. A DIFF describes the exact lines to remove and add. The patch tool looks for enough matching context to know where those changes belong.

If someone changed that file first, the context may no longer match. The patch can fail or report a conflict, leaving the vulnerability open. Someone can also force the DIFF onto the file and lose or damage the hand edit.

All of those outcomes start with a file that was changed in place. The vendor Directory becomes a second source of truth, separate from the code used to build the store. A later patch has to work around that difference before it can secure the file.

Find overrides before you trust the patch

These problems are findable before a patch is applied, and they should be checked again as part of applying one. Each type of override lives in a place you can search.

Start by listing the preferences declared across custom modules and extensions. Search the di.xml files with grep or an IDE for the classes named by the patch. Then review every plugin attached to the patched classes and methods.

For hand edits, create a DIFF between the vendor Directory on the store and a clean install of the exact same Magento version. The clean install gives you a Reproducible baseline. Differences show which vendor files were modified in place.

The security advisory should identify the affected files, classes, methods, and any related CVE numbers. Cross-reference those details with your preferences, plugins, and vendor DIFF. That comparison shows where the patch can stop short of the code handling the request.

Trace the code path after patching

The final step is verification. After applying a patch, confirm that the code it fixes is the code the store executes.

If a preference touches the patched class, verify which class Magento creates for the affected request. If a plugin touches the patched method, read its before, after, and around behavior. For an around plugin, confirm that it calls the original method when the security check must run.

Then test the affected behavior with a Reproducible set of inputs and expected results. Use a safe non-production environment when the test involves a security-sensitive request. The goal is to trace the request from its entry point through the override and into the patched logic.

The question is simple: is the fixed logic in the execution path, or is an override shadowing it? A patch report answers whether files changed. This check answers whether the running store is protected.

Every core override adds patching work

Every core override is a place a future patch may not reach. When a store replaces and wraps more core code, each security patch needs a code-path check instead of a status check alone.

That is a good reason to keep customization narrow and deliberate. A preference or around plugin can be the right tool for a real requirement, but it also creates another path to review when Magento changes the class or method.

Removing unnecessary overrides reduces the number of places a security fix can be blocked. It also makes the running code easier to compare with the patched core code.

Verify the code that actually runs

A security patch protects the store only when its changed logic reaches the request that needed it. Preferences, plugins, and hand edits can each leave the vulnerability active while the patch reports as applied.

For every patch, compare the advisory with the store's preferences, plugin declarations, and vendor DIFF. Trace the affected request. Test the expected result with Reproducible inputs. That is how you confirm protection instead of assuming it from a deployment message.