Signature-Based Malware Scanning
Four signature types, regex patterns, literal byte sequences, suspicious filenames, and pathglob matchers
Scans Magento 2 files for webshells, PolyShell payloads, polyglot files and known Magecart skimmers using four signature types. It also hashes PHP files to flag changes between scans and quarantines critical finds in upload folders.
Key Features:
Additional Services
Built-in from day one. No add-ons, no upsell, no licence keys to renew.
Four signature types, regex patterns, literal byte sequences, suspicious filenames, and pathglob matchers
Baseline hashing, fingerprints every PHP file in core Magento and your custom modules
Zero-touch containment, critical severity findings inside writable upload zones (pub/media, var/import, custom options) are moved to a q…
Findings grid, filter, sort, and bulk-action every detection
Cron-based scheduling, nightly, weekly, or custom cron expression
MEQP compliant, passes Adobe's Magento Extension Quality Program
Panth Malware Scanner is a signature-based malware scanner and file integrity monitor for Magento 2 and Adobe Commerce that detects webshells, PolyShell payloads, PHP object-injection attacks, and polyglot files.
The Panth Malware Scanner extension recursively walks the Magento document root, matches every file against a curated signature catalog of regex patterns, literal byte sequences, suspicious filenames, and path globs, and flags anything that looks like a backdoor, cryptominer, or injection payload. Critical findings are quarantined automatically inside writable upload zones.
It is built for Magento 2 store owners and agencies hardening freshly migrated stores, running post-breach security audits, or wanting continuous integrity monitoring during the active PolyShell (APSB25-94) exploitation wave that started in March 2026. An admin dashboard surfaces every detection with file path, matched signature, severity, and first-seen timestamp.
Scheduled scans run via Magento cron, email notifications alert the security team the moment a scan turns up something suspicious, and the controller-layer block list shuts down PolyShell uploads to /media/custom_options/quote, base64 GIF-header polyglots, and customer-attribute tmpfile abuse before payloads reach disk.
Best for:
Panth Malware Scanner combines signature-driven scanning, file integrity monitoring, and controller-layer blocking for Magento 2.
Panth Malware Scanner adds two layers to a Magento 2 store. A set of plugins inspects file uploads, REST and GraphQL requests, storefront request URIs and cart custom-option payloads while a request is being processed, and rejects anything that matches a built-in list of indicators (PHP open tags, known webshell names and hashes, polyglot image files, StyleSmuggler request markers). Inside files with valid image magic bytes a bare <?= byte sequence is ignored unless printable code follows it, so compressed photo data does not trigger a false positive. A signature-based scanner then walks the configured directories on disk, records every file that matches a signature in an admin grid, optionally moves critical findings inside upload directories to a quarantine folder, and emails a summary of new findings.
The module is used by store owners, agencies and developers who want blocked requests and on-disk findings visible inside the Magento admin. Its own user guide states that it is one layer of a defence-in-depth setup and is not a substitute for security patches, web application firewalls, backups or security audits.
Product page: kishansavaliya.com/magento-2-malware-scanner.html

