hk2 / sanitize-search
Magento 2 extension to sanitize harmful SQL keywords from search queries
Package info
github.com/basantmandal/magento2-search-sanitizer-module
Type:magento2-module
pkg:composer/hk2/sanitize-search
Requires
- php: ^8.1 || ^8.2 || ^8.3 || ^8.4
- hk2/core: ^1.0
- magento/framework: ^103.0.0
README
HK2 Sanitize Search โ Magento 2 Search Query Sanitizer
HK2 SanitizeSearch is a lightweight Magento 2 module that sanitizes user-submitted search queries by stripping harmful SQL keywords and characters. It hooks into Magento\Search\Model\QueryFactory via a beforeCreate plugin, applies a regex filter, and logs sanitization events to a dedicated log file for auditing.
๐ Overview
The module acts as a defense-in-depth layer against SQL injection attempts entering through the storefront search box. It removes SQL control keywords (SELECT, INSERT, UPDATE, DELETE, DROP, UNION), statement terminators (;), and comment markers (--, #) from user input before it reaches the search pipeline. Clean queries pass through with zero overhead.
๐ง Problem Statement
Magento's native search accepts arbitrary user input and feeds it into the search query pipeline. While Magento uses prepared statements and proper ORM practices, an unsanitized search box represents an unnecessary attack surface. Malicious actors can probe the system by submitting search strings containing SQL control characters and keywords (e.g., SELECT, UNION, ;, --).
Security best practices dictate that user input should be sanitized at every trust boundary. The search input field โ accessible to any visitor โ is a clear trust boundary that benefits from proactive sanitization.
๐ก Solution Approach
A plugin intercepts the beforeCreate method of Magento\Search\Model\QueryFactory and applies a preg_replace to remove dangerous patterns from the raw query string:
- SQL keywords:
SELECT,INSERT,UPDATE,DELETE,DROP,UNION(case-insensitive) - Statement terminator:
; - SQL comment markers:
--and#
If any content is stripped, the event is logged to var/log/sanitizer.log at WARNING level. The sanitizer can be toggled on/off via admin configuration at Stores > Configuration > HK2 > Search Sanitizer.
๐ Alternatives Considered
| Approach | Why not chosen |
|---|---|
| Prepared statement reliance only | Places full trust in the ORM layer; no defense-in-depth at the input boundary |
| Full input validation/whitelisting | Too restrictive; would break legitimate search queries with special characters |
| WAF-level filtering | Requires external infrastructure; adds latency; harder to audit |
| Escaping instead of stripping | Escaped SQL keywords may still appear suspicious in logs or trigger false alarms |
| Third-party security module | Heavy dependency; most include far more than search sanitization |
Stripping is chosen as a minimal, predictable operation โ it removes known dangerous patterns without altering the shape of legitimate queries.
๐ฅ Who is this for?
- Magento 2 store owners hardening their storefront against SQL injection probes
- Security-conscious developers needing a zero-dependency, auditable sanitization layer
- Agencies and system integrators deploying sites that must pass security compliance reviews
- Merchants in regulated industries (finance, healthcare, e-commerce) with customer data behind the search interface
๐ฏ Use Cases
- E-commerce stores โ prevent SQL injection attempts through the product search box
- Multi-tenant Magento installations โ a vulnerability in one tenant's code could be probed via search
- Compliance-driven environments โ satisfying audit requirements for input sanitization at all user entry points
- Staging/demo sites โ quickly add a security layer without modifying core or installing a full security suite
- Custom search implementations โ where
Magento\Search\Model\QueryFactoryis still part of the pipeline
โจ Key Features
- SQL keyword stripping โ removes
SELECT,INSERT,UPDATE,DELETE,DROP,UNION,;,--, and#from search queries (case-insensitive) - Dedicated logging โ every sanitization event is recorded to
var/log/sanitizer.logat WARNING level with original and sanitized values - Configurable enable/disable โ toggle via Stores > Configuration > HK2 > Search Sanitizer
- Defense-in-depth โ complements Magento's ORM and prepared statements with input-level sanitization
- Zero impact on clean queries โ queries without harmful patterns pass through unmodified
- Lightweight โ single plugin, no database schemas, no API endpoints, no console commands
๐๏ธ Architecture Overview
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Storefront search form โ
โ User submits: "product; DROP TABLE customers; --" โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Magento\Search\Model\QueryFactory::beforeCreate โ
โ (Plugin: HK2\SanitizeSearch\Plugin\SearchSanitizer) โ
โ โ
โ 1. Check config flag (hk2_sanitizesearch/general/enabled) โ
โ 2. If disabled โ return original query unchanged โ
โ 3. If enabled: โ
โ a. preg_replace(/(select|insert|update|delete|drop|union|;|--|#)/i) โ
โ b. trim() โ
โ c. If changed โ log original + sanitized to Monolog (WARNING) โ
โ d. Return sanitized query โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Normal Magento search pipeline โ
โ (Query, search results, etc.) โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Logging (when change detected):
HK2\SanitizeSearch\Logger\Logger (custom Monolog channel)
โโโ HK2\SanitizeSearch\Logger\Handler (writes to var/log/sanitizer.log, WARNING level)
Key files
| File | Role |
|---|---|
Plugin/SearchSanitizer.php |
Plugin intercepting QueryFactory::beforeCreate |
Logger/Logger.php |
Custom Monolog logger class |
Logger/Handler.php |
Log handler writing to var/log/sanitizer.log |
etc/di.xml |
Plugin registration and logger wiring |
etc/module.xml |
Module declaration sequencing on HK2_Core |
etc/adminhtml/system.xml |
Admin system configuration under HK2 tab |
etc/adminhtml/menu.xml |
Admin menu entry under Content |
๐ System Requirements
- Magento: 2.4.x (Open Source / Adobe Commerce)
- PHP: ^8.1 || ^8.2 || ^8.3 || ^8.4
- Composer: 2.x
- Dependencies:
hk2/core^1.0,magento/framework^103.0.0 - No database modifications โ operates entirely at the PHP plugin layer
๐ Installation
composer require hk2/sanitize-search
bin/magento module:enable HK2_SanitizeSearch bin/magento setup:upgrade bin/magento cache:clean
Verify:
bin/magento module:status HK2_SanitizeSearch
โ๏ธ Configuration
Navigate to Stores > Configuration > HK2 > Search Sanitizer (or Content > Search Sanitizer from the admin menu).
| Setting | Description |
|---|---|
| Enable Search Sanitization | Set to Yes to enable SQL keyword stripping. Set to No to pass all queries through unchanged. |
Default: No (disabled). Ships disabled so operators can enable after testing.
Configuration path: hk2_sanitizesearch/general/enabled
๐ Content Security Policy (CSP)
This module does not modify Magento's CSP headers or csp_whitelist.xml. It operates exclusively at the server-side PHP layer before the search query enters the ORM pipeline.
HK2 SanitizeSearch complements CSP in a holistic security strategy: CSP prevents malicious scripts from executing in the browser, while search sanitization prevents malicious SQL patterns from entering the database pipeline.
๐ Production Readiness
This module is production-ready and has been designed with the following considerations:
- Zero database schema changes โ no setup patch, no SQL install/upgrade scripts, no data patches
- Zero API surface โ no REST, GraphQL, or SOAP endpoints to secure
- Minimal performance impact โ a single
preg_replaceon the search query string; disabled by default - Configurable at runtime โ toggle via admin configuration without code deployment
- Defense-in-depth โ complements existing Magento security layers rather than replacing them
- Auditable โ all sanitization events are logged with original and sanitized values for forensic review
Enable on staging first, test with your store's typical search patterns, then enable in production.
๐ Privacy & GDPR
- No personal data collection โ the module does not track, store, or transmit user identities, IP addresses, or session data
- Log contents โ the only persisted data is the original and sanitized query string (written to
var/log/sanitizer.logat WARNING level) - Log retention โ standard Magento log rotation applies; configure per your data protection obligations
- No third-party services โ the module makes no external network calls and sends no data off-server
- Recommended actions: review log retention for
var/log/sanitizer.log, consider disabling query logging if searches may contain PII, include sanitization logging in your data processing register
๐งช Testing Strategy
| Test case | Input | Expected output |
|---|---|---|
| Clean query | laptop |
laptop (unchanged, no log) |
| SQL keyword | SELECT * FROM users |
* FROM users (logged) |
| Statement terminator | admin'; DELETE |
admin'' (logged) |
| Comment marker | password-- comment |
password comment (logged) |
| Hash comment | admin#foo |
adminfoo (logged) |
| Mixed case | UnIoN Select 1 |
1 (logged) |
| Multiple keywords | DROP;SELECT;UPDATE |
`` (empty, logged) |
| Disabled module | any input with config disabled | unchanged, no log |
| Empty input | `` | `` (no error) |
Recommended approach: enable on a staging environment first, submit various test queries, and inspect var/log/sanitizer.log before enabling in production.
No automated test suite ships with the module.
๐ Documentation
Additional documentation is available in the docs/ directory:
โ ๏ธ Known Limitations
- Pattern-based, not context-aware โ the regex match removes substrings. "selective" becomes "ive". This is by design: the filter errs on the side of removing potential threats.
- Defense-in-depth, not primary SQL protection โ not a substitute for prepared statements, parameterized queries, or proper ORM usage.
- No Unicode / multibyte awareness โ non-ASCII homoglyph attacks are not detected.
- Log growth โ in high-traffic stores with aggressive probing, the log file may grow quickly.
๐ค Contributing
Contributions are welcome. Please open an issue or pull request on the GitHub repository.
All contributions must adhere to the Conventional Commits specification for automated semantic release.
๐ License
Licensed under the Open Software License 3.0 (OSL-3.0).
The OSL-3.0 is an OSI-approved open source license. It allows you to use, modify, and distribute this software, provided that distributed modifications are made available in source code form.
โ๏ธ Disclaimer
This module provides defense-in-depth sanitization and is not a replacement for secure coding practices. The author and Basant Mandal are not responsible for any damages or security breaches resulting from the use or misuse of this software. Always follow Magento security best practices, keep your installation up to date, and perform regular security audits.