build: закрыть обходы релизного гейта тестов и проверять весь граф npm
Два гейта сборки проверяли не то, что обещали.
1. pnpm audit проверял production-подграф вместо всего lock-графа.
Гейт запускался с --prod под обоснованием «devDependencies в артефакт не
попадают». Для frontend build tooling это неверно по существу: vite и
rollup действительно не копируются на production-сервер как node_modules,
но они ИСПОЛНЯЮТСЯ на build-машине, читают наши исходники и порождают тот
самый production-бандл, который уезжает в артефакт.
Это не гипотеза: DOM clobbering в Rollup затрагивал именно генерируемый
бандл, и `pnpm audit --prod` его не показывал — по всему графу тот же
прогон дал 33 предупреждения против нуля. Критерий приёмки №47 в docs/11
формулировал «по всему графу» правильно ещё до того, как это стало правдой
в коде.
На текущем lock-файле полный граф на пороге high чист.
2. SKIP_TESTS позволял собрать production-артефакт без тестов.
Переменная была описана как «аварийное отключение тестов; для
release-сборок недопустимо». Недопустимость держалась исключительно на этой
фразе: ни metadata, ни финальная приёмка архива не проверяли, что тесты
запускались. То есть
SKIP_TESTS=true ./tools/build/build.sh
доходила до конца и выдавала обычный tarball с build_profile=production и
dependency_security_gate=true — артефакт, по которому невозможно отличить
проверенную сборку от непроверенной.
Глушила она при этом не только тесты: под тем же флагом пропускались
`tsc --noEmit` для оркестратора и `go vet` для админки, то есть проверка
типов и статический анализ того самого кода, который уезжает в production.
Выбран тот же строгий вариант, что уже принят для проверки зависимостей:
обхода нет. Готовый пакет объявляет tests_gate=true в metadata, и это
утверждение опирается на результат — обе функции прогона выставляют свой
флаг только после успешного завершения, а write_metadata отказывается
писать метаданные, если хотя бы один не подтверждён.
Приёмка закрепляет оба инварианта: --prod не может вернуться в гейт, SKIP_TESTS
не может вернуться ни в один модуль сборки и ни в README/docs, tests_gate=true
обязателен в metadata, а утверждение о прогоне обязано следовать за прогоном.
This commit is contained in:
@@ -23,9 +23,24 @@ set -euo pipefail
|
||||
# govulncheck — анализ достижимости: уязвимость считается только если до неё
|
||||
# есть путь вызова из нашего кода. Покрывает и stdlib, то есть
|
||||
# ровно то, что версия Go привносит в production-бинарь;
|
||||
# pnpm audit — граф npm без анализа достижимости, поэтому ограничен
|
||||
# production-зависимостями и порогом PNPM_AUDIT_LEVEL:
|
||||
# devDependencies в артефакт не попадают.
|
||||
# pnpm audit — ВЕСЬ lock-граф frontend без анализа достижимости, с порогом
|
||||
# PNPM_AUDIT_LEVEL.
|
||||
#
|
||||
# Про «весь граф» отдельно, потому что здесь стояло `--prod` с обоснованием
|
||||
# «devDependencies в артефакт не попадают».
|
||||
#
|
||||
# Для frontend build tooling это обоснование неверно по существу. Да, vite и
|
||||
# rollup не копируются на production-сервер как node_modules. Но они
|
||||
# ИСПОЛНЯЮТСЯ на build-машине, читают наши исходники и ПОРОЖДАЮТ тот самый
|
||||
# production-бандл, который уезжает в артефакт. Уязвимость в них — это
|
||||
# уязвимость в том, что мы выпускаем.
|
||||
#
|
||||
# Это не гипотеза. GHSA по DOM clobbering в Rollup затрагивал именно
|
||||
# генерируемый бандл, то есть уезжал в production, — и `pnpm audit --prod` его
|
||||
# не показывал. По всему графу тот же прогон дал 33 предупреждения против нуля.
|
||||
#
|
||||
# docs/11 формулировал критерий приёмки правильно («pnpm audit по всему графу»)
|
||||
# ещё до того, как это стало правдой в коде.
|
||||
|
||||
# Аварийного выхода у этого шага НЕТ, и это осознанное решение.
|
||||
#
|
||||
@@ -95,15 +110,15 @@ $report"
|
||||
esac
|
||||
}
|
||||
|
||||
# Анализ production-зависимостей frontend.
|
||||
# Анализ всего lock-графа frontend, включая build tooling.
|
||||
run_frontend_vulnerability_gate() {
|
||||
local ui_src="${UI_SRC:-apps}"
|
||||
local report status
|
||||
|
||||
log_step "Security: pnpm audit --prod (порог ${PNPM_AUDIT_LEVEL})"
|
||||
log_step "Security: pnpm audit по всему графу (порог ${PNPM_AUDIT_LEVEL})"
|
||||
|
||||
set +e
|
||||
report="$(cd "$ui_src/frontend" && "$PNPM_BIN" audit --prod --audit-level "$PNPM_AUDIT_LEVEL" 2>&1)"
|
||||
report="$(cd "$ui_src/frontend" && "$PNPM_BIN" audit --audit-level "$PNPM_AUDIT_LEVEL" 2>&1)"
|
||||
status=$?
|
||||
set -e
|
||||
|
||||
|
||||
Reference in New Issue
Block a user