Опирается на правила:
R-SEC-FIND-1…R-SEC-FIND-3иR-SEC-FIND-X1из Security Style Guide → раздел 6. Реакция на findings.
Важно знать
- CRITICAL → сборка падает, hotfix < 24 часов.
- HIGH → сборка падает, патч ≤ 2 недели (текущий спринт).
- MEDIUM → отчёт, патч ≤ 30 дней.
- LOW → игнорим, не отображаем в dashboard.
- Suppression без
until=— не считается suppressed, считается долгом.- GitHub Code Scanning / SARIF — единый dashboard через GitHub Security tab.
- «Не уверен, эксплуатируется ли» — добавляй suppression с обоснованием. Молчание = долг.
Findings — это входящий поток работы для security backlog. UCP формулирует SLA per severity, чтобы команда не тонула в noise (LOW) и быстро реагировала на критичное. Без SLA findings накапливаются, dashboard становится «море красного», команда привыкает.
Severity → SLA
R-SEC-FIND-1: четыре уровня, четыре действия.
| Severity | Инструменты | SLA на исправление | Блокирует |
|---|---|---|---|
| CRITICAL | любой | < 24 часа | Сборка падает, hotfix immediate |
| HIGH | SpotBugs / FindSecBugs / Trivy / DepCheck | ≤ 2 недели (sprint) | Сборка падает |
| MEDIUM | SpotBugs / FindSecBugs / Trivy | ≤ 30 дней | Отчёт, не блокирует |
| LOW | любой | — | Игнор, не отображается |
CRITICAL — hotfix < 24 часа
Примеры:
- Active exploit известный (Log4Shell-уровень).
- Hardcoded prod credential leaked.
- Critical CVE с public PoC в active runtime dependency.
Action plan:
- Алерт security-team немедленно.
- Создание hotfix branch.
- Применение patch / temporary mitigation.
- Deploy в проде в течение 24 часов.
- Post-mortem.
HIGH — текущий спринт
Примеры:
- CVE с CVSS 7.0-8.9 в зависимости.
- SQLi pattern в новом коде.
- Missing
@PreAuthorizeна admin endpoint.
Action plan:
- Создание ticket с label
security/high. - Включение в текущий спринт.
- Прогон через PR review до merge.
- Deploy с next release.
MEDIUM — 30 дней
Примеры:
- CVE с CVSS 4.0-6.9.
- SpotBugs
EI_EXPOSE_REPв нелегаси коде. - Trivy finding в OS package без active exploit.
Action plan:
- Ticket с label
security/medium. - Включение в один из следующих спринтов.
- Если за 30 дней не fixed — auto-escalate до HIGH.
LOW — игнор
Примеры:
- SpotBugs style findings (
URF_UNREAD_FIELD). - Theoretical CVE без known exploitation vector.
- Trivy finding в test dependency.
Не отображаем в дашборде. Не создаём ticket. Не тратим время.
Suppressions имеют срок
R-SEC-FIND-2: until= обязателен везде.
<!-- dependency-check-suppressions.xml -->
<suppress until="2026-08-01Z">
<notes>CVE-2024-XXXX: false positive в transitive dep, не в runtime path. Ждём fix в upstream library 2.5.</notes>
<cve>CVE-2024-XXXX</cve>
</suppress>
<!-- spotbugs-exclude.xml -->
<Match>
<!-- justify: legacy code path, refactor запланирован
до: 2026-09-30 -->
<Class name="ru.vikulinva.legacy.OldHandler"/>
<Bug pattern="MS_MUTABLE_COLLECTION"/>
</Match>
Раз в квартал — auto-script ищет просроченные suppressions:
#!/bin/bash
# tools/check-expired-suppressions.sh
NOW=$(date +%Y-%m-%d)
xmllint --xpath '//suppress[@until]' config/dependency-check-suppressions.xml |
while read entry; do
until=$(echo "$entry" | grep -oP 'until="\K[^"]+')
if [[ "$until" < "$NOW" ]]; then
echo "EXPIRED: $entry"
fi
done
CI прогоняет этот script weekly, постит issue в repo.
Без срока — suppression становится «забытым исключением». Через 2 года никто не помнит, почему добавили, security team не может ревью.
GitHub Code Scanning + SARIF
R-SEC-FIND-3: единый dashboard.
Все инструменты UCP экспортируют SARIF format (Static Analysis Results Interchange Format):
# CI step
- name: Upload SpotBugs SARIF
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: build/reports/spotbugs/main.sarif
- name: Upload Trivy SARIF
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: trivy-results.sarif
- name: Upload Dependency-Check SARIF
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: build/reports/dependency-check-report.sarif
После — все findings видны в GitHub Security tab:
- Filter по severity, tool, file.
- Tracking фикса (status: open / dismissed / fixed).
- Notifications в Slack/PagerDuty через GitHub.
Без отдельной инфры (SonarQube, Snyk dashboard) — встроено в GitHub.
Альтернатива для GitLab — GitLab Security Dashboard, тоже принимает SARIF.
«Не уверен, эксплуатируется ли»
R-SEC-FIND-X1: главный антипаттерн.
Security tool: "SQL_INJECTION_JDBC at OrderRepository.java:142"
Developer: "Ну вроде там getValidatedId(), это безопасно"
[ничего не делает]
[через год attacker эксплуатирует]
Что должно произойти:
<!-- spotbugs-exclude.xml -->
<Match>
<!-- justify: getValidatedId() возвращает только Long, проверен через @Valid @Min(1)
на DTO-уровне; реального string concat нет. False positive SpotBugs из-за
${} в SQL template (это JPQL parameter, не interpolation).
до: 2026-09-30 (пересмотреть после миграции на jOOQ типизированные queries) -->
<Class name="ru.vikulinva.order.OrderRepository"/>
<Method name="findByCustomerAndStatus"/>
<Bug pattern="SQL_INJECTION_JDBC"/>
</Match>
Это:
- Запись в репо — security team может ревью.
- Срок — повторная проверка через 6 месяцев.
- Обоснование — explicit аргумент.
«Молчание = долг» — finding в дашборде остаётся, suppression нет → security team тратит время на повторный анализ, каждое review дублирует работу.
Baseline-механика
R-SEC-4: релиз блокируется только на новые findings.
# config/security-baseline.json — обновляется на каждом merge в main
{
"dependencyCheck": {
"knownVulnerabilities": [
{"cve": "CVE-2024-12345", "package": "...", "firstSeen": "2026-03-15"}
]
}
}
При release tag — сравниваем findings с baseline:
- Новый CVE → блокируем release.
- CVE уже в baseline → не блокируем (это долг, отдельная задача).
Без baseline первый протухший CVE в transitive dep остановит pipeline на неделю — команда начнёт игнорировать всю security. Baseline отделяет «долг» от «новое».
Что запрещено
| Антипаттерн | Правило | Что взамен |
|---|---|---|
| Игнорирование finding без suppression | R-SEC-FIND-X1 | suppression с обоснованием |
Suppression без until= | R-SEC-FIND-2 | срок обязателен |
| CRITICAL не hotfix immediately | R-SEC-FIND-1 | < 24 часа |
| HIGH в backlog «когда-нибудь» | R-SEC-FIND-1 | ≤ 2 недели |
| MEDIUM игнорируется без срока | R-SEC-FIND-1 | ≤ 30 дней, auto-escalate если не fixed |
| LOW отображается в дашборде | R-SEC-FIND-1 | не показываем |
| Findings в proprietary tool без SARIF | R-SEC-FIND-3 | GitHub Code Scanning через SARIF |
| Baseline не updates на merge | R-SEC-4 | auto-update на main |
| Просроченные suppressions не trekаются | R-SEC-FIND-2 | weekly script |
Куда дальше
- Security → раздел 6. Реакция на findings — нормативные формулировки.
- SAST по коду — suppressions в
spotbugs-exclude.xml. - CVE в зависимостях — suppressions в
dependency-check-suppressions.xml. - Секреты в коде и истории — leak = CRITICAL, rotate immediately.
- Container/image-уязвимости — Trivy SARIF в Security tab.
- Криптография в коде — weak crypto = HIGH.
- Observability → SLO и алерты — security alerts отдельный канал.