Files
llm-wiki/raw/interviews/trivy-suppression-dual-control-governance-2026-06-20.md

63 lines
5.0 KiB
Markdown

---
title: interview-prep / trivy-suppression-dual-control-governance
source_type: interview-prep
status: raw
related_branches: [feature-dependency-vulnerability-management-contract]
related_projects: [ca-skeleton]
tags: [interview-prep, ca-skeleton, security, supply-chain, ci]
created: 2026-06-20
status_label: collecting
---
# interview-prep: trivy-suppression-dual-control-governance
> Layer: `raw/interviews/` — 면접 질문 원본 수집·연구 노트.
> `status_label`: `collecting`
## Parent / 부모
- [[raw/branch-notes/feature-dependency-vulnerability-management-contract]] — 이 branch 의 D5(Suppression governance) 를 구현하며 "취약점 suppression 을 어떻게 통제했나" 라는 질문이 자연스럽게 도출됨.
## 질문 / Question
- 질문 원문: "취약점 스캐너의 false-positive 나 accepted-risk 를 suppress 해야 할 때, 그 suppression 이 영구적인 silent bypass 가 되지 않도록 어떻게 통제했나요?"
- 출처: 예상 질문 (branch 작업에서 유추 — 2026-05-25 ca-tmpl audit 가 실제로 발견한 구멍)
- 받은 날짜·맥락: (예상)
## 질문 의도 추론 / Why this question
- 핵심 평가 대상: 운영 trade-off 인식 + 보안 게이트를 *우회 가능하게* 만들지 않는 설계 감각 + "정책과 강제(enforcement)의 분리".
- 함정 / 흔히 빠지는 답변 패턴: "`.trivyignore` 에 추가하면 된다" 로 끝내는 것 — *누가/언제까지/왜* suppress 했는지 통제하지 않으면 그 자체가 백도어가 된다.
- 따라올 만한 후속 질문: "CODEOWNERS 만으로 충분하지 않은 이유는?", "만료일 상한은 왜 90일인가?", "이미 만료된 suppression 은 어떻게 처리되나?"
## 답변 재료 / Raw answer material
- 사실 1 (근거: [[raw/branch-notes/feature-dependency-vulnerability-management-contract]] D5): suppression 은 단일 구조화 파일 `.trivyignore.yaml` 하나로만 허용. 인라인 `# trivy:ignore` 주석·CLI ad-hoc 무시는 금지.
- 사실 2 (근거: 동 branch D5 §3): **이중 통제** — (a) `verifyTrivyignore` Gradle gate 가 각 항목의 `statement`(사유)·`expired_at`(만료일) *필드 존재/유효*를 CI 에서 검증, (b) `.github/CODEOWNERS` + branch protection 이 *파일 변경 자체*에 보안 owner 승인을 merge-time 에 강제. 둘은 대체재가 아니라 보완재 — CODEOWNERS 는 "누가 바꾸나"만, gate 는 "필드가 갖춰졌나"만 잡는다.
- 사실 3 (근거: [[raw/official-docs/trivy-filtering-suppression-policy]] C4): Trivy 는 `expired_at` 이 없으면 **영구 유효**로 취급 → 만료일 누락 자체를 빌드 실패로 막아야 영구 ignore 를 차단할 수 있다.
- 내가 직접 한 경험 (근거: 동 branch §진행 중 메모 2026-06-20): `verifyTrivyignore` 를 line-based parser 로 구현하고 6-케이스(누락/만료/창초과/유효/nested/빈seed)로 pass·fail 을 직접 검증. `./gradlew check` green.
- 트레이드오프: 만료 창 길이 — 짧으면(예: 30일) 재검토 부담↑, 길면(예: 1년) 사실상 영구 ignore. **다수파/표준 없음** → team-policy 90일 default(`UNSUPPORTED_IMPL_DECISION` 로 명시). Trivy 공식 문서는 `expired_at` 필드 *존재*만 보장하고 상한은 권고하지 않는다.
- 한계 / "이건 안 해봤다": 실제 CI 러너에서 `.trivyignore.yaml` 변경 PR 이 CODEOWNERS 승인 없이 merge 차단되는지는 GitHub branch protection 설정에 의존 — `needs-confirmation`(로컬에선 Gradle gate 만 검증).
## Sources / 근거 (답변의 사실 근거)
- [[raw/branch-notes/feature-dependency-vulnerability-management-contract]] — D5, §구현가이드 §3, §진행 중 메모.
- [[raw/official-docs/trivy-filtering-suppression-policy]] — `expired_at`/`statement` 필드 의미(C3·C4·C5).
## 미해결 / Unknown
- 모르는 것 1: CODEOWNERS protected-path 가 force-push/admin override 로 우회되는 경로의 잔여 리스크.
- 모르는 것 2: 만료된 suppression 이 release 직전에 갑자기 빌드를 깨뜨릴 때의 운영 핸드오프(누가 renew 책임).
- 확인 방법: GitHub branch protection 문서 재확인 + 테스트 repo 에서 만료일·사유 없는 row PR 로 CI fail + merge block 실증.
## 답변 경계 / Answer boundary
- 자신 있게 말할 수 있는 범위: Gradle gate 의 필드 검증 로직과 6-케이스 검증 결과(로컬), 이중 통제 설계의 *이유*.
- "공식 문서를 다시 보고 답변드리겠습니다" 라고 해야 하는 부분: GitHub CODEOWNERS+branch-protection 의 정확한 merge 차단 시맨틱, force-push 예외.
- **절대 과장하지 말 것**: 이건 `locally-verified`(Gradle gate)다. CI 러너에서 워크플로/CODEOWNERS 가 실제로 차단하는 것은 아직 실증 안 함(`needs-confirmation`) — "운영에서 막아봤다"고 말하지 말 것.
## Related / 관련
- 관련 블로그 글감: [[raw/blog-topics/trivy-suppression-governance-static-gate-2026-06-20]]
- 답변 derive 후 위치: `[[wiki/interview/...]]` (생성되면)