etc/di.xml, etc/frontend/di.xml, etc/graphql/di.xml and etc/webapi_rest/di.xml (see the guard table under Usage).filename, pathglob, hash, literal and regex signature types; signatures cover PolyShell webshells, polyglot image files, eval() of base64_decode() style backdoors, .htaccess PHP handlers, StyleSmuggler markers, implant names and SHA-256 hashes, command-and-control domains and addresses, and INSERT INTO admin_user statements.vendor/composer/, dev/tests/ and others) plus an admin-configurable list of extra allowlist paths.var/panth_malware_quarantine/ with a .quarantined suffix, set to mode 0600 and the original is removed. Files outside the zones are only reported.bin/magento panth:malware:scan, and an in-admin Documentation & Hardening Guide page.Test/Unit/ for the detectors, scanner evaluation, reconciliation and reopening, file access, configuration reader, notifier, signature provider, grid columns and keyword search, admin actions, cron job, console command and GraphQL guards.The guards run inside the request. A blocked upload raises a LocalizedException and the temporary file is deleted; a blocked REST request gets HTTP 400; a blocked GraphQL request gets HTTP 400 (entry guard, payment guard) or a GraphQlInputException (query guard); a blocked storefront URI or media path gets an empty HTTP 404. Every block is written to the panth_malware_blocked_request table with source IP, user agent, URI, method, matched indicator, SHA-256 of the payload and a 500-character excerpt. Internal errors while inspecting a request let the request continue; an error while logging a block does not cancel the block.
| Guard | Hooks | What it checks |
|---|---|---|
| Upload Guard | Magento\Framework\File\Uploader::save |
First 64 KB of uploads with PHP, script, HTML, SVG, .htaccess or image extensions: image header followed by a PHP tag, or any inline needle (PHP tags, PolyShell beacons and hashes, eval() of base64_decode(), system() on $_REQUEST and similar). |
| REST API Guard | Magento\Webapi\Controller\Rest::dispatch |
URI, query string and header names for injected code, x_trace_ markers and the X-TRACE-<hex> header; POST, PUT and PATCH bodies up to 2 MB for inline needles and base64-encoded PHP tags. Token, customer, payment-information and order endpoints are skipped for the body check. |
| GraphQL Entry Guard | Magento\GraphQl\Controller\GraphQl::dispatch |
Header names, any styles[ query parameter and injected code in the URI (decoded up to three times). |
| GraphQL Guard | Magento\Framework\GraphQl\Query\QueryProcessor::process |
Mutation source text and variables for inline needles and base64 needles. |
| Payment Mutation Guard | Magento\GraphQl\Controller\GraphQl::dispatch |
Payment mutations whose payment methods are all inactive for the current store (configurable). |
| Custom Option Guard | Magento\Catalog\Model\Product\Option\Type\File\ValidatorFile::validate |
Product custom-option file uploads: image header followed by a PHP tag, or any inline needle in the first 64 KB. |
| Cart Custom Option Guard | Magento\Catalog\Model\CustomOptions\CustomOptionProcessor::convertToBuyRequest |
file_content, file_data, base64_encoded_data and content values on cart items, raw and base64-decoded. |
| Customer File Guard | Magento\Customer\Model\FileProcessor |
saveTemporaryFile and moveTemporaryFile for customer and customer address files, including the extension allowlist. |
| Customer Attribute Guard | Magento\Framework\App\Action\Action::execute (frontend) |
Upload-shaped frontend controllers, including the extension allowlist. |
| Image Content Guard | Magento\Catalog\Model\ImageUploader::saveFileToTmpDir |
Admin catalog image uploads: known shell names, missing extension, extension outside jpg, jpeg, gif, png, webp and svg, image header followed by a PHP tag, or any inline needle. |
| Media Path Guard | Magento\MediaStorage\App\Media::launch (pub/get.php) |
Executable extensions, missing extensions and known shell names inside customer-writable media directories. |
| Frontend Path Guard | Magento\Framework\App\FrontController::dispatch (frontend) |
Known PolyShell paths, known shell file names and injected code in the request URI. |
| Webapi File Guard | Magento\Framework\Api\Uploader (webapi_rest) |
REST service-contract file uploads: known shell names, executable extensions, or any inline needle. |
A scan walks each configured scan path, skipping excluded and allowlisted paths, symlinked files, symlinked directories (they are not followed; a configured scan path that is itself a symlink is still opened), files with other extensions and files above the size limit. Each file is read in full, hashed with SHA-256 and evaluated against every signature. A match is stored in panth_malware_scan_result with the highest severity, the matched signature IDs, a 400-character snippet and the first and last seen timestamps. An existing row is reset to status new when the file hash changes, and also when a file that was quarantined, deleted, clean or excluded is found again, so a re-planted file always raises a new alert. After a complete scan, open findings whose file is gone are set to clean and findings whose path is no longer scanned are set to excluded; quarantined findings keep their Quarantined status.
Run a scan in one of three ways:
Panth_MalwareScanner::scan_run). The button asks for confirmation and sends a POST request with the admin form key; the panth_malwarescanner/scan/run controller rejects GET requests. The controller allows up to 900 seconds and sends the notification email afterwards.panth_malwarescanner_run on the configured expression (default 0 3 * * *); the result, including dry_run and would_quarantine, is written to the Magento log.bin/magento panth:malware:scan, with the option --no-email to skip the notification and --dry-run to report findings without quarantining any file for that run. Progress is printed every 200 files.Report Only (Dry Run), panth_malwarescanner/protection/dry_run, default No: when set to Yes, every scan (cron, Run Scan Now and the console command) records findings as usual but never moves a file. Files that would have been auto-quarantined are counted as would_quarantine and logged with the message DRY RUN: would quarantine <path>. With the default No, Auto-Quarantine behaves as before.
Findings have the statuses New, Reviewed, Ignored / False Positive, Quarantined, Deleted, Clean (file no longer on disk) and Excluded (path no longer scanned). From the grid you can view the first 512 KB of a file (ACL Panth_MalwareScanner::scan_view_file), quarantine it, delete it permanently or mark it ignored. Quarantine, Delete Permanently and Mark Ignored require Panth_MalwareScanner::scan_delete. Quarantine copies the file to var/panth_malware_quarantine/<timestamp>__<sanitised path>.quarantined (a numeric suffix is added if that name exists) and removes the original; Delete Permanently unlinks the file. Both actions refuse symlinks and paths outside the Magento root. Ignored, deleted, clean and excluded findings are not emailed again.

