Обновлять WordPress на десятках сайтов скриптом — привычное дело; но между «обновил» и «обновил успешно» есть разница, и в этот раз она стала главной темой релиза. Версия 8.1.0 — security-выпуск: в нём появилась проверка CVE-2026-119977 прямо в инструменте — режим --security только читает версии ядра и говорит, кто уязвим (и годится для мониторинга раз в минуту, потому что не берёт ни блокировку, ни бэкап), а --harden закрывает веб-доступ к wp-content/upgrade/. Заодно обычный прогон --core/--full больше не считает успехом сам факт запуска, а лицензия сменилась на MIT. Ниже — что именно изменилось, как это проверить и где легко ошибиться с кодами выхода: в моих замерах --security без установленного WP-CLI вернул 3, а не 0 и не 1.

TL;DR: что нового и как проверить
--security(только чтение). Читает версию ядра каждого сайта, сравнивает с исправленными выпусками для CVE-2026-119977, печатает вердикт по сайту. Код 1 — есть уязвимый или нечитаемый сайт, код 0 — все на исправленной версии.--harden. Добавляет в.htaccessсайта блок, запрещающий доступ кwp-content/upgrade/; прежний файл один раз копируется в.htaccess.wp-cli-update.bak; для nginx директива печатается в конце прогона, потому что nginx.htaccessне читает.HARDEN_UPGRADE_DIR. Тот же блок можно включать в каждый пишущий режим; по умолчанию выключен, а--security,--healthи--checkотвергают флаг с кодом 2.- Колонка CVE в
--health. Значенияsafe,UPDATEили?, плюс полеcve_2026_119977в JSON Lines — мониторинг видит уязвимость без разбора текста. - Лицензия MIT. Коммерческое использование больше не требует отдельного соглашения.
bash -n Bash_WP-CLI_Update.sh # синтаксис, у меня OK
bash Bash_WP-CLI_Update.sh --help # версия и список режимов
bash Bash_WP-CLI_Update.sh --check # окружение; код 3, если нет wp
bash Bash_WP-CLI_Update.sh --security # код 1, если есть уязвимый сайт
Что нового в 8.1.0
| Что добавлено | Зачем | Ограничение |
|---|---|---|
--security |
найти сайты ниже исправленной версии ядра | только чтение, без блокировки и бэкапа |
--harden |
закрыть wp-content/upgrade/ от веба |
Apache и LiteSpeed; для nginx — директива в выводе |
--harden-upgrade-dir / --no-harden-upgrade-dir |
включать блок в пишущих режимах | по умолчанию 0 |
HARDEN_UPGRADE_DIR |
то же через конфигурацию | отвергается в read-only режимах |
Колонка CVE в --health |
видеть статус в инвентаризации | значения safe / UPDATE / ? |
Поле cve_2026_119977 в JSON Lines |
машинная обработка отчёта | — |
flowchart TB
HOST["хост с несколькими сайтами"] --> SEC["--security: чтение версии ядра"]
SEC --> CMP{"версия ниже исправленной?"}
CMP -- да --> EX1["вердикт UPDATE, код выхода 1"]
CMP -- нет --> EX0["вердикт safe, код 0"]
HOST --> HARD["--harden: блок в .htaccess, копия .bak"]
HARD --> APACHE["Apache и LiteSpeed: RewriteRule F"]
HARD --> NGINX["nginx: директива печатается, .htaccess не читает"]
HOST --> HEALTH["--health: колонка CVE в отчёте"]Отдельно стоит сказать про саму уязвимость, ради которой всё это: CVE-2026-119977 — состояние гонки в штатном обновляторе ядра WordPress, CVSS 8.1, в каталоге эксплуатируемых уязвимостей CISA с 03.11.2026. Затронуты ядра с 4.7 по 7.1.3; исправленные выпуски — 7.1.4, 7.0.8 на ветке 7.0, 6.9.11 на ветке 6.9 и 4.7.39 на ветке 4.7. Для 4.6 и старше исправления нет — такие сайты закрывать или переносить, а не «подождать патч».
Ключевые изменения
Прогон больше не считает себя успешным по факту запуска
Прежняя логика была простой: команда выполнилась — значит, обновили. Теперь --core и --full проверяют результат и, если сайт остался ниже исправленного выпуска, пишут это в журнал с номером CVE и версией, до которой нужно дойти. Разница принципиальная: «обновление не удалось, но ошибки не было» — самый частый способ оставить сайт уязвимым на недели.
Проверка не мешает мониторингу
--security не берёт блокировку и не делает бэкап — поэтому его можно вызывать хоть каждую минуту, из Zabbix или cron, не рискуя наложением на плановое обновление. Это редкое и правильное разделение: у режима чтения своя цена и свой контракт.
Закрытие каталога обновлений
--harden добавляет маркированный блок в .htaccess корня сайта:
# wp-cli-update: harden upgrade dir
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule ^wp-content/upgrade/ - [F,L]
</IfModule>
# /wp-cli-update: harden upgrade dir
Блок идемпотентен: повторный запуск не плодит копии, а прежний .htaccess один раз сохраняется как .htaccess.wp-cli-update.bak. Для nginx в конце прогона печатается строка, которую нужно положить в конфиг сайта:
location ^~ /wp-content/upgrade/ { deny all; }
Лицензия и документация
Лицензия стала MIT — это снимает вопрос «а можно ли в коммерции», который раньше требовал отдельного соглашения. AGENTS.md из большого файла превратился в карту: две непререкаемых правила, таблица файлов, краткий порядок проверки и ссылки на подробные документы (docs/AGENT-INSTALL.md, docs/AGENT-OPERATIONS.md, docs/DEVELOPMENT.md). Практический смысл — инструктаж агента перестал быть простынёй на сотни строк, которую никто не читает целиком.
Замеры и цифры
Снято 08.11.2026 на Windows с Git Bash, архив релиза распакован, сайтов нет — проверял поведение оболочки и коды выхода.
| Что измерено | Значение | Как |
|---|---|---|
SHA-256 архива bash-wp-cli-update-8.1.0.tar.gz |
0d9b268b…58ba, совпал с SHA256SUMS |
Get-FileHash против файла из релиза |
| Размер архива | 183 080 байт | загрузка gh release download |
| Синтаксис | bash -n — чисто |
Git Bash |
Версия в --help |
8.1.0 |
запуск --help |
| Режимов в справке | 25 строк режимов и опций, включая --security, --harden, --doctor, --completion |
разбор вывода --help |
--check без WP-CLI |
сообщение WP-CLI not found … set WP_CLI_PATH, код 3 |
запуск с замером $? |
--security без WP-CLI |
то же сообщение, код 3 | там же |
Главный вывод из замеров — про коды: 3 — это ошибка окружения, а не «сайт уязвим». Если мониторинг ловит только ненулевой код, он будет путать «нет wp-cli на хосте» с «сайт ниже исправленной версии». Различать надо явно: 1 — уязвимый сайт, 2 — неверное сочетание флагов, 3 — окружение.
Чего замеры не показывают: реального обновления сайтов и работы --harden на живом Apache — сайтов под рукой не было, а на Windows-хосте .htaccess ничего не значит. Эти части — по заметкам к релизу и коду; их стоит проверять на своём стенде.
Установка и обновление
flowchart LR
A["скачать архив релиза"] --> B["сверить SHA256SUMS"]
B --> C["распаковать поверх прежней копии"]
C --> D["--check: окружение и сайты"]
D --> E{"код 0?"}
E -- "3" --> F["нет WP-CLI или путь не тот"]
E -- "0" --> G["--security: кто уязвим"]
G --> H["--core или --full: обновление ядра"]
H --> I["--harden: закрыть каталог обновлений"]# архив из релиза и сверка контрольной суммы
gh release download v8.1.0 -R paulmann/Bash_WP-CLI_Update -D ./rel
cd ./rel && sha256sum -c SHA256SUMS
# распаковать поверх прежней копии и проверить окружение
tar -xzf bash-wp-cli-update-8.1.0.tar.gz -C /opt/wp-update --strip-components=1
/opt/wp-update/Bash_WP-CLI_Update.sh --check
| Шаг | Команда | Ожидание |
|---|---|---|
| Синтаксис и версия | bash -n … && … --help |
без ошибок, 8.1.0 в первой строке |
| Окружение | --check |
код 0; код 3 — нет WP-CLI или путей |
| Кто уязвим | --security |
код 1 при наличии сайта ниже исправленной версии |
| Обновление | --core или --full |
в журнале нет строк «остался ниже» |
| Защита каталога | --harden |
блок в .htaccess, рядом .htaccess.wp-cli-update.bak |
| Проверка | --health |
колонка CVE без UPDATE |
Проверка после обновления
flowchart TD
R["запуск"] --> Z{"код выхода"}
Z -- 0 --> OK["всё в порядке: обновлено или уже безопасно"]
Z -- 1 --> WARN["есть сайт ниже исправленной версии"]
Z -- 2 --> USE["неверное сочетание флагов"]
Z -- 3 --> ENV["окружение: нет wp, нет путей"]Четыре проверки, каждая с однозначным результатом:
--helpпоказывает8.1.0— значит, запускается новая копия, а не старая изPATH.--checkдаёт код 0. Код 3 — не поломка сайта, а отсутствиеwpили неверныйWP_CLI_PATH.--securityдаёт код 0 на всех сайтах группы. Код 1 — есть работа: смотреть, какой сайт и какую версию ядра он держит.--healthв JSON Lines содержитcve_2026_119977со значениемsafe— если поле есть, мониторинг можно строить на нём, не разбирая текст.
Совместимость
| Что | Состояние |
|---|---|
| Лицензия | MIT (было — отдельное соглашение для коммерции); архив legacy/ сохраняет прежнюю |
| Ядра WordPress | инструмент работает с 4.7+; для уязвимости исправления есть на ветках 7.1, 7.0, 6.9, 4.7 |
| Чего нет в 8.1.0 | изменений менеджера, поисковика, режимов, опций, ключей конфигурации и кодов выхода |
| 8.1.1 | только тесты: починен рекордер в test_fleet.sh; поведение инструмента не менялось |
| nginx | .htaccess не читается: нужна директива location ^~ /wp-content/upgrade/ { deny all; } |
Версия 8.1.1, вышедшая через полтора часа, — чисто тестовый патч. Причина в заметках описана честно: фальшивый wp в тестах собирал строку четырьмя вызовами printf внутри перенаправленной группы, при -j 5 записи накладывались, и проверка «ожидалось 5 вызовов» видела 4. Запись собрана в переменную и печатается одним printf. Ни одного изменения в самом инструменте эта версия не несёт.
Подводные камни
- Код 3 читают как «уязвим». Проверено: без WP-CLI и
--check, и--securityвозвращают 3. Уязвимый сайт — это 1. Если алерт не различает 1 и 3, дежурный будет искать дыру там, где на хосте просто не установленwp. --hardenне работает на nginx. Он честно печатает директиву, но применять её нужно в конфиге сайта;.htaccessтам игнорируется.HARDEN_UPGRADE_DIRв read-only режимах отвергается с кодом 2. Это не ошибка конфигурации, а защита от «включил везде не глядя».--securityне обновляет. Он только смотрит: ни блокировки, ни бэкапа, ни изменений. Ждать от него лечения уязвимости нельзя.- 4.6 и старше исправления не получат. Если такие сайты в парке есть, обсуждать надо не «когда обновим», а перенос или закрытие.
.htaccessкопируется один раз. Второй прогон не перезапишет.bak— при ручных правках помнить, что рядом лежит не свежая копия.- Колонка CVE со значением
?. Это «версию прочитать не удалось», а не «безопасно»: тот же код 1 в--security, но в таблице он выглядит безобидно.
FAQ
Что именно исправлено в 8.1.0?
Это выпуск под CVE-2026-119977: добавлены проверка уязвимых ядер (--security), закрытие каталога обновлений (--harden), колонка CVE в --health, а режимы обновления теперь сообщают, если сайт остался ниже исправленной версии.
Можно ли звать --security каждую минуту?
Да, это режим только для чтения: ни блокировки, ни бэкапа он не берёт, поэтому безопасен для мониторинга и как проверка перед обновлением.
Почему --security вернул 3, а не 1?
Потому что 3 — ошибка окружения: не найден wp. Код 1 означает, что найден уязвимый или нечитаемый сайт. Различать их нужно в самом мониторинге, иначе тревога будет ложной.
Нужен ли --harden, если сайт за nginx?
Да, но применять надо не .htaccess, а напечатанную директиву: location ^~ /wp-content/upgrade/ { deny all; }.
Что изменилось в лицензии?
Проект перешёл на MIT: коммерческое использование больше не требует отдельного соглашения. Тексты прежней лицензии остались в архиве legacy/.
Чем отличается 8.1.1?
Только тестами: исправлен рекордер вызовов, который при параллельном прогоне терял записи. Ни режимы, ни опции, ни коды выхода не менялись.
Итог
8.1.0 — редкий случай, когда релиз про безопасность не добавляет «ещё одну защиту», а закрывает разрыв между «команда отработала» и «сайт действительно обновлён». Полезнее всего здесь два режима чтения: --security для мониторинга и колонка CVE в --health для инвентаризации, плюс --harden для тех, кто на Apache и LiteSpeed. Главная практическая ловушка — коды выхода: 1 и 3 означают совершенно разные вещи, и в моих замерах без WP-CLI обе команды дали именно 3.
Цитата: Успешное обновление — это не код возврата команды, а версия ядра на сайте после неё.
Связанные материалы
- Bash WP-CLI Update: обзор продукта — основная статья: режимы, установка, обновление парка сайтов.
- Релиз v8.1.0 — заметки:
--security,--harden, MIT, CVE-2026-119977. - Репозиторий проекта — код, тесты, документация для агентов.
- PHP Shield: файрвол для PHP — другой подход к защите веб-приложения на уровне запросов.
- github-agent: гигиена репозитория одной командой — инструмент, которым проверялась документация этого релиза.
LLM Summary
- Тема:
Bash WP-CLI Update8.1.0 — security-релиз скрипта обслуживания парка WordPress: проверка уязвимых ядер, закрытие каталога обновлений, MIT. - Уязвимость:
CVE-2026-119977, состояние гонки в штатном обновляторе ядра, CVSS 8.1, в CISA KEV с 03.11.2026; затронуты 4.7–7.1.3, исправлены 7.1.4, 7.0.8, 6.9.11, 4.7.39, для 4.6 и старше исправления нет. - Новые режимы:
--security(только чтение, вердикт по сайту, код 1 при уязвимом или нечитаемом сайте, код 0 если все безопасны) и--harden(маркированный блок в.htaccess, копия.htaccess.wp-cli-update.bak, директива для nginx печатается). - Конфигурация:
--harden-upgrade-dir/--no-harden-upgrade-dir, ключHARDEN_UPGRADE_DIR(по умолчанию 0); в--security,--healthи--checkфлаг отвергается с кодом 2. - Отчёты: колонка CVE в
--health(safe/UPDATE/?) и полеcve_2026_119977в JSON Lines. - Замеры 08.11.2026: SHA-256 архива совпал с
SHA256SUMS(0d9b268b…58ba), архив 183 080 байт,bash -nчисто,--helpпечатает8.1.0; без WP-CLI--checkи--securityвозвращают 3. - Лицензия: MIT; тексты прежней лицензии остались в
legacy/. - 8.1.1: только тесты — исправлен рекордер вызовов, терявший записи при
-j 5. - Не проверялось: реальное обновление сайтов и работа
--hardenна живом Apache — сайтов и веб-сервера под рукой не было. - Ссылки: https://github.com/paulmann/Bash_WP-CLI_Update/releases/tag/v8.1.0, https://sysadministrator.ru/bash-wp-cli-update/
Промт для агента (установка и настройка)
Готовый промт для AI-агента: скопируйте блок целиком. Шаги собраны по AGENTS.md репозитория (две непререкаемых правила, порядок проверки) и по выводу --help версии 8.1.0.
Задача: обновить Bash WP-CLI Update до 8.1.0 и проверить, есть ли на хосте сайты, уязвимые по CVE-2026-119977.
Материалы:
- репозиторий: https://github.com/paulmann/Bash_WP-CLI_Update
- контракт для агентов: https://github.com/paulmann/Bash_WP-CLI_Update/blob/main/AGENTS.md
- релиз: https://github.com/paulmann/Bash_WP-CLI_Update/releases/tag/v8.1.0
Шаг 1. Скачать архив релиза и сверить контрольную сумму:
gh release download v8.1.0 -R paulmann/Bash_WP-CLI_Update -D ./rel
cd ./rel && sha256sum -c SHA256SUMS
Шаг 2. Распаковать поверх прежней копии, проверить синтаксис и версию:
bash -n Bash_WP-CLI_Update.sh
bash Bash_WP-CLI_Update.sh --help # первая строка должна содержать 8.1.0
Шаг 3. Проверить окружение: bash Bash_WP-CLI_Update.sh --check
# код 0 — окружение в порядке; код 3 — нет wp или неверный WP_CLI_PATH
Шаг 4. Найти уязвимые сайты: bash Bash_WP-CLI_Update.sh --security
# код 0 — все на исправленной версии; код 1 — есть сайт ниже исправленной или версия не читается
Шаг 5. Обновить ядро и схему: --core (или --full), затем повторить --security до кода 0.
Шаг 6. Закрыть каталог обновлений: --harden, для nginx применить напечатанную директиву location ^~ /wp-content/upgrade/ { deny all; }
Шаг 7. Проверить инвентаризацию: --health, колонка CVE не должна показывать UPDATE или ?.
Запрещено:
- считать код 3 признаком уязвимости: это ошибка окружения, а не состояние сайта;
- ждать от --security лечения: он только читает и ничего не меняет;
- включать HARDEN_UPGRADE_DIR в режимах --security, --health, --check: флаг отвергается с кодом 2;
- оставлять сайты на ядрах 4.6 и старше в расчёте на исправление: его не будет;
- считать, что --harden работает на nginx: там нужна директива в конфиге сайта.
Что считать успехом: --check даёт 0, --security даёт 0, --health показывает safe по всем сайтам, каталог обновлений закрыт на уровне веб-сервера.