Экранирование HTML

Введение

В ACF 5.10 появилась важная функция безопасности — экранирование HTML. Впервые представленная как экспериментальная функция в ACF 5.9.6, она гарантирует, что всё HTML-содержимое, выводимое ACF, проходит через wp_kses() функцию WordPress.

Пропуская всё HTML-содержимое через эту основную функцию WordPress, ACF гарантирует, что выводимый им HTML не уязвим для атак типа межсайтового выполнения сценариев.

Важно отметить, что это влияет только на HTML-содержимое, выводимое ACF в панели управления WordPress или в любых формах во внешней части сайта, созданных с помощью acf_form(). Это не влияет на значения полей, загруженные через API-функции, такие как get_field(). Мы не предполагаем, где именно в вашей теме используются значения полей, и поэтому не экранируем их.

Начиная с ACF 6.2.5, экранирование HTML также применяется к значениям, выводимым с помощью шорткода ACF, а начиная с ACF 6.2.7 — к значениям, выводимым с помощью the_field и the_sub_field.

Реализация

Новая система экранирования HTML в ACF добавляет функцию экранирования acf_esc_html(), которая теперь используется во всём плагине везде, где ACF выводит HTML. Эта функция принимает содержимое для вывода и передаёт его функции wp_kses(), возвращая результат. Она также передаёт контекстную строку acf.

/**
 * Очищает текстовое содержимое и удаляет запрещённый HTML.
 *
 * Эта функция имитирует wp_kses_post() с контекстом "acf" для расширения функциональности.
 *
 * @date    16/4/21
 * @since   5.9.6
 *
 * @param   string $string
 * @return  string
 */
function acf_esc_html( $string = '' ) {
    return wp_kses( (string) $string, 'acf' );
}

Пропуская содержимое ACF через wp_kses(), WordPress удаляет все запрещённые HTML-теги и атрибуты тегов. Список разрешённых тегов управляется wp_kses_allowed_html() WordPress. По умолчанию WordPress содержит набор предопределённых разрешённых тегов и их атрибутов. Ниже приведён пример разрешённого тега button и его атрибутов.

[button] => Array
    (
        [disabled] => true
        [name] => true
        [type] => true
        [value] => true
        [aria-describedby] => true
        [aria-details] => true
        [aria-label] => true
        [aria-labelledby] => true
        [aria-hidden] => true
        [class] => true
        [id] => true
        [style] => true
        [title] => true
        [role] => true
        [data-*] => true
    )

Если в содержимом, переданном в wp_kses(), встречается HTML-элемент, отсутствующий в списке разрешённых тегов, или атрибут тега, отсутствующий в списке разрешённых атрибутов, он будет удалён из содержимого.

Настройка

Передача пользовательского контекста acf в wp_kses() позволяет сторонним разработчикам настраивать список разрешённых HTML-тегов и атрибутов. Если вы хотите разрешить определённый HTML-тег или атрибут тега, добавьте его в список разрешённых тегов с помощью фильтра wp_kses_allowed_html в PHP.

Например, этот фильтр в файле functions.php темы или пользовательском плагине позволяет использовать тег iframe:

add_filter( 'wp_kses_allowed_html', 'acf_add_allowed_iframe_tag', 10, 2 );
function acf_add_allowed_iframe_tag( $tags, $context ) {
    if ( $context === 'acf' ) {
        $tags['iframe'] = array(
            'src'             => true,
            'height'          => true,
            'width'           => true,
            'frameborder'     => true,
            'allowfullscreen' => true,
        );
    }

    return $tags;
}

Вот ещё один пример, в котором явно разрешены теги svg и path:

add_filter( 'wp_kses_allowed_html', 'acf_add_allowed_svg_tag', 10, 2 );
function acf_add_allowed_svg_tag( $tags, $context ) {
    if ( $context === 'acf' ) {
        $tags['svg']  = array(
            'xmlns'       => true,
            'fill'        => true,
            'viewbox'     => true,
            'role'        => true,
            'aria-hidden' => true,
            'focusable'   => true,
        );
        $tags['path'] = array(
            'd'    => true,
            'fill' => true,
        );
    }

    return $tags;
}

Важно помнить, что любые добавленные вами разрешённые теги могут повлиять на безопасность. Поэтому разрешайте только теги, которые считаются безопасными. Пример потенциально небезопасного тега — script.

Функциональность WordPress, удаляющая HTML-теги и свойства тегов, которые считает небезопасными, также удаляет небезопасные CSS-свойства, например CSS-свойство display. В некоторых случаях может потребоваться определить и подключить встроенный стиль в панели управления WordPress, чтобы применить такое свойство к информационным сообщениям ACF.

<div style="display: flex">

Поскольку свойство display удаляется, оно будет удалено из тега div.

Как и в случае с отдельными HTML-тегами, отдельные CSS-свойства также можно разрешить с помощью фильтра safe_style_css:

add_filter( 'safe_style_css', 'add_display_to_safe_css', 10, 1 );
function add_display_to_safe_css( $css_attributes ) {
    $css_attributes[] = 'display';

    return $css_attributes;
}

Обратите внимание: хотя это возможно, мы не рекомендуем так делать, поскольку это может подвергнуть ваш сайт риску уязвимостей безопасности.

Экранирование HTML в блоках ACF

В Advanced Custom Fields PRO версии 5.12 и выше WordPress выполняет стандартную очистку wp_kses_post() для блоков ACF у пользователей с правами администратора, у которых отсутствует разрешение unfiltered_html. В некоторых случаях это может привести к удалению HTML из содержимого блока — и, следовательно, к тому, что он не будет выведен во внешней части сайта, — хотя в версиях до 5.12 этот HTML не удалялся.

Если пользователю без разрешения unfiltered_html необходимо вставлять в блоки ACF HTML, который удаляется функцией wp_kses_post(), можно разрешить определённые HTML-теги, используя тот же фильтр wp_kses_allowed_html, что показан выше, но с контекстом «post»:

add_filter( 'wp_kses_allowed_html', 'acf_add_allowed_iframe_tag', 10, 2 );
function acf_add_allowed_iframe_tag( $tags, $context ) {
    if ( $context === 'post' ) {
     $tags['iframe'] = array(
         'src'          => true,
         'height'       => true,
         'width'        => true,
         'frameborder'  => true,
         'allowfullscreen' => true,
     );
    }

    return $tags;
}

Другой вариант — вручную предоставить пользователю разрешение unfiltered_html.

Обновлено: 30.09.2026