Ошибки безопасности в AI-сгенерированном PHP-коде

WordPress услуги
Нужна помощь с сайтом?
Исправим, настроим или улучшим сайт. Оставьте заявку — подскажем решение.
Оставить заявку
Автор:vkuzyomko

Ошибки безопасности в AI-сгенерированном PHP-коде

Краткий ответ: главная проблема AI-сгенерированного PHP-кода не в том, что он “не работает”, а в том, что он часто работает без нормальной проверки прав, nonce, входных данных, SQL-запросов и вывода HTML. Для WordPress это может закончиться XSS, SQL injection, CSRF, утечкой данных, удалением записей, поломкой админки или взломом сайта.

AI может быстро написать шорткод, AJAX-обработчик, форму, мини-плагин или интеграцию с API. Но он не видит весь сайт: роли пользователей, активные плагины, кеш, WooCommerce, REST API, ограничения хостинга, старый код темы и реальные сценарии атаки. Поэтому код от AI нужно воспринимать как черновик, а не как готовое безопасное решение.

Если плагин или сниппет был написан через ChatGPT, Cursor, Claude или другой AI-инструмент, его лучше проверить до установки на рабочий сайт. Подробный чек-лист по этому сценарию есть в статье как проверить WordPress-плагин, написанный через ChatGPT.

Причина

AI обычно генерирует PHP-код по видимому запросу: “сделай форму”, “сохрани настройку”, “выведи таблицу”, “добавь AJAX”. Он старается выполнить задачу, но не всегда добавляет защитные проверки, которые обязательны для WordPress-разработки.

В WordPress входные данные нужно проверять, очищать и экранировать. Официальная документация WordPress прямо разделяет валидацию, sanitization и escaping: данные нужно проверять до использования и экранировать перед выводом на страницу. :contentReference[oaicite:0]{index=0}

Типичная логическая ошибка AI-кода: он добавляет только “чтобы работало”, но не добавляет “чтобы безопасно работало”. Например, AJAX-запрос сохраняет данные, но не проверяет, кто именно отправил запрос. Или SQL-запрос строится напрямую из $_POST. Или HTML выводится без esc_html() и esc_attr().

Почему это особенно опасно в WordPress

  • Код часто вставляют прямо в functions.php, и ошибка ломает весь сайт.
  • AJAX-обработчики доступны через admin-ajax.php.
  • REST API может открыть лишние данные наружу.
  • Пользователь с ролью Subscriber может получить доступ к действию, которое должно быть только для администратора.
  • WooCommerce, формы, личные кабинеты и CRM-интеграции часто работают с персональными данными.
  • Кеш и security-плагины могут скрывать проблему до момента, когда она уже используется.

Самые частые ошибки безопасности в AI-сгенерированном PHP-коде

Ошибка Что ломает Чем опасно Как исправлять
Нет проверки прав Любой авторизованный пользователь может выполнить действие Удаление данных, изменение настроек, доступ к чужим данным Добавить current_user_can()
Нет nonce Запрос можно отправить со сторонней страницы CSRF-атака Добавить wp_nonce_field(), wp_create_nonce(), check_ajax_referer()
SQL из $_GET или $_POST Запрос к базе становится управляемым извне SQL injection Использовать $wpdb->prepare()
Вывод без escaping В HTML попадает чужой скрипт XSS Использовать esc_html(), esc_attr(), esc_url(), wp_kses_post()
Небезопасная загрузка файлов На сайт можно загрузить опасный файл Вредоносный код, фишинг, заражение Проверять MIME, расширение, размер, права и путь загрузки
Прямое подключение PHP-файлов Файл можно открыть напрямую Ошибки, раскрытие путей, обход логики WordPress Добавить проверку defined( 'ABSPATH' )
Опасный REST endpoint API отдаёт или меняет данные без контроля Утечка данных, изменение настроек Добавить permission_callback

Диагностика

Проверять AI PHP-код нужно не только на синтаксис. Синтаксически правильный код может быть небезопасным. Визуально он выглядит аккуратно, но внутри может отсутствовать проверка прав, nonce или подготовка SQL-запроса.

