Однажды я добавил SAST-сканер в продовый пайплайн без настройки порогов. Через час в Slack прилетело сорок уведомлений: мёрж заблокирован, двести находок, из которых сто восемьдесят — false positives. Релиз сдвинулся на два дня, а слово «безопасность» стало ругательным в командном чате на три недели.
Это классический антипаттерн DevSecOps: взять инструмент, включить на максимум, сломать процесс. Но проблема глубже, чем просто «неправильно настроили».
⚠️ CI/CD-пайплайн — это вектор атаки
Большинство статей о shift left security останавливаются на тезисе «лови баги раньше». Но за ним прячется неочевидная вещь: незащищённый пайплайн — полноценный инструмент для атаки на всю организацию.
В матрице MITRE ATT&CK задокументированы конкретные техники против CI/CD:
• Poisoned Pipeline Execution — внедрение кода через конфиг пайплайна
• T1195.001 — компрометация зависимостей и инструментов сборки
• T1552.001 — секреты, забытые прямо в конфигах
SolarWinds в 2020-м — не абстрактный кейс. Вредоносный код внедрили в процесс сборки, и он разлетелся через легитимное обновление на тысячи организаций. Это происходит, когда безопасность в пайплайне — просто галочка, а не процесс.
🛠 Минимальный стек, который реально работает
Не нужно прикручивать десять сканеров за один спринт. Четыре инструмента закрывают четыре разных вектора:
1.
Gitleaks — ловит захардкоженные секреты до того, как они осядут в git-истории навсегда2.
Semgrep — SAST с читаемыми правилами, стартуй с p/owasp-top-ten, не с полным аудитом3.
Trivy — CVE в зависимостях и контейнерах, работает с package-lock.json, requirements.txt, Dockerfile4.
OWASP ZAP — DAST на staging, ловит то, что видно только в рантаймеНи один из них не заменяет остальные. Именно поэтому — стек, а не один сканер.
💡 Главный урок после трёх провалов
Начинай с
allow_failure: true. Везде. Сканеры показывают находки, но не блокируют мёрж. Разработчики видят результаты, привыкают к инструменту, доверие не рушится. Убираешь эту настройку в первый день — получаешь бунт. Блокирующие правила вводи постепенно, начиная только с severity: ERROR и только после того, как команда перестала воспринимать сканер как врага.Ещё один контринтуитивный момент: секрет, попавший в git-историю, остаётся там даже после удаления файла.
git log помнит всё. Поэтому Gitleaks запускают с флагом GIT_DEPTH: 0 — иначе shallow clone просто пропустит старые коммиты со всеми их сюрпризами.Полный roadmap с конфигами для GitLab CI и GitHub Actions, примерами правил Semgrep и разбором реальных кейсов — в статье на форуме.
https://codeby.net/threads/devsecops-vnedreniye-s-nulya-kak-vstroit-bezopasnost-v-ci-cd-i-ne-slomat-razrabotku.92943/
