Перейти к содержанию

Последовательности экранирования

Почти каждая ошибка экранирования — это ошибка контекста, а не ошибка синтаксиса. Символ известен — кавычка, обратный слеш, амперсанд — и неясно, какое из шести конфликтующих правил применяется там, где строка вот-вот попадёт.

Поэтому эта таблица организована по контексту, а не по символу. Одна и та же кавычка удвоена в ячейке CSV, экранирована обратным слешем в JSON, превращена в " в HTML и полностью оставлена в одиночных кавычках оболочки. Четыре строки, четыре правила, один символ.

Наиболее важное правило — то, к которому люди обращаются в последнюю очередь: экранируйте на границе, через которую переходит значение, и экранируйте его один раз. Текст, экранированный дважды — & в исходнике страницы, \\n в выходном файле — это подпись значения, которое прошло через два кодировщика, каждый из которых предполагал, что он первый.

Строки JSON

10

JSON допускает точно эти экранирования. Буквальный перевод строки или вкладка внутри строки недействительны.

ЭкранированиеОзначаетКогда вам это нужноВ контексте
\""Двойная кавычка внутри строки"say \"hi\""
\\\Буквальный обратный слешПричина, по которой пути Windows ломают JSON."C:\\dir"
\//Косая черта — необязательноЗаконно, но ненужно; привычка от встраивания JSON в теги <script>."a\/b"
\nU+000AПодача ленты"line\nline"
\rU+000DВозврат каретки
\tU+0009Вкладка
\bU+0008Возврат на рассчёт
\fU+000CФорма подачи
\u00e9éЛюбой символ по его четырёхзначному коду точки"caf\u00e9"
\ud83d\ude00😀Символ выше U+FFFF, как пара суррогатаJSON не имеет форма \u{…}, поэтому астральные символы занимают два экранирования.

Строки JavaScript

10

Надмножество JSON, плюс экранирования буквального шаблона.

