Security-стадия этого пайплайна проходит всегда. Почему и как это исправить?
CI-воркфлоу должен гейтить мерж по находкам безопасности, но джоба security зелёная уже три месяца, хотя сканер явно сообщает о критичных находках.
Ограничения: скан остаётся на каждом pull request, а исправление должно обеспечиваться платформенной командой, а не договорённостью.
name: ci
on: [pull_request]
jobs:
security:
runs-on: ubuntu-latest
permissions: write-all
steps:
- uses: actions/checkout@main
- uses: some-vendor/sast-action@v2
continue-on-error: true
with:
api-token: "${{ secrets.SAST_TOKEN }}"
- name: Report
run: echo "scan token ${{ secrets.SAST_TOKEN }} finished" >> report.log
- name: Gate
run: exit 0
Найдите и исправьте дефекты, из-за которых этот гейт бессмысленен.
Скан не может уронить сборку — continue-on-error: true глотает его код возврата, а шаг Gate жёстко делает exit 0. Плюс токен печатается в лог, а write-all работает на незапиненном экшене. Гейтить по реальному коду возврата, убрать echo, ротировать токен, сузить permissions, запинить по SHA.
- ✗Читать зелёную джобу как пройденный гейт, не проверив путь выхода
- ✗Считать
continue-on-errorнастройкой отзывчивости, а не обходом - ✗Удалять утёкший токен из лога вместо ротации самих учётных данных
- →Почему пиннинг экшена на commit SHA важнее пиннинга на тег?
- →Как помешать команде снова добавить
continue-on-errorв джобу security?
Гейт бессмыслен по четырём причинам, и каждая правится отдельно.
continue-on-error: true проглатывает ненулевой код возврата сканера, поэтому шаг всегда «успешен». Финальный шаг Gate с run: exit 0 жёстко зашивает успех независимо от результатов. Вместе они делают джобу зелёной всегда.
Секрет SAST_TOKEN печатается в report.log. Этот токен теперь скомпрометирован: артефакт мог быть скачан, а лог — сохранён. Удаления строки недостаточно — токен нужно ротировать.
permissions: write-all даёт джобе права записи на весь репозиторий, а actions/checkout@main и sast-action@v2 — плавающие ссылки: изменение в апстриме выполнится с этими правами.
name: ci
on: [pull_request]
jobs:
security:
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@8f4b7f8 # запинено по SHA
- uses: some-vendor/sast-action@3a1c9de # запинено по SHA
with:
api-token: "${{ secrets.SAST_TOKEN_ROTATED }}"
- name: Report
run: echo "scan finished" >> report.log
Скан теперь валит джобу собственным кодом возврата, отдельный шаг Gate не нужен. Чтобы команды не вернули continue-on-error, блокирующая проверка должна жить в reusable workflow, которым владеет платформа, и требоваться правилом защиты ветки.