After a scan, findings with notified = 0, a status that is not resolved and a severity at or above Minimum Severity for Email are sent in one message with the subject "Malware Scanner Alert: N new finding(s) on
Scan findings are kept until they are deleted from the grid. Blocked request records are kept until an administrator uses Clear Old Records on the Blocked Requests grid, which asks for confirmation and sends a POST request with the admin form key (GET requests are rejected); it deletes records older than 90 days by default (the days parameter accepts 1 to 3650). Quarantined files stay in var/panth_malware_quarantine/ until removed manually.
USER_GUIDE.md covers installation, verifying the guards, each configuration screen, the scheduled scan, email notifications, the findings grid and quarantine workflow, severity levels, the in-admin documentation page, the customer upload allowlist with the matching nginx rules, StyleSmuggler checks, troubleshooting and a CLI reference.
See CHANGELOG.md.
| Platform | Versions |
|---|---|
| Magento Open Source | 2.4.4 to 2.4.8 |
| Adobe Commerce | 2.4.4 to 2.4.8 |
| PHP | 8.1, 8.2, 8.3, 8.4 |
Composer constraints: magento/framework ^103.0, magento/module-backend ^102.0, magento/module-ui ^101.2, magento/module-cron ^100.4, magento/module-config ^101.2, magento/module-store ^101.1, magento/module-catalog ^104.0, magento/module-webapi ^100.4.
~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0.mage2kishan/module-core ^1.0 (module Panth_Core), which provides the parent admin menu and is loaded before this module.magento/* packages listed above.mbstring extension (mb_substr is used when building finding snippets) and a working Magento cron for scheduled scans. No external binaries are called.composer require mage2kishan/module-malware-scanner
bin/magento module:enable Panth_Core Panth_MalwareScanner
bin/magento setup:upgrade
bin/magento setup:di:compile
bin/magento setup:static-content:deploy -f
bin/magento cache:flush
setup:di:compile is only needed in production mode. The static content step is required because the module ships view/adminhtml/web/css/scan-grid.css.
Check the result:
bin/magento module:status Panth_MalwareScanner
Admin path: Stores > Configuration > Panth Extensions > Malware Scanner. All settings are in the default scope except where noted. The section is protected by the ACL resource Panth_MalwareScanner::system_config.

| Setting | Default | What it does |
|---|---|---|
| Enable Module | Yes | Turns the on-disk scanner, the cron scan, the upload janitor cron and every guard plugin on or off. When it is No, all guards let requests through unchanged. If the setting cannot be read, the guards stay active. |
| Max File Size to Scan (KB) | 2048 | Files larger than this are skipped by the scanner. |
| Scan Paths (relative to Magento root) | pub/media, app/code, vendor, var, generated, lib, bin, setup, pub/static | Directories the scanner walks, one per line. |
| Exclude Paths | var/cache, var/log, var/page_cache, var/session, var/tmp, var/view_preprocessed, var/composer_home, generated/code, generated/metadata, pub/static/_cache, pub/static/frontend, pub/static/adminhtml, pub/media/catalog/product/cache | Directories skipped by the scanner, one per line. var/panth_malware_quarantine and the module's own directory are always excluded. |
| File Extensions to Scan | php,phtml,phar,php3,php4,php5,php7,phps,inc,htaccess,jpg,jpeg,png,gif,svg,html,htm,js | Comma-separated list. .htaccess files are always included. |
| Enforce Extension Allowlist on Customer Uploads | Yes | Customer file uploads (customer and customer address attributes, frontend upload controllers) are rejected when the extension is not on the allowlist, regardless of content. Website and store view scope. |
| Customer Upload Extension Allowlist | jpg,jpeg,png,gif,webp,bmp,pdf,doc,docx,xls,xlsx | Comma-separated. Shown only when the setting above is Yes. Website and store view scope. |
| Setting | Default | What it does |
|---|---|---|
| Enable Cron Scan | Yes | Runs the scanner from the panth_malwarescanner_run cron job. Requires Enable Module = Yes. |
| Cron Expression | 0 3 * * * | Schedule of the cron job (daily at 03:00 by default). |
| Setting | Default | What it does |
|---|---|---|
| Auto-Quarantine Critical Findings | Yes | During a scan, files with a critical signature match inside a quarantine zone are moved to var/panth_malware_quarantine/. |
| Report Only (Dry Run) | No | When Yes, scans record findings but never move files; critical findings inside the quarantine zones are only logged as "would quarantine". Applies to the cron scan, Run Scan Now and the console command. |
| Quarantine Zones | pub/media, var/import, var/export, var/tmp, var/importexport | Directories where auto-quarantine may remove files. app, app/code, app/design, app/etc, vendor, lib, generated, bin, setup, pub/static, pub/errors and dev are ignored even if entered here. |
| Purge Non-Allowlisted Customer Uploads (read-side janitor) | No | Enables the hourly panth_malwarescanner_purge_uploads cron job, which deletes files under pub/media/customer_address, pub/media/customer and pub/media/custom_options whose extension is not on the Customer Upload Extension Allowlist. Each deletion is logged to the Blocked Requests grid as janitor_purge. |
| Block Payment Mutations For Disabled Methods | Yes | Rejects the GraphQL mutations handlePayflowProResponse, createPayflowProToken, getPayflowLinkToken, createPaypalExpressToken and createBraintreeClientToken with HTTP 400 when none of the related payment methods is active for the current store. Website and store view scope. |
| Extra Allowlist Paths | (empty) | Path prefixes, one per line, skipped by the scanner in addition to the built-in allowlist. |
A read-only group of label fields listing the guard plugins (Upload Guard, REST API Guard, GraphQL Guard, Payment Mutation Guard, Custom Option Guard, Media Path Guard, Frontend Path Guard, Customer File Guard, Customer Attribute Guard, Image Content Guard, Webapi File Guard, Cart Custom Option Guard). It has no settings.
| Setting | Default | What it does |
|---|---|---|
| Extra command-and-control domains | (empty) | Hosts, one per line or comma separated, added to the shipped list. A file containing one raises a critical finding. |
| Extra attacker addresses | (empty) | IP addresses added to the shipped list. Matched only in script files and under pub/media, var/report, var/import, var/export and var/importexport; a match raises a high finding. |
| Setting | Default | What it does |
|---|---|---|
| Send Email on Detection | Yes | Sends the findings email after a scan. Nothing is sent while Recipient Emails is empty. |
| Recipient Emails | (empty) | One address per line. |
| Minimum Severity for Email | High | Findings below this severity are not emailed. |
| Sender | General Contact | Store email identity used as the sender. |
Config paths: panth_malwarescanner/general/enabled, panth_malwarescanner/general/max_file_size_kb, panth_malwarescanner/general/scan_paths, panth_malwarescanner/general/exclude_paths, panth_malwarescanner/general/extensions, panth_malwarescanner/general/enforce_upload_extension_allowlist, panth_malwarescanner/general/upload_extension_allowlist, panth_malwarescanner/cron/enabled, panth_malwarescanner/cron/schedule, panth_malwarescanner/protection/auto_quarantine, panth_malwarescanner/protection/dry_run, panth_malwarescanner/protection/quarantine_zones, panth_malwarescanner/protection/purge_nonallowlisted_uploads, panth_malwarescanner/protection/payment_method_guard, panth_malwarescanner/protection/allowlist_paths, panth_malwarescanner/indicators/extra_c2_domains, panth_malwarescanner/indicators/extra_c2_ips, panth_malwarescanner/notification/enabled, panth_malwarescanner/notification/recipients, panth_malwarescanner/notification/min_severity, panth_malwarescanner/notification/sender.
Admin menu: the module adds a "Malware Scanner" group under the Panth_Core menu with the entries "Scan Findings", "Blocked Requests", "Configuration" and "Documentation & Hardening Guide". With default settings the scanner runs nightly, auto-quarantine is on, the upload janitor is off and no email is sent until recipients are entered.
bin/magento module:disable Panth_MalwareScanner
composer remove mage2kishan/module-malware-scanner
bin/magento setup:upgrade
bin/magento setup:di:compile
bin/magento cache:flush
The tables panth_malware_scan_result and panth_malware_blocked_request, the panth_malwarescanner/* rows in core_config_data and any files in var/panth_malware_quarantine/ are not removed by these commands. Panth_Core stays installed if other Panth modules use it.
Commercial software license. See LICENSE.txt in this repository.
Panth_MalwareScanner; Composer package: mage2kishan/module-malware-scanner; namespace: Panth\MalwareScanner.Model\SignatureProvider. Request-side patterns live in Model\AttackPatternDetector and Model\RequestInjectionDetector. Model\Scanner evaluates files, Model\FileAccess performs quarantine, purge and safe reads, Model\Notifier sends the email, Model\BlockedRequestLogger writes blocked-request rows, and Helper\Config exposes every setting.guardedOperations argument of Plugin\GraphQl\PaymentMethodGuard in etc/graphql/di.xml and can be extended from another module's di.xml.Console\Command\ScanCommand (panth:malware:scan). Cron classes: Cron\RunScan, Cron\PurgeNonAllowlistedUploads.panth_malwarescanner; controllers under Controller\Adminhtml\Scan (Index, Run, View, Delete, Purge, Ignore, MassDelete, MassPurge, MassIgnore), Controller\Adminhtml\BlockedRequest (Index, View, Clear) and Controller\Adminhtml\Docs\Index.panth_malware_scan_listing and panth_malware_blocked_listing.Panth_MalwareScanner::malware, ::scan_view, ::scan_run, ::scan_delete, ::scan_view_file, ::blocked_log, ::config, ::system_config.etc/db_schema.xml): panth_malware_scan_result and panth_malware_blocked_request.panth_malwarescanner_notification_template (view/frontend/email/malware_alert.html).| Module Category | Security |
|---|---|
| Best For | Mid-Market |
Panth Malware Scanner is built specifically for Magento 2 filesystems, it understands the directory layout, knows which folders are writable from the frontend, and ships signatures tuned for Magento-targeted threats (Magecart skimmers, PolyShell webshells, admin-layout injection). Traditional AV tools scan everything with generic signatures and produce noise.
The Scanner module focuses on detection, quarantine, and alerting. For active prevention (upload guards, REST API filters) Panth Infotech also ships integrated firewall guards described in the module composer description.
No. Scans run via cron in the background. The file walker uses streaming reads and skips known-noise directories so a full scan of a typical 2.4.8 store completes in minutes, not hours.
Yes. Signatures are declared in XML and merged across modules, add your own via an etc/panth_malware_signatures.xml file in a custom module.
They are moved to var/panth_quarantine with full metadata. Nothing is deleted automatically, review and delete manually once confirmed malicious.
Yes. The module is compatible with Adobe Commerce Cloud, quarantine path is configurable to a writable mount.
Yes. Source is on GitHub at github.com/mage2sk/module-malware-scanner.
Yes. Panth_Core is a free required dependency, Composer installs it automatically.
Talk to Kishan directly: written quote, scope and timeline within 24 hours. No sales call.
Malware Scanner & File Integrity Monitor for Magento 2