ЭкранированиеОзначаетКогда вам это нужноВ контексте
\''Одиночная кавычка внутри строки одиночных кавычек
\""Двойная кавычка внутри строки двойных кавычек
\``Обратная кавычка внутри буквального шаблона
\${${Буквальный ${ внутри буквального шаблонаБез обратного слеша он запускает интерполяцию.
\nU+000AПодача ленты
\xe9éСимвол по двум шестнадцатеричным цифрам, до U+00FF
\u00e9éСимвол по четырём шестнадцатеричным цифрам
\u{1f600}😀Любая кодовая точка, однако долгоНе требует пары суррогата, в отличие от четырёхзначной формы.
\0U+0000Нулевой символ
\u2028U+2028Разделитель линииДопустимо в строке JS, но не в JSON — классический перерыв JSONP.

Текст HTML и атрибуты

8

Только & и < строго должны быть экранированы в тексте; кавычки имеют значение внутри атрибутов.

ЭкранированиеОзначаетКогда вам это нужноВ контексте
&amp;&АмперсандЭкранируйте этот сначала, иначе каждое другое экранирование удвоится.
&lt;<Знак «меньше», поэтому оно не начинает тег
&gt;>Знак «больше»
&quot;"Двойная кавычка внутри атрибута
&#39;'Одиночная кавычка внутри атрибута&apos; также работает в HTML5, но числовая форма безопасна везде.
&nbsp;U+00A0Неразрывное пространство
&#233;éЛюбой символ по десятичному коду точки
&#xE9;éЛюбой символ по шестнадцатеричному коду точки

URL-адреса (процентное кодирование)

9

Какие символы требуют экранирования, зависит от части URL, в которой они находятся.

ЭкранированиеОзначаетКогда вам это нужноВ контексте
%20 Пробел, допустимый везде в URL
+ Пробел, но только в строке запроса, кодированной в формеВ сегменте пути это буквальный знак плюс.
%25%Буквальный знак процентаПропустите это, и значение декодируется дважды.
%2F/Косая черта внутри одного сегмента пути
%3F?Знак вопроса внутри значения
%26&Амперсанд внутри значения параметра
%3D=Знак равно внутри значения параметра
%23#Хеш, поэтому он не запускает фрагмент
%C3%A9éСимвол не-ASCII как его UTF-8 байтыОдин символ может стать двумя, тремя или четырьмя группами процентов.

Поля CSV

5

RFC 4180: цитируйте поле, затем удвойте любую кавычку внутри него. Обратные слеши ничего не значат.

ЭкранированиеОзначаетКогда вам это нужноВ контексте
"""Кавычка внутри цитируемого поля — удвойте её"say ""hi"""
"a,b",Поле, содержащее разделитель — цитируйте поле
"a b"U+000AПоле, содержащее разрыв строки — цитируйте поле
" a" Сохранить начальные или конечные пробелыБез кавычек, многие парсеры их обрезают.
'=SUM(A1)=Остановите электронную таблицу, выполняя ячейку как формулуПрименяется к значениям, начинающимся с =, +, - или @. Это инъекция формулы.

Литералы и идентификаторы SQL

6

Прочитайте их; не пишите их. Вместо этого используйте параметризованные запросы.

ЭкранированиеОзначаетКогда вам это нужноВ контексте
'''Кавычка внутри строкового литерала — удвойте её'O''Brien'
"order"orderЗарезервированное слово, используемое как имя столбцаДвойные кавычки — стандарт; SQL Server использует [скобки].
`order`orderТо же самое в MySQL и MariaDB
\%%Буквальный % внутри шаблона LIKE
\__Буквальный _ внутри шаблона LIKE
$tag$ … $tag$'Кодирование PostgreSQL доллара — абсолютно нет экранирования внутриПолезно для тел кода, где удвоение каждой кавычки нечитаемо.

Аргументы оболочки

6

Одиночные кавычки буквальны, двойные кавычки по-прежнему расширяют переменные.

ЭкранированиеОзначаетКогда вам это нужноВ контексте
'…'$ ` \Всё внутри буквальноСамое безопасное цитирование есть — но оно не может содержать одиночную кавычку.
"…"* ? spaceГлобусы и пробелы безопасны, переменные по-прежнему расширяютсяAlways quote variables: "$var", never bare $var.
\ Пробел в неприводимом имени файла
\$$Буквальный знак доллара внутри двойных кавычек
\``Буквальная обратная кавычка, а не замена команды
'\'''Одиночная кавычка внутри одиночных кавычекЗакрыть, уйти, переоткрыть — нет способа вложить его напрямую.

FAQ

Почему мой JSON ломается на пути к файлу Windows?
Потому что обратный слеш запускает последовательность экранирования в строке JSON, поэтому C:\dir читается как C, затем недействительное экранирование. Написанное правильно значение — "C:\\dir" — два обратных слеша в файле, один в разобранной строке. Прямые слеши работают на Windows и избегают проблемы полностью.
Верно ли %20 или + для пробела в URL?
Оба, в разных местах. %20 правильно везде в URL. Знак плюса обозначает пробел только внутри строки запроса, закодированной как application/x-www-form-urlencoded — в сегменте пути это буквальный плюс. Используйте %20, когда вы не уверены, потому что он правильный везде.
Как поместить кавычку внутри поля CSV?
Оберните поле в кавычки и удвойте внутреннюю: "say ""hi""". Это RFC 4180, и это причина, по которой CSV, полный удвоенных кавычек, не повреждается. Обратный слеш ничего не означает для соответствующего парсера CSV.
Для чего нужен начальный апостроф в строке формулы CSV?
Это обезвреживает инъекцию формулы. Ячейка, начинающаяся с =, +, - или @, выполняется как формула при открытии в электронной таблице, поэтому значение, такое как =SUM(A1) из ненадёжного источника, становится кодом. Добавление апострофа в начало заставляет ячейку читаться как текст.
Должен ли я экранировать SQL вручную?
Нет. Удвоение кавычки задокументировано здесь, потому что вам нужно читать экранированный SQL, а не писать его — используйте параметризованные запросы и позвольте драйверу обрабатывать значение. Ручное экранирование — это то, откуда приходит SQL-инъекция, и её безопасная версия при проверке не существует.