Security is a crucial part of any eCommerce platform, and Adobe Commerce (Magento) offers several built-in security features to protect stores from attacks. In this blog, we will cover six important security features with simple explanations and examples.
1. Content Security Policy (CSP)
CSP is a security feature like a bounce for your website, that defines which sources of content (e.g., scripts, images, etc.) are allowed to be executed within a web page.
It helps to prevents cross-site scripting (XSS) attacks by restricting unauthorized sources of content.
Imagine a hacker tries to inject a malicious script into your product page to steal customer information. With CSP enabled, Adobe Commerce will block that script from loading, keeping your site safe.
How to Implement CSP in Magento?
Magento allows you to whitelist safe scripts and resources using the csp_whitelist.xml
file.
<?xml version="1.0" encoding="UTF-8"?>
<csp_whitelist xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Csp:etc/csp_whitelist.xsd">
<policies>
<policy id="script-src">
<values>
<value id="cardinal_commerce_geo" type="host">geoapi.cardinalcommerce.com</value>
<value id="cardinal_commerce_1eaf" type="host">1eafapi.cardinalcommerce.com</value>
</values>
</policy>
<policy id="connect-src">
<values>
<value id="cardinal_commerce_geo" type="host">geo.cardinalcommerce.com</value>
<value id="cardinal_commerce_1eaf" type="host">1eaf.cardinalcommerce.com</value>
</values>
</policy>
<policy id="frame-src">
<values>
<value id="cardinal_commerce_geo" type="host">geo.cardinalcommerce.com</value>
<value id="cardinal_commerce_1eaf" type="host">1eaf.cardinalcommerce.com</value>
</values>
</policy>
<policy id="form-action">
<values>
<value id="cardinal_commerce_geo" type="host">geo.cardinalcommerce.com</value>
<value id="cardinal_commerce_1eaf_stag" type="host">*.cardinalcommerce.com</value>
<value id="cardinal_commerce_cent" type="host">centinelapi.cardinalcommerce.com</value>
</values>
</policy>
</policies>
</csp_whitelist>
Identification
- CSP errors in the browser console (blocked scripts, images, etc.).
csp_whitelist.xml
file in a module.- Headers like
Content-Security-Policy
in responses. - JavaScript inline styles or scripts blocked by CSP.
Types of Policies
You can find below policy supported by Magento 2 using below command in your code-base.
grep -ohr '<policy id="[^"]*"' app/code vendor/magento | sort -u
Policy ID | Purpose |
---|---|
connect-src | Restricts AJAX, WebSockets, and Fetch API requests |
font-src | Controls where fonts can be loaded from |
form-action | Restricts form submission destinations |
frame-ancestors | Controls which domains can embed Magento in an iframe |
frame-src | Defines where iframes can load content from (deprecated) |
img-src | Restricts image loading sources |
media-src | Controls where audio/video files can be loaded from |
object-src | Blocks or restricts <object> , <embed> , <applet> |
script-src | Restricts JavaScript execution sources |
style-src | Controls where CSS stylesheets can be loaded from |
2. Escaping
Adobe Commerce uses escaping mechanisms to prevent XSS attacks by ensuring that user-supplied data is properly encoded before being output in HTML.
This prevents attackers from injecting malicious code into a website.
How to Securely Render Dynamic Values in Magento?
In Magento 2, To render values securely in different contexts, we can use the block’s built-in escaping methods:
For JavaScript
$block->escapeJs('value');
This method escapes a string for JavaScript context, ensuring that special characters (like unicode symbols) are properly encoded.
For HTML
$block->escapeHtml('value', $allowedTags);
This should be your default method for escaping output in HTML. It prevents execution of harmful scripts while allowing safe HTML tags if specified.
For HTML Attributes
$block->escapeHtmlAttr('value', $escapeSingleQuote);
Use this method when inserting dynamic values into HTML attributes.
For Example:
title="<?php echo $block->escapeHtmlAttr($title) ?>"
By default, it also escapes single quotes. If you do not need this behavior, set the second parameter to false
:
onclick="console.log('<?php echo $block->escapeHtmlAttr($message, false) ?>')"
For URLs
$block->escapeUrl($url);
This method ensures that only safe URLs are used, preventing security risks from malicious inputs like javascript:
, vbscript:
, and data:
schemes.
These escaping methods are part of Magento’s AbstractBlock
class and provide a robust way to securely handle user input across different contexts.
Identification
- Use of
escapeHtml()
,escapeJs()
,escapeUrl()
,escapeCss()
in templates. - Use of
__(‘text’)
for translations (since it applies escaping). - Checking for
Magento\Framework\Escaper
in PHP files.
Available Escape Functions in Magento 2
You can find all the available functions in the Magento 2 code base using below grep command:
grep -A 1 "function escape" vendor/magento/framework/Escaper.php
Output:
public function escapeHtml($data, $allowedTags = null)
{
--
private function escapeText(\DOMDocument $domDocument)
{
--
private function escapeAttributeValues(\DOMDocument $domDocument)
{
--
private function escapeAttributeValue($name, $value)
{
--
public function escapeHtmlAttr($string, $escapeSingleQuote = true)
{
--
public function escapeUrl($string)
{
--
public function escapeJs($string)
{
--
public function escapeCss($string)
{
--
public function escapeJsQuote($data, $quote = '\'')
{
--
public function escapeXssInUrl($data)
{
--
private function escapeScriptIdentifiers(string $data): string
{
--
public function escapeQuote($data, $addSlashes = false)
{
3. Form Keys (CSRF Protection)
Form keys are unique tokens generated for forms to validate submissions.
It prevents Cross-Site Request Forgery (CSRF) attacks by ensuring that only authorized users can submit forms.
Example of a Form Key in Magento Forms
We can easily generate and use form key using Magento’s default block class method in our phtml files as below:
<form action="<?php echo $block->getFormAction(); ?>" method="post">
<input name="form_key" type="hidden" value="<?= $block->escapeHtmlAttr($block->getFormKey()) ?>" />
<!-- Other form fields -->
</form>
The code responsible for generating form keys can be found in Magento\Framework\Data\Form\FormKey::getFormKey()
CSRF tokens will be added to all forms automatically by the lib/web/mage/common.js
file.
4. Sanitization
Sanitization involves cleaning and filtering user input to remove or escape malicious characters.
This Prevents SQL injection and other injection attacks by ensuring user input is safe.
Identification
- Use of
stripTags()
,filter_var()
, orhtmlspecialchars()
in PHP. \Magento\Framework\Filter\FilterManager
used for input processing.- Validation rules applied to data models.
How to Sanitize Input in Magento?
Example 1 : Using filter_var()
//Refer : vendor/magento/module-customer/Model/Account/Redirect.php
/**
* Check if referrer is well-formatted
*
* @param string $referrer
* @return bool
*/
private function isReferrerValid(string $referrer) : bool
{
$result = true;
if (preg_match('/^(https?|\/\/)/i', $referrer)) {
if (filter_var($referrer, FILTER_VALIDATE_URL) === false) {
$result = false;
}
}
return $result;
}
Example 2 : Using htmlspecialchars()
$input = '<script>alert("XSS");</script>';
$sanitizedInput = htmlspecialchars($input, ENT_QUOTES, 'UTF-8');

Example 3 : Using filterManager class
use Magento\Framework\Filter\FilterManager;
.........
$filterManager = \Magento\Framework\App\ObjectManager::getInstance()
->get(FilterManager::class);
$input = '<b>Invalid</b> HTML';
$sanitizedInput = $filterManager->stripTags($input);
Example 4 : Using Validation Rules in Data Models
use Magento\Framework\DataObject;
$dataObject = new DataObject();
$dataObject->setData('description', '<script>alert("XSS");</script>');
// Validate the input
$validator = new \Magento\Framework\Validator\DataObject();
$validator->isValid($dataObject);
//Note: This is a simplified example. Magento 2 uses more complex validation rules depending on the module and data type.
5. reCAPTCHA
Adobe Commerce supports the use of Google reCAPTCHA to prevent automated attacks, such as brute-force login attempts or spam form submissions.
reCAPTCHA uses artificial intelligence to distinguish between human and automated interactions.

How to Enable reCAPTCHA in Magento?
- Go to Admin Panel > Stores > Configuration > Security > Google reCAPTCHA.
- Enable it as per your requirement for example login, registration.
Configurations Steps
This adds a Google reCAPTCHA challenge to prevent spam submissions.
6. Input Validation
Adobe Commerce performs input validation checks that user-provided data meets specific rules before it’s accepted.
This helps prevent attacks such as SQL injection and cross-site scripting (XSS) by restricting the types of data that can be input into the system.
Form Validation Rules
In Magento 2, form validation ensures that user input is sanitized and meets specific criteria before submission. Magento provides built-in validation using jQuery Validation and Magento_Ui/js/lib/validation/validator
.
Enabling Form Validation
To enable form validation in Magento 2, add the data-mage-init
attribute to the form element:
<form data-mage-init='{"validation": {}}'>
...
</form>
Ways to add fields to the validation:
1. Using data-validate Attribute
Define validation rules as a JSON object inside the data-validate
attribute:
<input type="text" name="email" data-validate='{"required":true, "email":true}' />
2. Adding Rule Name as an Attribute
Some validation rules can be added directly as attributes:
<input type="text" name="email" required email />
3. Using Rule Name as a Class
You can also apply validation rules by adding class names:
<input type="text" name="phone" class="required-entry validate-phoneStrict" />
4. Adding Validation in data-mage-init
Define validation rules within data-mage-init
at the form level:
<form data-mage-init='{"validation": {}}'>
<input type="text" name="zip" data-validate='{"required":true, "digits":true}' />
</form>
Creating a Custom Validation Rule
To add custom validation, create a JavaScript file and connect it to the page. You can do this using a mixin or a standalone JavaScript file.
Method 1: Adding Custom Rule Using jQuery Validate
Create a new JavaScript file, e.g., view/frontend/web/js/validation-rules.js
:
define([
'jquery',
'mage/translate',
'jquery/validate'
], function ($) {
'use strict';
$.validator.addMethod(
'custom-rule',
function (value, element) {
return value === 'Magento';
},
$.mage.__('The value must be "Magento".')
);
return function () {};
});
Then include this file in your requirejs-config.js
:
var config = {
map: {
'*': {
'validation-rules': 'Vendor_Module/js/validation-rules'
}
}
};
Method 2: Adding Validation to
Magento_Ui/js/lib/validation/validator
Some forms in Magento 2 use Magento_Ui/js/lib/validation/validator
instead of jQuery Validate. To add a validation rule using this method, update your JavaScript file:
define([
'Magento_Ui/js/lib/validation/validator'
], function (validator) {
'use strict';
validator.addRule(
'custom-rule',
function (value) {
return value === 'Magento';
},
$.mage.__('The value must be "Magento".')
);
return validator;
});
Default Form Validation Rules
You can find all by default available rules in below file
vendor/magento/module-ui/view/base/web/js/lib/validation/rules.js
Some of them are :
- max-words: Ensures that the input contains a maximum number of words.
- min-words: Ensures that the input contains a minimum number of words.
- range-words: Ensures that the input contains a number of words within a specified range.
- letters-with-basic-punc: Ensures that the input contains only letters and basic punctuation.
- alphanumeric: Ensures that the input contains only letters, numbers, spaces, or underscores.
- letters-only: Ensures that the input contains only letters.
- no-whitespace: Ensures that the input does not contain any whitespace.
- zip-range: Ensures that the input is a valid zip code within a specified range.
- integer: Ensures that the input is a valid integer.
- vinUS: Ensures that the input is a valid US vehicle identification number (VIN).
These security features are essential for protecting Adobe Commerce stores against common web vulnerabilities and ensuring the security and integrity of customer data.
Server Side/Backend Validators
Data Models (validateBeforeSave
)
Magento allows you to define validation logic in data models by overriding the validateBeforeSave()
method.
namespace Jigar\CustomModule\Model;
use Magento\Framework\Exception\LocalizedException;
use Magento\Framework\Model\AbstractModel;
class CustomModel extends AbstractModel
{
protected function _construct()
{
$this->_init(\Vendor\Module\Model\ResourceModel\CustomModel::class);
}
public function validateBeforeSave()
{
if (strlen($this->getData('custom_field')) < 5) {
throw new LocalizedException(__('Custom field must have at least 5 characters.'));
}
return parent::validateBeforeSave();
}
}
This method is called before the model is saved.If validation fails, a LocalizedException
is thrown, preventing the record from being saved.
Using Magento’s Data Validation Classes
Magento provides \Magento\Framework\Validator\AbstractValidator
for reusable validation logic.
Creating a Custom Validator Class
namespace Jigar\CustomModule\Validator;
use Magento\Framework\Validator\AbstractValidator;
class CustomValidator extends AbstractValidator
{
public function isValid($value)
{
if (strlen($value) < 5) {
$this->_addMessages([__('The field value must have at least 5 characters.')]);
return false;
}
return true;
}
}
Using the Validator in a Model
use Jigar\CustomModule\Validator\CustomValidator;
$validator = new CustomValidator();
if (!$validator->isValid($this->getData('custom_field'))) {
throw new \Magento\Framework\Exception\LocalizedException(
__('Validation failed: %1', implode(', ', $validator->getMessages()))
);
}
Using Data Validators in etc/di.xml
Magento 2 allows defining validation rules in etc/di.xml
to apply validation globally.
<type name="Jigar\CustomModule\Model\CustomModel">
<arguments>
<argument name="validationRules" xsi:type="array">
<item name="custom_field" xsi:type="object">Vendor\Module\Validator\CustomValidator</item>
</argument>
</arguments>
</type>
Using Magento’s Built-in Data Validation
Using Magento’s Built-in Data Validation (\Magento\Framework\Validator
)
Magento has built-in validation classes for various field types:
\Magento\Framework\Validator\EmailAddress
→ Validates email addresses.\Magento\Framework\Validator\StringLength
→ Checks string length.\Magento\Framework\Validator\Digits
→ Ensures numeric input.\Magento\Framework\Validator\Regex
→ Applies regex patterns for validation.
use Magento\Framework\Validator\EmailAddress;
use Magento\Framework\Exception\LocalizedException;
$emailValidator = new EmailAddress();
if (!$emailValidator->isValid($email)) {
throw new LocalizedException(__('Invalid email address.'));
}
Zend/Laminas based validators
Magento 2 uses Zend Framework (Laminas) for various backend validations. Many of Magento’s validation components extend or wrap Zend’s classes for handling form validation, filtering input, and sanitizing data.
use Laminas\Validator\EmailAddress;
use Magento\Framework\Exception\LocalizedException;
$emailValidator = new EmailAddress();
if (!$emailValidator->isValid('test-email.com')) {
throw new LocalizedException(__('Invalid email address.'));
}
Bonus Security Features in Adobe Commerce
- Secure Password Hashing:
Adobe Commerce uses strong algorithms like bcrypt to store passwords securely. No action is needed—it works automatically. - Commerce uses its own strategy for password hashing, based on different native PHP hashing algorithms. Commerce supports multiple algorithms like
MD5
,SHA256
, orArgon 2ID13
. If the Sodium extension is installed (installed by default in PHP 7.3), thenArgon 2ID13
is chosen as the default hashing algorithm. Otherwise,SHA256
is the default. Commerce can use the native PHPpassword_hash
function with Argon 2i algorithm support. - Two-Factor Authentication (2FA):
Go to Stores > Configuration > Security > Two-Factor Authentication to enable 2FA for admin logins. - Security Scanning Tool:
Use the Adobe Commerce Security Scan tool (available in your Adobe Commerce account) to regularly check for vulnerabilities.
Adobe Commerce (Magento) provides powerful security features to protect your store from common threats. By implementing CSP, escaping, form keys, sanitization, reCAPTCHA, and input validation, you can make your store safer for customers.
You may also like,
Securely render Javascript inside Magento 2 template files using PHP
Fastly : How to set basic authentication for a specific page in Magento 2
Very useful tips! Great deep dive—thanks a lot!!