Skip to content

Commit 8fab448

Browse files
committed
minor #17897 [Validator] Document the new NoSuspiciousCharacters constraint (MatTheCat)
This PR was squashed before being merged into the 6.3 branch. Discussion ---------- [Validator] Document the new `NoSuspiciousCharacters` constraint Feature PR: symfony/symfony#49300 Commits ------- e4d1b82 [Validator] Document the new `NoSuspiciousCharacters` constraint
2 parents da2abef + e4d1b82 commit 8fab448

File tree

3 files changed

+159
-0
lines changed

3 files changed

+159
-0
lines changed

reference/constraints.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ Validation Constraints Reference
7979
constraints/Traverse
8080
constraints/CssColor
8181
constraints/Cascade
82+
constraints/NoSuspiciousCharacters
8283

8384
The Validator is designed to validate objects against *constraints*.
8485
In real life, a constraint could be: "The cake must not be burned". In
Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
NoSuspiciousCharacters
2+
======================
3+
4+
.. versionadded:: 6.3
5+
6+
The ``NoSuspiciousCharacters`` constraint was introduced in Symfony 6.3.
7+
8+
..
9+
10+
Because Unicode contains such a large number of characters and incorporates
11+
the varied writing systems of the world, incorrect usage can expose programs
12+
or systems to possible security attacks.
13+
14+
`Unicode® Technical Standard #39`_
15+
16+
"symfony.com" and "ѕymfony.com" look similar, but the latter actually starts with a
17+
`cyrillic small letter dze`_. It could make a user think they'll navigate to Symfony's
18+
website, whereas it would be somewhere else.
19+
This is a kind of `spoofing attack`_ (called "IDN homograph attack"). It tries to
20+
identify something as something else to exploit the resulting confusion.
21+
This is why it is recommended to check user-submitted, public-facing identifiers for
22+
suspicious characters in order to prevent such attacks.
23+
24+
This constraint ensures strings or :phpclass:`Stringable`s do not include any
25+
suspicious characters. As it leverages PHP's :phpclass:`Spoofchecker`, the intl
26+
extension must be enabled to use it.
27+
28+
========== ===================================================================
29+
Applies to :ref:`property or method <validation-property-target>`
30+
Class :class:`Symfony\\Component\\Validator\\Constraints\\NoSuspiciousCharacters`
31+
Validator :class:`Symfony\\Component\\Validator\\Constraints\\NoSuspiciousCharactersValidator`
32+
========== ===================================================================
33+
34+
Basic Usage
35+
-----------
36+
37+
The following constraint will ensures a username cannot be spoofed by using many
38+
detection mechanisms:
39+
40+
.. configuration-block::
41+
42+
.. code-block:: php-attributes
43+
44+
// src/Entity/User.php
45+
namespace App\Entity;
46+
47+
use Symfony\Component\Validator\Constraints as Assert;
48+
49+
class User
50+
{
51+
#[Assert\NoSuspiciousCharacters]
52+
private string $username;
53+
}
54+
55+
.. code-block:: yaml
56+
57+
# config/validator/validation.yaml
58+
App\Entity\User:
59+
properties:
60+
username:
61+
- NoSuspiciousCharacters: ~
62+
63+
.. code-block:: xml
64+
65+
<!-- config/validator/validation.xml -->
66+
<?xml version="1.0" encoding="UTF-8" ?>
67+
<constraint-mapping xmlns="http://symfony.com/schema/dic/constraint-mapping"
68+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
69+
xsi:schemaLocation="http://symfony.com/schema/dic/constraint-mapping https://symfony.com/schema/dic/constraint-mapping/constraint-mapping-1.0.xsd">
70+
71+
<class name="App\Entity\User">
72+
<property name="username">
73+
<constraint name="NoSuspiciousCharacters"/>
74+
</property>
75+
</class>
76+
</constraint-mapping>
77+
78+
.. code-block:: php
79+
80+
// src/Entity/User.php
81+
namespace App\Entity;
82+
83+
use Symfony\Component\Validator\Constraints as Assert;
84+
use Symfony\Component\Validator\Mapping\ClassMetadata;
85+
86+
class User
87+
{
88+
public static function loadValidatorMetadata(ClassMetadata $metadata)
89+
{
90+
$metadata->addPropertyConstraint('username', new Assert\NoSuspiciousCharacters());
91+
}
92+
}
93+
94+
.. include:: /reference/constraints/_empty-values-are-valid.rst.inc
95+
96+
Options
97+
-------
98+
99+
``checks``
100+
~~~~~~~~~~
101+
102+
**type**: ``integer`` **default**: all
103+
104+
This option is a bitmask of the checks you want to perform on the string:
105+
106+
* ``NoSuspiciousCharacters::CHECK_INVISIBLE`` checks for the presence of invisible characters such as zero-width spaces, or character sequences that are likely not to display, such as multiple occurrences of the same non-spacing mark.
107+
* ``NoSuspiciousCharacters::CHECK_MIXED_NUMBERS`` (usable with ICU 58 or higher) checks for numbers from different numbering systems.
108+
* ``NoSuspiciousCharacters::CHECK_HIDDEN_OVERLAY`` (usable with ICU 62 or higher) checks for combining characters hidden in their preceding one.
109+
110+
You can also configure additional requirements using :ref:`locales <locales>` and
111+
:ref:`restrictionLevel <restrictionlevel>`.
112+
113+
``locales``
114+
~~~~~~~~~~~
115+
116+
**type**: ``array`` **default**: :ref:`framework.enabled_locales <reference-enabled-locales>`
117+
118+
Restrict the string's characters to those normally used with the associated languages.
119+
120+
For example, the character "π" would be considered suspicious if you restricted the
121+
locale to "English", because the Greek script is not associated with it.
122+
123+
Passing an empty array, or configuring :ref:`restrictionLevel <restrictionlevel>` to
124+
``NoSuspiciousCharacters::RESTRICTION_LEVEL_NONE`` will disable this requirement.
125+
126+
``restrictionLevel``
127+
~~~~~~~~~~~~~~~~~~~~
128+
129+
**type**: ``integer`` **default**: ``NoSuspiciousCharacters::RESTRICTION_LEVEL_MODERATE`` on ICU >= 58, otherwise ``NoSuspiciousCharacters::RESTRICTION_LEVEL_SINGLE_SCRIPT``
130+
131+
Configures the set of acceptable characters for the validated string through a
132+
specified "level":
133+
134+
* ``NoSuspiciousCharacters::RESTRICTION_LEVEL_MINIMAL`` requires the string's characters to match :ref:`the configured locales <locales>`'.
135+
* ``NoSuspiciousCharacters::RESTRICTION_LEVEL_MODERATE`` also requires the string to be `covered`_ by Latin and any one other `Recommended`_ or `Limited Use`_ script, except Cyrillic, Greek, and Cherokee.
136+
* ``NoSuspiciousCharacters::RESTRICTION_LEVEL_HIGH`` (usable with ICU 58 or higher) also requires the string to be `covered`_ by any of the following sets of scripts:
137+
138+
* Latin + Han + Bopomofo (or equivalently: Latn + Hanb)
139+
* Latin + Han + Hiragana + Katakana (or equivalently: Latn + Jpan)
140+
* Latin + Han + Hangul (or equivalently: Latn + Kore)
141+
* ``NoSuspiciousCharacters::RESTRICTION_LEVEL_SINGLE_SCRIPT`` also requires the string to be `single-script`_.
142+
* ``NoSuspiciousCharacters::RESTRICTION_LEVEL_ASCII`` (usable with ICU 58 or higher) also requires the string's characters to be in the ASCII range.
143+
144+
You can accept all characters by setting this option to
145+
``NoSuspiciousCharacters::RESTRICTION_LEVEL_NONE``.
146+
147+
.. include:: /reference/constraints/_groups-option.rst.inc
148+
149+
.. include:: /reference/constraints/_payload-option.rst.inc
150+
151+
.. _`Unicode® Technical Standard #39`: https://unicode.org/reports/tr39/
152+
.. _`cyrillic small letter dze`: https://graphemica.com/%D1%95
153+
.. _`spoofing attack`: https://en.wikipedia.org/wiki/Spoofing_attack
154+
.. _`single-script`: https://unicode.org/reports/tr39/#def-single-script
155+
.. _`covered`: https://unicode.org/reports/tr39/#def-cover
156+
.. _`Recommended`: https://www.unicode.org/reports/tr31/#Table_Recommended_Scripts
157+
.. _`Limited Use`: https://www.unicode.org/reports/tr31/#Table_Limited_Use_Scripts

reference/constraints/map.rst.inc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ String Constraints
2929
* :doc:`UserPassword </reference/constraints/UserPassword>`
3030
* :doc:`NotCompromisedPassword </reference/constraints/NotCompromisedPassword>`
3131
* :doc:`CssColor </reference/constraints/CssColor>`
32+
* :doc:`NoSuspiciousCharacters </reference/constraints/NoSuspiciousCharacters>`
3233

3334
Comparison Constraints
3435
~~~~~~~~~~~~~~~~~~~~~~

0 commit comments

Comments
 (0)