Мини-чеклист проверки

  • Есть ли в начале файла защита от прямого доступа: defined( 'ABSPATH' ) || exit;?
  • Есть ли проверка прав через current_user_can() перед изменением данных?
  • Есть ли nonce для форм, AJAX и опасных действий?
  • Все ли данные из $_POST, $_GET, $_REQUEST проходят через wp_unslash() и sanitization?
  • Все ли SQL-запросы с переменными идут через $wpdb->prepare()?
  • Все ли данные перед выводом проходят через escaping?
  • Не сохраняются ли токены, пароли и API-ключи в открытом виде?
  • Нет ли в коде eval(), unserialize() для внешних данных, shell_exec(), exec(), base64_decode() без понятной причины?
  • Не доступен ли AJAX для гостей через wp_ajax_nopriv_, если действие должно быть только для авторизованных пользователей?
  • Есть ли обработка ошибок без вывода технических путей и SQL-ошибок пользователю?

Где искать проблемы на сайте

  • wp-content/debug.log — ошибки PHP, warnings, notices, fatal errors.
  • Консоль браузера — JS-ошибки, проблемы AJAX, 403/500.
  • Network в DevTools — ответы admin-ajax.php, REST API, формы.
  • Логи хостинга — PHP fatal error, memory limit, blocked requests.
  • Security-плагин или WAF — заблокированные POST-запросы.
  • База данных — подозрительные значения в wp_options, post meta, user meta.

Если после установки AI-кода сайт начал вести себя нестабильно, стоит отдельно разобрать не только ошибку, но и архитектуру решения. Такая ситуация часто похожа на сценарий, когда проект после вайб-кодинга начал ломаться: отдельные функции работают, но связанная логика сайта постепенно разваливается.

Нужно быстро решить проблему на сайте?

Если не хотите рисковать сайтом и тратить время на эксперименты, можно оставить заявку. Я посмотрю задачу и предложу аккуратное решение.

Оставить заявку

Решение

Безопасное исправление AI PHP-кода начинается с простого правила: нельзя вставлять код на рабочий сайт без проверки входа, прав, базы данных и вывода.

Правильный порядок проверки

  • Сделать резервную копию файлов и базы данных.
  • Проверить код на локальной копии или staging-сайте.
  • Включить логирование ошибок.
  • Проверить все AJAX, REST, формы и сохранение настроек.
  • Проверить роли: Administrator, Editor, Author, Subscriber, Guest.
  • Проверить прямой доступ к PHP-файлам.
  • Проверить SQL-запросы.
  • Проверить вывод HTML на XSS.
  • Проверить работу с кешем и security-плагинами.
  • Только после этого переносить код на рабочий сайт.

Что должно быть в безопасном WordPress-коде

  • ABSPATH в начале PHP-файлов.
  • current_user_can() перед действиями, которые меняют данные.
  • check_ajax_referer() или wp_verify_nonce() для защиты запросов.
  • sanitize_text_field(), sanitize_email(), absint(), sanitize_key() для входных данных.
  • $wpdb->prepare() для SQL.
  • esc_html(), esc_attr(), esc_url() перед выводом.
  • wp_send_json_success() и wp_send_json_error() для AJAX.
  • permission_callback для REST API.

Важно не путать nonce и права доступа. Nonce помогает защититься от подделки запроса, но сам по себе не означает, что пользователь имеет право выполнить действие. Для административных операций нужна отдельная проверка через current_user_can(). В документации и примерах WordPress эти проверки обычно идут вместе: nonce проверяет запрос, capability проверяет полномочия пользователя. :contentReference[oaicite:1]{index=1}

Код

Важно: код ниже влияет на сохранение данных через AJAX. Не вставляйте его вместо существующего обработчика без проверки на копии сайта. Лучше добавлять такие правки в отдельный мини-плагин или в functions.php дочерней темы, если вы понимаете, какой обработчик заменяете.

Плохой пример AI-кода

Такой код может работать, но он небезопасен: нет nonce, нет проверки прав, данные из $_POST используются напрямую.

<?php
add_action( 'wp_ajax_save_ai_title', 'save_ai_title' );

function save_ai_title() {
    global $wpdb;

    $post_id = $_POST['post_id'];
    $title   = $_POST['title'];

    $wpdb->query(
        "UPDATE {$wpdb->posts} SET post_title = '$title' WHERE ID = $post_id"
    );

    echo 'saved';
    wp_die();
}

