Пошаговая настройка GitLab CI
Как подключить ScanSuite к GitLab: токен, переменные, раннер и шаблон, разбор результатов, проверка merge request и готовые рецепты.
Задание GitLab запускает CI-клиент ScanSuite из образа appsec4u/scansuite-ci:1. Клиент собирает в архив файлы под контролем Git, отправляет их на сервер ScanSuite, запускает сканирование и ждёт результата. Сканирует сам сервер, так что раннеру не нужны ни сканеры, ни много памяти. После сканирования клиент проверяет результат по порогу качества (quality gate): по умолчанию сборку останавливает любая уязвимость уровня High или Critical и любой секрет, которого у продукта раньше не было. Затем клиент сохраняет отчёты и завершает работу:
| Итог | Что вы получаете |
|---|---|
| Задание прошло | Блокирующих уязвимостей нет. Найденное всё равно сохраняется в ScanSuite. |
| Задание завершилось с ошибкой | В журнале перечислены все блокирующие уязвимости и секреты. На вкладке Tests конвейера и в merge request они показаны как проваленные тесты. |
| Отчёты | scansuite-junit.xml (отчёт о тестах для GitLab), scansuite.json (сводка) и scansuite.sarif. GitLab хранит их как артефакты задания 30 дней. |
Что понадобится
| Что | Требования |
|---|---|
| ScanSuite | Команда на сервере ScanSuite Teams, в которой у вас роль «Администратор команды»: она нужна, чтобы завести сервисный аккаунт. |
| Продукт | Продукт ScanSuite, в который будут попадать уязвимости. Его можно создать заранее на странице «Продукты» или поручить это первому запуску конвейера (см. «Рецепты»). |
| GitLab | Роль Maintainer в проекте: без неё не изменить настройки CI/CD и правила слияния. |
| Раннер | Раннер GitLab с исполнителем Docker, который выполняет задания без тегов, может скачать образ appsec4u/scansuite-ci:1 с Docker Hub и видит сервер ScanSuite по HTTPS. Подойдут и общие раннеры GitLab.com, если сервер доступен из интернета. |
Шаг 1. Выпустите токен в ScanSuite
Конвейер обращается к ScanSuite не с паролем сотрудника, а с токеном сервисного аккаунта. Такой аккаунт принадлежит команде и не перестанет работать, когда кто-то из неё уйдёт.
- 01Откройте страницу «Команды»
В боковом меню, в разделе «Администрирование», выберите «Команды» и перейдите на вкладку «Люди». Нужная карточка — «Автоматизация и API-токены».
- 02Заведите сервисный аккаунт
В поле «Новый сервисный аккаунт» укажите имя, например gitlab-ci, в поле «Роль» выберите «Оператор» и нажмите «Создать». Роль по умолчанию, «Читатель», запускать сканирования не может.
- 03Выпустите токен
У нового аккаунта нажмите «Новый токен». Задайте имя и срок действия — не больше 90 дней, — оставьте набор прав «Конвейер CI» и нажмите «Создать токен».
- 04Скопируйте токен
Он показывается только один раз и понадобится на шаге 2. Если токен потерялся, отзовите его и выпустите новый.


В набор «Конвейер CI» входит только то, что нужно конвейеру: запуск и остановка сканирований, просмотр сканирований, уязвимостей, продуктов и найденных учётных данных, загрузка отчётов и создание продуктов. В списке у каждого токена видны его права и срок действия. За 14 дней до истечения срока клиент начинает предупреждать об этом в журнале задания.
Шаг 2. Добавьте переменные CI/CD в GitLab
В проекте GitLab откройте Settings → CI/CD → Variables и добавьте через Add variable четыре переменные:
| Key | Value | Видимость и флажки |
|---|---|---|
| SCANSUITE_URL | Адрес сервера ScanSuite, например https://scansuite.example.com | Visible |
| SCANSUITE_TEAM | Короткое имя команды. Его видно на странице «Моя учётная запись» (меню пользователя): ссылка на команду заканчивается на ?team=<короткое имя>. | Visible |
| SCANSUITE_PRODUCT | Название продукта — точно так, как на странице «Продукты». Вместо него можно задать номер продукта в SCANSUITE_PRODUCT_ID. | Visible |
| SCANSUITE_TOKEN | Токен из шага 1. | Masked, без флажка Protect variable |