Что здесь неправильно

  • $_POST['post_id'] не приведён к числу.
  • $_POST['title'] не очищен.
  • SQL-запрос собран строкой.
  • Нет $wpdb->prepare().
  • Нет проверки current_user_can().
  • Нет nonce.
  • Ответ AJAX возвращается через echo, а не через JSON.

Безопаснее

Этот пример показывает базовую структуру безопасного AJAX-обработчика для WordPress.

<?php
defined( 'ABSPATH' ) || exit;

add_action( 'wp_ajax_sc_save_ai_title', 'sc_save_ai_title' );

function sc_save_ai_title() {
    check_ajax_referer( 'sc_save_ai_title_nonce', 'nonce' );

    if ( ! current_user_can( 'edit_posts' ) ) {
        wp_send_json_error(
            array(
                'message' => 'Недостаточно прав для выполнения действия.',
            ),
            403
        );
    }

    $post_id = isset( $_POST['post_id'] ) ? absint( wp_unslash( $_POST['post_id'] ) ) : 0;
    $title   = isset( $_POST['title'] ) ? sanitize_text_field( wp_unslash( $_POST['title'] ) ) : '';

    if ( ! $post_id || '' === $title ) {
        wp_send_json_error(
            array(
                'message' => 'Некорректные данные.',
            ),
            400
        );
    }

    if ( ! current_user_can( 'edit_post', $post_id ) ) {
        wp_send_json_error(
            array(
                'message' => 'Нет доступа к этой записи.',
            ),
            403
        );
    }

    $updated = wp_update_post(
        array(
            'ID'         => $post_id,
            'post_title' => $title,
        ),
        true
    );

    if ( is_wp_error( $updated ) ) {
        wp_send_json_error(
            array(
                'message' => 'Не удалось сохранить заголовок.',
            ),
            500
        );
    }

    wp_send_json_success(
        array(
            'message' => 'Заголовок сохранён.',
            'post_id' => $post_id,
            'title'   => $title,
        )
    );
}

Пример nonce для формы в админке

Куда вставлять: в PHP-шаблон формы настроек, метабокса или административной страницы плагина.

<?php
wp_nonce_field( 'sc_save_ai_title_nonce', 'sc_save_ai_title_nonce_field' );

Проверка nonce в обычной форме

Куда вставлять: в обработчик сохранения формы. Для AJAX чаще используется check_ajax_referer(), для обычной POST-формы — wp_verify_nonce().

<?php
if (
    ! isset( $_POST['sc_save_ai_title_nonce_field'] ) ||
    ! wp_verify_nonce(
        sanitize_text_field( wp_unslash( $_POST['sc_save_ai_title_nonce_field'] ) ),
        'sc_save_ai_title_nonce'
    )
) {
    wp_die( 'Ошибка проверки безопасности.' );
}

Безопасный SQL-запрос через $wpdb

Куда вставлять: в плагин или обработчик, где действительно нужен прямой запрос к базе. Если можно использовать функции WordPress вроде wp_update_post(), update_post_meta(), get_users(), лучше использовать их.

<?php
global $wpdb;

$user_id = isset( $_POST['user_id'] ) ? absint( wp_unslash( $_POST['user_id'] ) ) : 0;

$results = $wpdb->get_results(
    $wpdb->prepare(
        "SELECT ID, user_email FROM {$wpdb->users} WHERE ID = %d",
        $user_id
    )
);

Правильный вывод данных в HTML

Куда вставлять: в шаблон, шорткод, виджет, админ-таблицу или HTML-вывод плагина.

<?php
$title = get_the_title();
$url   = get_permalink();

echo '<a href="' . esc_url( $url ) . '">' . esc_html( $title ) . '</a>';

Результат

После исправления AI PHP-кода сайт должен работать предсказуемее: AJAX-запросы не выполняются без nonce, пользователи без нужных прав не могут менять данные, SQL-запросы не принимают внешние значения как часть команды, а HTML-вывод не пропускает чужой скрипт.

Хороший результат проверки — это не только отсутствие fatal error. Нормальный результат выглядит так:

  • админка открывается без ошибок;
  • debug.log не заполняется новыми предупреждениями;
  • AJAX возвращает понятный JSON;
  • пользователь без прав получает 403;
  • гость не может вызвать закрытое действие;
  • данные в базе сохраняются в ожидаемом формате;
  • вывод на фронтенде не ломает HTML;
  • security-плагин не блокирует нормальные действия;
  • после обновления WordPress код не разваливается.

Дополнительные способы

Включить debug.log

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

Куда вставлять: wp-config.php, выше строки /* That's all, stop editing! */.

define( 'WP_DEBUG', true );
define( 'WP_DEBUG_LOG', true );
define( 'WP_DEBUG_DISPLAY', false );

Проверить активные плагины через WP-CLI

Куда выполнять: SSH/терминал на хостинге, если доступен WP-CLI.

wp plugin list --status=active

Проверить PHP-ошибки после установки AI-кода

  • Откройте страницу, где работает новый код.
  • Повторите действие: отправка формы, сохранение настройки, AJAX-запрос.
  • Проверьте wp-content/debug.log.
  • Проверьте HTTP-ответ в DevTools → Network.
  • Проверьте логи хостинга.

Разделить код на безопасные части

AI часто генерирует один большой кусок кода. Для поддержки и безопасности лучше разделять:

  • регистрацию хуков;
  • проверку прав;
  • получение входных данных;
  • валидацию;
  • работу с базой;
  • HTML-вывод;
  • логирование ошибок.

Если код уже превратился в большой неуправляемый файл, лучше не дописывать новые функции сверху, а провести технический аудит. Для таких случаев подходит услуга доработка проекта после вайб-кодинга, когда нужно не просто “пофиксить одну ошибку”, а привести AI-код в рабочее и безопасное состояние.

Частые ошибки

Ошибка 1: “Nonce есть, значит всё безопасно”

Нет. Nonce не заменяет проверку прав. Он помогает понять, что запрос пришёл из ожидаемого места, но не доказывает, что пользователь имеет право менять настройки, удалять данные или редактировать запись.

Ошибка 2: “Код работает у администратора, значит можно публиковать”

Нужно проверять разные роли. Часто проблема проявляется только у редактора, менеджера магазина, подписчика или гостя.

Ошибка 3: “Данные уже в базе, значит их можно выводить без проверки”

Нельзя. В базе могут быть данные, которые раньше попали туда через форму, импорт, API, старый плагин или ручное редактирование. WordPress рекомендует экранировать данные как можно ближе к месту вывода. :contentReference[oaicite:2]{index=2}

Ошибка 4: “AI сам добавил sanitize_text_field(), этого достаточно”

Не всегда. Для числа нужен absint(), для email — sanitize_email(), для URL — esc_url_raw() при сохранении и esc_url() при выводе, для HTML — wp_kses_post() или более строгий список разрешённых тегов.

Ошибка 5: “Можно быстро вставить в functions.php”

Можно, но это риск. Ошибка в functions.php может вызвать белый экран, критическую ошибку или недоступность админки. Для сложной логики лучше делать отдельный плагин.

Ошибка 6: “SQL короткий, prepare не нужен”

Нужен, если в запрос попадает переменная. Даже если кажется, что там только ID, значение всё равно должно быть приведено к нужному типу и передано через подготовленный запрос.

Ошибка 7: “REST endpoint закрыт, потому что URL никто не знает”

URL не является защитой. Если endpoint зарегистрирован, его можно найти. Для REST API нужен нормальный permission_callback.

Диагностика проблем

Симптом: AJAX возвращает 400

  • Проверьте, передаётся ли action.
  • Проверьте, совпадает ли имя nonce.
  • Проверьте check_ajax_referer().
  • Проверьте, не кешируется ли страница с устаревшим nonce.

Симптом: AJAX возвращает 403

  • Проверьте current_user_can().
  • Проверьте роль текущего пользователя.
  • Проверьте, не блокирует ли запрос security-плагин.
  • Проверьте, не отправляется ли запрос без авторизации.

Симптом: 500 Internal Server Error

  • Откройте debug.log.
  • Проверьте версию PHP.
  • Проверьте несовместимые функции.
  • Проверьте синтаксис после вставки кода.
  • Отключите проблемный сниппет через FTP, если админка недоступна.