GitLab ставит флажок Protect variable по умолчанию. Защищённая переменная доступна только конвейерам защищённых веток и тегов, поэтому любой merge request из обычной ветки завершится ошибкой Set SCANSUITE_TOKEN ... с кодом выхода 3. Оставляйте токен защищённым, только если все конвейеры со сканированием запускаются на защищённых ветках или тегах.

Переменные проекта действуют во всех заданиях и имеют приоритет над переменными из .gitlab-ci.yml. Это важно, если какое-то задание должно отправлять результаты в другой продукт: см. Монорепозиторий.
Шаг 3. Проверьте раннер
Раннеры, доступные проекту, перечислены в Settings → CI/CD → Runners. Хотя бы один из них должен быть в состоянии Online, работать с исполнителем Docker и выполнять задания без тегов. Если ваши раннеры берут только задания с тегами, добавьте тег скрытому заданию шаблона в своём .gitlab-ci.yml:
.scansuite:
tags: [docker]
Шаг 4. Подключите шаблон
Сервер ScanSuite раздаёт шаблон для GitLab CI, который всегда соответствует версии сервера. Добавьте его в файл .gitlab-ci.yml в корне репозитория (если файла нет, создайте его), указав адрес своего сервера:
include:
- remote: 'https://scansuite.example.com/ci/scansuite.gitlab-ci.yml'Шаблон добавляет в стадию test два задания:
| Задание | Когда запускается | Что сканирует |
|---|---|---|
| scansuite-merge-request | В каждом merge request | quick-classic (правила Semgrep, без AI) — только файлы, изменённые в merge request |
| scansuite-default-branch | При каждом push в основную ветку | standard-ai (AI SAST с анализом достижимости, поиск секретов с проверкой через AI, проверка зависимостей) — весь репозиторий |
Закоммитьте файл в основную ветку — этот push и запустит первый конвейер.
Если в конвейере уже объявлены стадии, оставьте их и добавьте к ним test: задания шаблона работают в этой стадии. Если подключать файл по внешней ссылке не хочется, скопируйте содержимое шаблона по тому же адресу в свой репозиторий. AI SAST считает подключение внешнего файла без фиксации версии уязвимостью уровня Medium.
Шаг 5. Посмотрите результат в GitLab
Откройте Build → Pipelines и выберите последний конвейер. В тестовом прогоне задание основной ветки работало три минуты и, как и ожидалось на таком приложении, завершилось с ошибкой:

Откройте задание с ошибкой. В конце журнала написано, что нашло сканирование и почему задание не прошло:

| Строка журнала | Смысл |
|---|---|
| Scan jfzyghvb (#95) Queued … Finished after 160s | Идентификатор сканирования: по нему сканирование можно найти в ScanSuite. |
| Open findings in this scan: Critical 1, High 2, … | Сколько уязвимостей нашло сканирование. |
| BLOCKING [Critical] OS command injection -- app.py::host (Reachable) | Уязвимость, из-за которой проверка не пройдена: файл, место в коде и причина. По строке на каждую. |
| BLOCKING [Secret] github_token -- …/settings.py#L3 | Блокирующий секрет и ссылка на файл в GitLab. |
| Quality gate FAILED: 3 blocking finding(s), 1 blocking secret(s) | Итог проверки. |
| Exit code 1: the quality gate failed … | Причина ошибки. Ниже GitLab всегда пишет exit code 1, а настоящий код выхода — в этой строке (см. «Если что-то пошло не так»). |
На вкладке Tests конвейера каждая блокирующая уязвимость показана как проваленный тест, с разбивкой по заданиям. Отчёты JSON и SARIF можно скачать на странице задания, в блоке Job artifacts: кнопки Download и Browse.

Шаг 6. Найдите уязвимости в ScanSuite
Сканирование из конвейера ничем не отличается от обычного сканирования продукта. Оно появляется в «Истории сканирований» под именем архива проекта, например scansuite-ci-e2e.zip. На странице сканирования видно, что оно изменило, а по кнопке «Показать уязвимости» открывается список с уровнем, местом в коде и достижимостью. Разбирайте уязвимости как обычно. Порог учитывает только уязвимости в статусах Open и In Progress, так что уязвимость, закрытая как ложное срабатывание или принятый риск, следующий конвейер уже не остановит.


Каждая уязвимость ссылается на файл и строку в GitLab на том коммите, который сканировался: клиент передаёт адрес репозитория и коммит вместе с архивом.
Проверка merge request
Задание с ошибкой не даст слить изменения, только если это включено в проекте: Settings → Merge requests → Merge checks → Pipelines must succeed.

Тогда merge request показывает блокирующие уязвимости как проваленные тесты, а слияние становится доступно только после успешного конвейера:

Сканирование для merge request стоит выбирать внимательно. В тесте ветка добавила pickle.loads для данных из запроса и eval для параметра запроса:
| Сканирование | Результат |
|---|---|
| quick-classic (по умолчанию в шаблоне) | Прошло примерно за минуту: правила не сработали ни на одной из этих строк. |
| quick-ai | Примерно за 30 секунд нашло две уязвимости Critical — небезопасную десериализацию и выполнение кода через eval — и остановило merge request. |
Если в команде подключён AI, проверяйте merge request набором quick-ai. Оба набора сканируют только изменённые файлы. Поиску секретов и проверке зависимостей нужен весь репозиторий, поэтому они выполняются на основной ветке.
include:
- remote: 'https://scansuite.example.com/ci/scansuite.gitlab-ci.yml'
scansuite-merge-request:
variables:
SCANSUITE_PROFILE: quick-aiЕсли merge request затрагивает только исключённые файлы (например, при SCANSUITE_EXTRA_ARGS: --exclude docs/*), задание сразу проходит: сканировать нечего.
Какой набор и когда запускать
| Когда | Без AI | С AI | Сколько заняло в тесте |
|---|---|---|---|
| Merge request | quick-classic | quick-ai | Около минуты |
| Основная ветка | standard-classic | standard-ai | 3–4 минуты |
| По ночам или перед релизом | full-classic | full-ai | full-ai: от 7 до 25 минут, на большой кодовой базе намного дольше |
Набор задаётся в задании переменной SCANSUITE_PROFILE. На учебном приложении standard-ai остановил сборку из-за трёх уязвимостей (инъекций и обхода каталогов, все с подтверждённой достижимостью) и одного проверенного секрета. standard-classic нашёл 15 блокирующих уязвимостей: те же инъекции, на которые сработало сразу несколько правил Semgrep, и уязвимые версии pyyaml, flask, jinja2 и requests.
Настройка порога
Каждый параметр задаётся переменной — в задании или для всего проекта:
| Переменная | По умолчанию | Когда задание завершается с ошибкой |
|---|---|---|
| SCANSUITE_FAIL_ON_SEVERITY | high | Минимальный уровень, при котором задание завершается с ошибкой. Значение none отключает проверку. |
| SCANSUITE_MAX | Сколько уязвимостей каждого уровня допустимо, например high=0,medium=10. | |
| SCANSUITE_BLOCK_CLASS | Классы уязвимостей, которые блокируют сборку при любом уровне, например sql_injection,command_injection. | |
| SCANSUITE_MIN_CONFIDENCE | any | reachable: учитываются только уязвимости, достижимость которых подтвердил AI, и уязвимости с известным эксплойтом. |
| SCANSUITE_FAIL_ON_SECRETS | new | new — секреты, которых у продукта раньше не было; all — все секреты; none — секреты не учитываются. |
В тесте задание с SCANSUITE_FAIL_ON_SEVERITY: critical и SCANSUITE_BLOCK_CLASS: sql_injection,command_injection,code_injection всё равно остановилось на SQL-инъекциях и внедрении команд уровня High. В журнале у них вместо High severity стоит blocked class sql_injection.
Для первого сканирования продукта все секреты новые. Поэтому задание, которое создаёт продукт, или первое сканирование уже существующего репозитория остановится на давно закоммиченных секретах. Разберите их в ScanSuite или на первое время задайте SCANSUITE_FAIL_ON_SECRETS: none.
Рецепты
Каждый рецепт — это задание, которое нужно добавить в .gitlab-ci.yml после include. Задания наследуют скрытое задание шаблона .scansuite, а вместе с ним образ, отчёты и артефакты.
DAST и сканирование образов
Эти задания запускают на более поздней стадии — после развёртывания и сборки образа. Благодаря needs: [] они выполняются, даже если статическое сканирование уже остановило сборку. Без этого GitLab их пропустит, причём именно тогда, когда они нужнее всего.
stages: [test, verify]
scansuite-dast:
extends: .scansuite
stage: verify
needs: []
variables:
SCANSUITE_SCAN_TYPE: dast
SCANSUITE_TARGETS: https://staging.example.com
SCANSUITE_PROFILE: quick
SCANSUITE_FAIL_ON_SEVERITY: critical
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH && $CI_PIPELINE_SOURCE != "merge_request_event"
scansuite-image:
extends: .scansuite
stage: verify
needs: []
variables:
SCANSUITE_SCAN_TYPE: infra
SCANSUITE_TARGETS: registry.example.com/shop/api:$CI_COMMIT_SHORT_SHA
SCANSUITE_EXTRA_ARGS: --scanners docker_image_scan
SCANSUITE_FAIL_ON_SEVERITY: critical
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH && $CI_PIPELINE_SOURCE != "merge_request_event"Цели DAST и сканирования инфраструктуры должны быть разрешены команде: страница «Команды», вкладка «Сканирование», карточки «Веб-цели» и «Инфраструктурные цели». Если цели нет в списке, задание завершится с кодом 3 ещё до начала сканирования. В тесте сканирование образа python:3.8-slim нашло 9 уязвимостей уровня Critical и остановило сборку, а DAST прошёл: найденные им проблемы уровней High и Medium ниже порога critical.
Ночное полное сканирование
Создайте расписание в Build → Pipeline schedules и добавьте задание. Набор full-ai анализирует историю Git, поэтому задание скачивает её целиком.
scansuite-nightly:
extends: .scansuite
variables:
SCANSUITE_PROFILE: full-ai
GIT_DEPTH: "0"
SCANSUITE_MAX: high=0,critical=0,medium=10
SCANSUITE_TIMEOUT: "14400"
rules:
- if: $CI_PIPELINE_SOURCE == "schedule"
SCANSUITE_MAX задаёт допустимое количество: ни одной уязвимости High и Critical и не больше десяти Medium. В тесте ночное сканирование нашло 2 уязвимости Critical, 3 High и 2 Medium: пять из них, High и Critical, остановили сборку, а две Medium уложились в лимит.
SCANSUITE_TIMEOUT позволяет клиенту ждать до четырёх часов, но GitLab прервёт задание раньше — по собственному таймауту. По умолчанию это час; значение видно в поле Timeout на странице задания. Для длинных сканирований добавьте в задание timeout: 4h (ограничение самого раннера при этом сохраняется).
Проверка релиза по тегу
Эта проверка строже, чем для merge request: учитываются только достижимые уязвимости, но начиная с уровня Medium, и все секреты продукта, а полный отчёт сохраняется вместе с релизом.
stages: [test, release]
scansuite-release:
extends: .scansuite
stage: release
variables:
SCANSUITE_PROFILE: standard-ai
SCANSUITE_FAIL_ON_SEVERITY: medium
SCANSUITE_MIN_CONFIDENCE: reachable
SCANSUITE_FAIL_ON_SECRETS: all
SCANSUITE_EXTRA_ARGS: --report-zip scansuite-report.zip
artifacts:
when: always
paths: [scansuite-report.zip, scansuite.json]
rules:
- if: $CI_COMMIT_TAGСоздайте тег в Code → Tags или отправьте его в репозиторий. В тесте проверка релиза не прошла из-за шести достижимых уязвимостей уровня Medium и выше — инъекций, открытого для всего интернета доступа по SSH в main.tf и подключения внешнего файла без фиксации версии, — а также из-за закоммиченного токена GitHub: при all он учитывается, хотя прежние сканирования его уже находили. Архив с отчётом остаётся в артефактах задания:

Монорепозиторий: свой продукт для каждого сервиса
Для каждой папки сервиса запускается отдельное задание, и каждое пишет в свой продукт, который создаётся при первом запуске. Продукт передаётся ключом, а не переменной: переменная SCANSUITE_PRODUCT в задании уступит переменной проекта из шага 2, и все сервисы окажутся в одном продукте.
scansuite-services:
extends: .scansuite
parallel:
matrix:
- SERVICE: [payments, web]
variables:
SCANSUITE_PROFILE: quick-classic
SCANSUITE_CHANGED_ONLY: "1"
SCANSUITE_EXTRA_ARGS: --source-dir services/$SERVICE --product-name $SERVICE --create-product
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"GitLab запускает по заданию на сервис: scansuite-services: [payments] и scansuite-services: [web]. При первом запуске в журнале появляется строка Created product …, а затем каждый журнал начинается с названия продукта, куда уходят результаты (в тесте продукты назывались e2e-$SERVICE: Team default, product e2e-payments (#10)). В тесте merge request менял оба сервиса: задание payments остановилось на SQL-инъекции, web прошло, и merge request был заблокирован из-за одного сервиса.
Продукт создаётся при первом запуске
Для нового репозитория продукт может создать сам конвейер — заводить его в ScanSuite вручную не нужно (набор прав «Конвейер CI» это позволяет). Задайте ключи в скрытом задании, и их унаследуют все задания:
.scansuite:
variables:
SCANSUITE_EXTRA_ARGS: --product-name $CI_PROJECT_NAME --create-productПервый запуск пишет в журнал Created product scansuite-ci-e2e (#12), следующие уже находят этот продукт. Если задание задаёт собственный SCANSUITE_EXTRA_ARGS, это значение заменяется, поэтому повторите в нём оба ключа. Можно и иначе: добавьте в переменные проекта SCANSUITE_CREATE_PRODUCT со значением 1 рядом с SCANSUITE_PRODUCT.
Сначала без блокировок
Пока команда привыкает к результатам, сканирование может публиковать отчёты, никогда не останавливая конвейер:
scansuite-default-branch:
variables:
SCANSUITE_FAIL_ON_SEVERITY: none
SCANSUITE_FAIL_ON_SECRETS: noneЕсли сборка должна останавливаться на уязвимостях, но не из-за недоступности ScanSuite, вместо этого добавьте SCANSUITE_EXTRA_ARGS: --soft-fail. В тесте при недоступном сервере клиент около минуты пытался подключиться, затем записал в журнал --soft-fail: exiting 0 instead of 5, и задание прошло.
Большой репозиторий: клонирование на стороне сервера
По умолчанию раннер загружает рабочую копию на сервер. Большой репозиторий удобнее отдать серверу ScanSuite: он сам склонирует ветку, а с --mode incremental будет сканировать только то, что изменилось после его последнего сканирования этой ветки.
- 01Создайте пару ключей для ScanSuite
Например: ssh-keygen -t ed25519 -N "" -f scansuite-deploy. Не используйте эту пару ни для чего другого.
- 02Добавьте открытый ключ в GitLab
В проекте откройте Settings → Repository → Deploy keys → Add new key и вставьте содержимое scansuite-deploy.pub. Права на запись не нужны.
- 03Добавьте закрытый ключ в ScanSuite
На странице «Команды» откройте вкладку «Сканирование», карточку «Доступ к репозиториям» и в поле «Ключ SSH для клонирования» вставьте содержимое scansuite-deploy. Нажмите «Сохранить», а сам файл удалите.
- 04Добавьте задание
Укажите SSH-адрес проекта. Если SSH в GitLab работает не на порту 22, используйте адрес вида ssh:// с номером порта, как в примере ниже.

scansuite-incremental:
extends: .scansuite
variables:
SCANSUITE_SOURCE: git
SCANSUITE_GIT_URL: ssh://git@gitlab.example.com:2222/$CI_PROJECT_PATH.git
SCANSUITE_PROFILE: standard-ai
SCANSUITE_EXTRA_ARGS: --mode incremental
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCHИсточник в журнале выглядит так: ssh://…/scansuite-ci-e2e.git @ main (the server clones the branch head, not necessarily …). Сервер берёт ветку в том состоянии, в каком она была в момент запуска сканирования, а оно может быть новее коммита, на котором запущен конвейер. В тесте первый запуск склонировал и просканировал всю ветку (и остановился на заложенных уязвимостях), а второй записал Nothing to scan: … no new commits since successful scan hzyljnog и прошёл за 13 секунд.
При первом клонировании сервер запоминает SSH-ключ хоста Git-сервера и в дальнейшем отказывается работать, если ключ изменился. Если GitLab переустановили или перенесли и ключ хоста поменялся, клонирование будет завершаться ошибкой could not resolve the remote revision: @@@@…, пока администратор ScanSuite не удалит старый ключ из файла /var/tmp/scansuite/git-auth/known_hosts в контейнере worker.
Без шаблона
Если подключать внешний файл нельзя, напишите задание сами. Entrypoint образа нужно очистить: GitLab запускает в контейнере собственную оболочку.
scansuite:
stage: test
image:
name: appsec4u/scansuite-ci:1
entrypoint: [""]
variables:
GIT_DEPTH: "50"
script:
- scansuite-ci --profile quick-classic --changed-only --junit scansuite-junit.xml --sarif scansuite.sarif
artifacts:
when: always
reports: { junit: scansuite-junit.xml }
paths: [scansuite.sarif]
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"Отдельные AI-сканирования
Ключи --scanners и --options заменяют сканеры и параметры, заданные набором. Передавайте их через SCANSUITE_EXTRA_ARGS:
# AI SAST со всеми возможностями
scansuite-ai-sast:
extends: .scansuite
variables:
GIT_DEPTH: "0"
SCANSUITE_EXTRA_ARGS: >-
--scanners mlsast
--options mlsast_reachability,mlsast_security_architecture,mlsast_boundary_hunt,mlsast_git_history
# Зависимости: сборку останавливают только CVE, достижимость которых подтвердил AI
scansuite-ai-deps:
extends: .scansuite
variables:
SCANSUITE_MIN_CONFIDENCE: reachable
SCANSUITE_EXTRA_ARGS: --scanners dep_checks --options dep_checks_reachability
# Секреты: сборку останавливают только проверенные секреты, которых у продукта ещё не было
scansuite-ai-secrets:
extends: .scansuite
variables:
SCANSUITE_FAIL_ON_SEVERITY: none
SCANSUITE_FAIL_ON_SECRETS: new
SCANSUITE_EXTRA_ARGS: --scanners secrets --options secrets_aiВ тесте проверка зависимостей прошла: в requirements.txt указаны версии с известными CVE (классическое сканирование на них остановилось), но AI не нашёл ни одной, до которой можно добраться из кода приложения. Поиск секретов тоже прошёл: единственный проверенный секрет продукт уже знал, а при new учитываются только секреты, которых у продукта раньше не было.
AI SAST со всеми возможностями просканировал учебное приложение меньше чем за четыре минуты и нашёл две уязвимости Critical и три High в app.py и в обоих сервисах. Для каждой указано место в коде, через которое до неё можно добраться.
Собственный удостоверяющий центр
Если сертификат сервера ScanSuite выпущен вашим собственным удостоверяющим центром, добавьте его сертификат в репозиторий и укажите путь к нему. Без этого клиент выводит предупреждение и работает без проверки сертификата; с SCANSUITE_STRICT_TLS: "1" он вместо этого завершится с ошибкой.
.scansuite:
variables:
SCANSUITE_CA_BUNDLE: ci/corp-root.pemЕсли что-то пошло не так
Какой бы ни была причина, GitLab завершает задание с ошибкой строкой ERROR: Job failed: exit code 1. Настоящий код выхода — в последней строке клиента, которая начинается с [scansuite]:

| Код выхода | Значение | Что делать |
|---|---|---|
| 0 | Проверка пройдена или сканировать нечего. | — |
| 1 | Проверка не пройдена: есть блокирующие уязвимости или секреты. | Посмотрите строки BLOCKING или вкладку Tests, исправьте код или разберите уязвимости в ScanSuite. |
| 2 | Сканирование завершилось ошибкой, было отменено или отклонено сервером, или один из сканеров не отработал. | Сканер указан в журнале; подробности — на странице сканирования в ScanSuite. |
| 3 | Ошибка настройки: ключ, токен, права, цель или сертификат. | Что исправить, написано в строке перед кодом выхода. |
| 4 | Не дождались окончания сканирования (по умолчанию ждём 2 часа). | Увеличьте SCANSUITE_TIMEOUT (в секундах). |
| 5 | ScanSuite недоступен. | Проверьте, что раннер может подключиться к SCANSUITE_URL. |
| Сообщение или признак | Причина и решение |
|---|---|
| Set SCANSUITE_TOKEN ... | Токен не попал в задание: переменная защищена (Protected), а конвейер запущен на незащищённой ветке (см. шаг 2), или переменной нет вовсе. |
| Product 'X' was not found in team Y | Значение SCANSUITE_PRODUCT не совпадает с названием продукта, или указана не та команда. Чтобы продукт создавался автоматически, добавьте --create-product. |
| The API token lacks permission(s): ... | Токен выпущен без набора «Конвейер CI», или у сервисного аккаунта роль «Читатель». Выпустите новый токен. |
| Cannot run on this server: openvas: ... | Этот сканер не настроен для вашей команды. Где его настроить, сказано в сообщении. |
| Уязвимости попадают не в тот продукт | В задании задана переменная SCANSUITE_PRODUCT, но переменная проекта важнее. Передайте --product-name через SCANSUITE_EXTRA_ARGS. |
| --changed-only: no base to compare with | Конвейер запущен не для merge request, или в клоне нет целевой ветки. В этом случае сканируется весь репозиторий. |
| This is a shallow clone, so Git history analysis sees only ... | Для full-ai и других сканирований с анализом истории Git задайте GIT_DEPTH: "0". |
| Задание поздней стадии пропущено | Сканирование на одной из предыдущих стадий завершилось с ошибкой. Добавьте заданию needs: []. |
Отмена задания отменяет и сканирование. Если отменить конвейер в GitLab, клиент успеет остановить сканирование в ScanSuite (Cancelled scan zbepcxtn (pipeline interrupted)), и забытый конвейер не будет занимать сканер. А вот если клиент сам перестал ждать (SCANSUITE_TIMEOUT, код выхода 4), сканирование продолжится — чтобы его отменить, добавьте --cancel-on-timeout.
Полное описание ключей, в том числе авторизации для DAST, параметров сканирования инфраструктуры и других систем CI, — в разделе CI/CD и автоматизация.
Проверено: 2026-10-03