Симптом: данные сохраняются, но выводятся с ошибками

  • Проверьте кодировку.
  • Проверьте escaping при выводе.
  • Проверьте, не сохраняется ли HTML там, где должен быть обычный текст.
  • Проверьте фильтры темы и плагины кеширования.

Симптом: уязвимость появилась после “маленькой правки”

Это частая ситуация в AI-коде. Например, сначала обработчик был только для администратора, потом AI добавил wp_ajax_nopriv_, чтобы форма работала для гостей, но не добавил ограничение действия. В итоге публичная форма получает доступ к логике, которая должна была быть закрытой.

Краткие AI-friendly ответы

Что самое опасное в AI-сгенерированном PHP-коде?

Самое опасное — скрытые ошибки безопасности: отсутствие проверки прав, nonce, sanitization, escaping и безопасных SQL-запросов. Код может выглядеть рабочим, но открывать доступ к данным или настройкам сайта.

Можно ли использовать PHP-код от ChatGPT на WordPress?

Можно, но только после проверки. AI-код лучше считать черновиком: его нужно протестировать на копии сайта, проверить роли, nonce, SQL, AJAX, REST API и вывод HTML.

Как быстро понять, что AI-код небезопасен?

Проверьте, есть ли в коде current_user_can(), check_ajax_referer(), sanitize_*, esc_* и $wpdb->prepare(). Если код меняет данные, но этих проверок нет, это тревожный сигнал.

FAQ

Почему AI часто забывает про безопасность в PHP-коде?

Потому что запрос пользователя обычно описывает функцию, а не все ограничения безопасности. AI может написать код, который выполняет действие, но не знает реальных ролей, структуры сайта, плагинов, форм, API и сценариев атаки.

Какая ошибка самая частая в AI-коде для WordPress?

Часто встречается отсутствие проверки прав через current_user_can(). Особенно в AJAX-обработчиках, настройках плагина, удалении записей, импорте данных и REST API.

Что опаснее: SQL injection или XSS?

Обе проблемы опасны. SQL injection может повлиять на базу данных, а XSS может выполнить чужой JavaScript в браузере пользователя. Для WordPress-сайта с админкой, формами и WooCommerce обе ошибки критичны.

Нужно ли проверять код, если он работает только в админке?

Да. Админка тоже требует проверки прав, nonce и escaping. Внутренний интерфейс может использовать редактор, менеджер магазина, контент-менеджер или другой пользователь с неполными правами.

Можно ли вставлять AI-код в functions.php?

Для маленьких проверенных сниппетов — можно, но осторожно. Для AJAX, REST API, интеграций, таблиц базы данных, загрузки файлов и WooCommerce лучше делать отдельный плагин. Так проще отключить код через FTP, если что-то сломается.

Как проверить AI-код без программиста?

Минимально: сделать бэкап, поставить код на копию сайта, включить debug.log, проверить действия под разными ролями, посмотреть ошибки в DevTools и не устанавливать код на рабочий сайт, если есть 403, 500, warnings или непонятные SQL-запросы.

Почему security-плагин не решает проблему полностью?

Security-плагин может заблокировать часть атак, но он не исправляет неправильную логику внутри вашего кода. Если AJAX-обработчик сам разрешает пользователю удалить данные без проверки прав, плагин не всегда поймёт бизнес-логику сайта.

Что делать, если после AI-кода сайт уже сломался?

Отключите проблемный сниппет или плагин через FTP, проверьте debug.log, восстановите доступ к админке, затем разберите код по частям. Не стоит сразу просить AI “починить всё”, лучше сначала найти точную функцию, которая вызвала ошибку.

Вывод

Ошибки безопасности в AI-сгенерированном PHP-коде чаще всего появляются не из-за синтаксиса, а из-за пропущенной логики защиты. Код может красиво выглядеть, успешно сохранять данные и даже решать задачу, но при этом открывать доступ к AJAX, REST API, SQL, настройкам или HTML-выводу.

Для WordPress безопасный минимум такой: проверка прав, nonce, sanitization, validation, prepared SQL, escaping, логирование ошибок и тестирование на копии сайта. AI можно использовать как помощника, но финальную ответственность за безопасность кода должен нести разработчик, который понимает WordPress, PHP и реальные риски конкретного сайта.

Об авторе

vkuzyomko administrator