494 lines
62 KiB
Markdown
494 lines
62 KiB
Markdown
---
|
||
title: branch / feature-dependency-vulnerability-management-contract
|
||
source_type: branch-note
|
||
status: raw
|
||
confidence: medium
|
||
branch: feature-dependency-vulnerability-management-contract
|
||
parent_branch:
|
||
related_projects: [ca-skeleton]
|
||
governing_docs: [raw/project-notes/ca-skeleton-operational-contract]
|
||
tags: [branch, ca-skeleton, security, supply-chain, ci]
|
||
created: 2026-06-15
|
||
target_merge:
|
||
status_label: in-progress
|
||
id: BR-CA-SKELETON-OPERATIONAL-CONTRACT-051
|
||
kind: project-work-item
|
||
project: ca-skeleton-operational-contract
|
||
work_item: WI-CA-SKELETON-OPERATIONAL-CONTRACT-051
|
||
inherits: [DEC-CA-SKELETON-OPERATIONAL-CONTRACT-STACK-BUILD-001@1]
|
||
refines: []
|
||
overrides: []
|
||
depends_on: [WI-CA-SKELETON-OPERATIONAL-CONTRACT-028, WI-CA-SKELETON-OPERATIONAL-CONTRACT-030, WI-CA-SKELETON-OPERATIONAL-CONTRACT-029]
|
||
contract_packet: 1
|
||
contract_packet_sha256: bb574e1b56cc247fc24b861ef1249c28991938b0dab6bab63999d5cf9ffb756b
|
||
---
|
||
|
||
# branch: feature-dependency-vulnerability-management-contract
|
||
|
||
> Layer: `raw/branch-notes/` — 단일 브랜치의 **TODO·결정·진행 기록**. 머지/종료 후 verified 결과는 `/ingest`로 `wiki/projects/`에 추출. 원본은 raw에 영구 보관.
|
||
> `status_label`: `in-progress` | `review` | `merged` | `abandoned`
|
||
> **계층 표기**: "root branch" 라는 별도 개념은 없음. project 의 직접 자식 branch 는 `parent_branch:` 를 **비워두고** `related_projects` 만 채움. 다른 branch 의 자식이면 `parent_branch: <부모 branch 이름>` 명시 + `## Parent` 섹션의 부모 wikilink 필수.
|
||
|
||
<!-- section-id: branch-parent -->
|
||
## 부모 (필수)
|
||
|
||
> 이 branch 가 어느 작업 묶음에 속하는지. 모든 branch 는 예외 없이 upward link 보유.
|
||
|
||
- **Project 의 직접 자식 branch** (`parent_branch:` 비어있음): [[raw/project-notes/ca-skeleton-operational-contract]]
|
||
- 본 branch 는 project-note 의 §18 Control Plane Contract 중 **Build / Release / Supply Chain** (의존성 취약점 차단) + **CI Quality Gates** (vulnerability scan gate) 영역을 정제한다.
|
||
|
||
형제 branch (같은 부모의 다른 자식 — 본 branch 와 계약 경계를 공유):
|
||
|
||
- [[raw/branch-notes/feature-build-release-supply-chain-contract]] — SBOM·서명(Cosign/SLSA)·dependency **locking**·artifact versioning 의 owner. 본 branch 는 그 D2(high/critical=release-blocking)·D3(Renovate/Dependabot) 의 `UNSUPPORTED_DECISION` 스텁을 **승계해 정책 owner** 가 된다(아래 §Audit & Findings).
|
||
- [[raw/branch-notes/feature-ci-quality-gates-contract]] — CI gate **wiring**(release-blocking vs warning-only) 의 owner. 본 branch 의 severity 정책을 *consume*. 그 D5(Trivy scanner+suppression) `UNSUPPORTED_DECISION` 스텁도 본 branch 가 정책 owner 로 정합.
|
||
- [[raw/branch-notes/feature-container-runtime-contract]] — container **image** scan wiring + base image(Temurin JRE slim) owner. 본 branch 의 동일 severity 정책을 *consume*.
|
||
|
||
<!-- GENERATED: branch-contract:start -->
|
||
<!-- section-id: branch-contract-packet -->
|
||
## 브랜치 계약 패킷
|
||
|
||
- **생성 시 프로젝트 개정**: `1`
|
||
- **패킷 스키마**: `contract_packet: 1`
|
||
- **완료 조건**: scanner·severity·suppression·update·license 정책과 CI failure gate가 명시된다
|
||
|
||
<!-- section-id: inherited-project-decisions -->
|
||
### 상속한 프로젝트 결정
|
||
|
||
| Decision Ref | Project Summary | Branch Application | Source |
|
||
|---|---|---|---|
|
||
| `DEC-CA-SKELETON-OPERATIONAL-CONTRACT-STACK-BUILD-001@1` | build tool은 Gradle Groovy DSL이다 | Work Item 완료 조건에 적용 | [[raw/project-notes/ca-skeleton-operational-contract]] |
|
||
|
||
<!-- section-id: branch-local-decisions -->
|
||
### 브랜치 지역 결정
|
||
|
||
> 기존 branch-local 결정은 아래 `## Decision Evidence Map / 결정-근거 매핑`의 D-row가 소유하며 이 packet에서 복제하지 않는다.
|
||
|
||
| Decision ID | Decision | Relation | Supporting Claims | Status |
|
||
|---|---|---|---|---|
|
||
|
||
<!-- section-id: declared-overrides -->
|
||
### 선언한 예외
|
||
|
||
| Override ID | Overrides | Reason | Approval | Status |
|
||
|---|---|---|---|---|
|
||
<!-- GENERATED: branch-contract:end -->
|
||
|
||
<!-- section-id: branch-goal -->
|
||
## 목표
|
||
|
||
ca-skeleton 의 §18 Build/Release/Supply Chain 과 CI Quality Gates 에는 "high/critical vulnerability 는 release-blocking" (supply-chain D2) 과 "vulnerability scanner = Trivy + suppression" (ci-gates D5), "dependency upgrade = Renovate/Dependabot" (supply-chain D3) 라는 **정책 의도만 있고 외부 근거 없는 `UNSUPPORTED_DECISION` 스텁**이 세 sibling branch 에 흩어져 있다. 어느 branch 도 *어떤 스캐너 / 어떤 심각도 표준 / 어떤 임계값 / 어떻게 suppress / 얼마나 빨리 고칠지* 를 근거와 함께 정하지 않았다 — 즉 **의존성 취약점 관리 정책의 single owner 가 없다**.
|
||
|
||
본 branch 는 그 빈 자리를 메우는 **dependency vulnerability *정책* 의 single owner** 다 (§25 SSOT Owner Map 에 해당 owner 부재 확인 → Cross-Branch Conflict Procedure 통과). 정의 대상: SCA 스캐너 선택, CVSS 심각도 표준·차단 임계값, KEV override, 스캐너 소스 우선순위(tie-break), suppression governance(만료·사유·무단변경 차단), 의존성 보안 업데이트 자동화(Renovate/Dependabot), PR-time 보완 게이트(dependency-review-action). gate *wiring* 은 ci-gates 가, image scan *wiring* 은 container-runtime 이, SBOM/서명/locking 은 supply-chain 이 소유하고 — 셋 다 본 branch 의 severity 정책을 *consume* 한다.
|
||
|
||
- 이슈: (미생성 — Phase C2 실 구현 단계에 연결)
|
||
- PR: (미생성)
|
||
|
||
<!-- section-id: branch-scope -->
|
||
## 범위
|
||
|
||
### 포함 범위
|
||
|
||
- **SCA 스캐너 선택** — 의존성(라이브러리) CVE 스캔 도구. ci-gates 의 잠정 "Trivy" 를 공식 근거로 승격/검증.
|
||
- **심각도 분류 표준 + 차단 임계값** — CVSS 버전, 점수→등급 매핑, 어느 등급부터 release-blocking. supply-chain D2 의 "high/critical=blocking" 에 외부 표준 부여.
|
||
- **KEV override** — 실제 악용(exploited in the wild) CVE 는 CVSS 점수 무관 차단.
|
||
- **스캐너 심각도 소스 우선순위(tie-break)** — NVD vs GHSA/벤더 점수 충돌 시 규칙.
|
||
- **Suppression governance** — `.trivyignore` 포맷 + 만료일 강제 + 사유 기록 + PR 승인 + 무단 변경 차단 정적 게이트(2026-05-25 audit finding 해소).
|
||
- **의존성 보안 업데이트 자동화** — Renovate primary / Dependabot 조건부 + patch-level 보안 PR auto-merge 정책. supply-chain D3 정합.
|
||
- **PR-time 보완 게이트** — GitHub dependency-review-action 으로 신규 도입 취약 의존성 차단(전체 스냅샷 스캔과 역할 분리).
|
||
- **스캔 단계/스코프** — PR 게이트 + 의존성 불변이라도 CVE DB 갱신을 잡는 scheduled 재스캔 + pre-release image scan.
|
||
- **의존성 라이선스 준수 스캔(license/NOTICE)** — Trivy 가 이미 `*gradle.lockfile` 의 license 도 스캔(License ✓)하므로 통합. 금지(strong-copyleft) 라이선스 release-blocking + allow-list 정책 + PR-time allow/deny(dependency-review-action). governing §35-E L2052 가 *license scan* 을 본 branch 영역으로 명시.
|
||
|
||
### 제외 범위
|
||
|
||
> 의도적으로 제외한 것. 면접 등에서 "이건 범위에 없었습니다"라고 답할 근거.
|
||
|
||
- **CI gate wiring(release-blocking vs warning-only 판정·`needs:`/`if:` 의존성 구성)** — `feature-ci-quality-gates-contract` owner. 본 branch 는 정책을 제공만.
|
||
- **container image scan wiring + base image 선택** — `feature-container-runtime-contract` owner (본 branch severity 정책 consume).
|
||
- **SBOM 생성·artifact 서명(Cosign/SLSA)·dependency *version locking*·artifact versioning·rollback** — `feature-build-release-supply-chain-contract` owner.
|
||
- **secret scan(gitleaks)** — `feature-secrets-config-source-contract` owner.
|
||
- **특정 CI provider(GitHub Actions) workflow YAML 의 실제 구현 세부** — 본 branch 는 계약/정책, 구현은 Phase C2.
|
||
|
||
## 근거 (필수, 최소 1개+)
|
||
|
||
> 이 branch의 구현·설계 결정의 **근거가 되는 외부 자료**. 공식 문서·대기업 기술 블로그·강의 등 raw 자료를 인용. 같은 자료가 여러 결정의 근거면 결정 표시와 함께 여러 번 등장 가능.
|
||
|
||
| Source | 정당화하는 결정 |
|
||
|---|---|
|
||
| [[raw/official-docs/trivy-action-github-actions]] | D1/게이트 — exit-code+severity 로 release-blocking CI 게이트 구성, trivyignores 파라미터로 suppression 파일 지정 |
|
||
| [[raw/official-docs/github-dependency-review-action]] | PR-time 보완 게이트 — 신규 도입 취약 의존성 차단(C1·C2). 단독 릴리즈 게이트 부적합(PR diff 전용, C4). severity 커스터마이즈 가능(C3). |
|
||
| [[raw/official-docs/trivy-filtering-suppression-policy]] | suppression governance — `.trivyignore` `exp:YYYY-MM-DD` 만료일(C3), `.trivyignore.yaml` `expired_at` 필드(C4) 로 영구 suppress 방지; `statement` 필드로 사유 기록(C5) |
|
||
| [[raw/official-docs/vuln-severity-cisa-kev-catalog-official]] | KEV 목록에 등재된 CVE = CVSS 점수와 무관하게 릴리즈 차단(exploitation-in-the-wild override). `dueDate` 필드 존재는 CISA 자체가 우선 시한을 부여한다는 증거 (CISA-KEV-C3). |
|
||
| [[raw/official-docs/vuln-severity-cvss-v31-spec-first-official]] | 릴리즈 차단 심각도 기준 = CVSS v3.1 base score, High(≥7.0)/Critical(≥9.0) 차단. FIRST.org 명세가 정성 등급 구간(Table 14, C1)과 Base Score 정의(C3)의 권위 표준. |
|
||
| [[raw/official-docs/dependabot-security-updates-gradle-official]] | Dependabot 조건부 허용 근거 — security updates 정의(C1), security vs version updates 구분(C2), grouped security updates 생태계 단위 묶음(C3·C4), manifest/lock 한정 트리거(C5) |
|
||
| [[raw/official-docs/trivy-java-language-coverage]] | D1/SCA 채택 — `*gradle.lockfile` SBOM·Vulnerability·License 공식 지원(C1), 오프라인 스캔 가능(C2), Java 취약점 소스 = GitHub Advisory Database Maven(C5) |
|
||
| [[raw/official-docs/renovate-vulnerability-alerts-gradle-official]] | Renovate primary 채택 근거 — `security:only-security-updates` preset이 `osvVulnerabilityAlerts: true` + `vulnerabilityAlerts.enabled: true` + 전체 패키지 기본 비활성화 구성임을 공식 문서로 확인 (C1·C2·C3) |
|
||
|
||
> **Deferred 아카이브 (후속 `/branch-spec` 재실행 또는 수동 dispatch)** — 아래 자료는 *대안 비교*·*보강 신호* 근거로 `wiki-decision-researcher` 가 URL·핵심 사실을 이미 확보했으나, 본 run 의 archive 예산을 핵심 7건에 집중하느라 raw 미등록. 해당 결정의 Evidence Strength 가 그만큼 낮음을 Decision Evidence Map 에 표기:
|
||
> - `https://dependency-check.github.io/DependencyCheck/dependency-check-gradle/index.html` — OWASP Dependency-Check (D1 대안: 멀티모듈 `dependencyCheckAggregate` + `failBuildOnCVSS`, NVD API 키 필요)
|
||
> - `https://github.com/anchore/grype` — Grype (D1 대안: false-positive 최저 + KEV/EPSS 내장, 단 gradle.lockfile 공식 지원 불명확)
|
||
> - `https://nvd.nist.gov/vuln-metrics/cvss` — NVD severity bands (D2 보강: CVSS v3.x/v4.0 밴드 corroboration)
|
||
> - `https://www.first.org/epss/` — FIRST EPSS (D8 보강: EPSS ≥ 0.1 escalation 신호 근거)
|
||
> - `https://trivy.dev/docs/latest/scanner/vulnerability/` — Trivy 소스 우선순위(언어 패키지 GHSA>NVD) (D4 보강 — coverage 페이지엔 OS 패키지만 명시됨)
|
||
> - `https://www.cisa.gov/news-events/directives/bod-26-04-prioritizing-security-updates-based-risk` — CISA BOD 26-04 (D3 보강: KEV=독립 우선순위 인자; CISA HTML 403 으로 본 run 미확보)
|
||
|
||
## TODO
|
||
|
||
각 항목 옆에 증거 등급 표기: `actually-implemented` | `locally-verified` | `prod-verified` | `documented-only` | `planned` | `needs-confirmation`
|
||
|
||
> ca-tmpl ground truth(2026-06-15 확인): `.github/workflows/` 없음, `gradle/locks/` 없음, Renovate/Dependabot/Trivy config 없음 → 본 branch 전 항목 `planned` (코드 미존재). `actually-implemented` 승급은 Phase C2 실 구현 + `src/`/CI grep 확인 후.
|
||
|
||
- [x] Trivy fs scan CI job (`aquasecurity/trivy-action`, `scan-type: fs`, `exit-code: 1`, `severity: CRITICAL,HIGH`, `TRIVY_FILE_PATTERNS` 멀티모듈 workaround) — 등급: `actually-implemented` (`.github/workflows/dependency-vulnerability.yml` `trivy-fs` 잡, YAML valid; 실제 CI 실행은 `needs-confirmation`) (D1)
|
||
- [x] `dependency-review-action` required check (`fail-on-severity: high`) — 등급: `actually-implemented` (`.github/dependency-review-config.yml` + workflow `dependency-review` 잡; graph 제출은 `dependency-submission` 잡으로 보강) (D7)
|
||
- [x] severity 정책 문서화: CVSS v3.1 밴드 + ≥High 차단 + KEV override + EPSS escalation — 등급: `actually-implemented` (`.github/dependency-vulnerability-policy.md` §2/§3/§4, 모든 team-policy 값 `UNSUPPORTED_IMPL_DECISION` 라벨) (D2/D3/D8)
|
||
- [x] `.trivyignore.yaml` suppression 정책 + 만료일 강제 + 무단변경 차단 정적 게이트 — 등급: `locally-verified` (`verifyTrivyignore` Gradle gate: 6-케이스 pass/fail 검증 + `./gradlew check` green; `.trivyignore.yaml` 빈 seed + `.github/CODEOWNERS` merge-gate) (D5)
|
||
- [x] Renovate `security:only-security-updates` 설정 + patch 보안 PR auto-merge 정책 — 등급: `actually-implemented` (`renovate.json`, JSON valid; Renovate 봇 실행은 `needs-confirmation`) (D6)
|
||
- [x] scheduled 재스캔 job(CVE DB 갱신 캡처) + pre-release `trivy image` scan — 등급: `actually-implemented` (workflow `schedule` daily cron + `trivy-image` release 잡, `vars.RELEASE_IMAGE_REF` 게이팅으로 container-runtime wiring seam) (D1/구현가이드 §1)
|
||
- [x] 의존성 라이선스 스캔: Trivy license(gradle.lockfile) + dependency-review-action `deny-licenses` + 금지 SPDX 목록 정의 — 등급: `actually-implemented` (`scanners: vuln,license` + GPL/AGPL deny-list; 목록은 `UNSUPPORTED_IMPL_DECISION` team-policy) (D10)
|
||
- [ ] sibling 역참조 정합: supply-chain D2/D3, ci-gates D5 의 `UNSUPPORTED`/`OWNER_AMBIGUITY` → 본 branch 위임으로 갱신 (§Audit & Findings, 비차단) — 등급: `planned` (비차단 — 다음 작업자/`/sync`; 본 구현 머지와 독립)
|
||
|
||
## 진행 중 메모
|
||
|
||
작업하며 떠오른 메모. 자유 형식.
|
||
|
||
### 2026-06-20 — Phase C2 구현 (ca-tmpl, branch `feature/dependency-vulnerability-management-contract`)
|
||
|
||
정책 7건(D1·D2/D3/D8·D5·D6·D7·D10·§1)을 ca-tmpl 의 커밋 가능한 아티팩트로 실 구현. 커밋은 사용자가 직접 수행(working tree 만 변경).
|
||
|
||
**커밋 대상 파일 (tracked):**
|
||
|
||
- `.github/workflows/dependency-vulnerability.yml` — D1 `trivy-fs`(PR+daily schedule, `scanners: vuln,license`, `severity: CRITICAL,HIGH`, `exit-code:1`, `trivyignores: .trivyignore.yaml`, `TRIVY_FILE_PATTERNS`) + D7 `dependency-review`(PR) + `dependency-submission`(`gradle/actions/dependency-submission`, graph fail-open 보강) + §1 `trivy-image`(release, `vars.RELEASE_IMAGE_REF` 게이팅 — container-runtime wiring seam).
|
||
- `.github/dependency-review-config.yml` — D7 `fail-on-severity: high` + `fail-on-scopes: [runtime]` + D10 `deny-licenses`(GPL/AGPL family) + `comment-summary-in-pr: on-failure`.
|
||
- `.trivyignore.yaml` — D5 빈 seed(`vulnerabilities/licenses/misconfigurations/secrets: []`) + 헤더에 `id`/`statement`/`expired_at` 포맷 문서화. repo 루트(Trivy 자동 인식).
|
||
- `renovate.json` — D6 `config:recommended` + `security:only-security-updates` + `vulnerabilityAlerts`(stable) + `osvVulnerabilityAlerts`(experimental) + patch auto-merge / minor·major human review packageRules.
|
||
- `.github/CODEOWNERS` — D5 §3 ② merge-time 승인(`.trivyignore.yaml`·policy·workflows·`renovate.json` → `@DongHyeonka` placeholder).
|
||
- `.github/dependency-vulnerability-policy.md` — D2/D3/D4/D8/D9/D10 통합 정책 SSOT(committed). 모든 team-policy 수치 `UNSUPPORTED_IMPL_DECISION` 라벨.
|
||
- `src/build.gradle` — D5 §3 ① `verifyTrivyignore` Gradle gate(line-based parser, `maxWindowDays=90`), `subprojects { check { dependsOn } }` 배선(기존 `verifyEnvKeys` 패턴).
|
||
- `src/README.md`·`README.md` — gate 문서화 + 정책 참조.
|
||
|
||
**검증(locally-verified):** `verifyTrivyignore` 6-케이스 — 빈 seed pass / 유효+nested paths pass / `expired_at` 누락 fail / `statement` 누락 fail / 이미 만료 fail / 90일 초과 fail, seed 복원 후 재pass. `./gradlew check` = BUILD SUCCESSFUL(106 tasks). 4개 check-wired gate 동시 통과. workflow/dep-review YAML + renovate JSON 구문 유효성 확인. CI 러너에서의 실제 스캔 동작은 `needs-confirmation`(§Claims To Verify 참조).
|
||
|
||
**UNSUPPORTED_IMPL_DECISION 기본값 선택(스켈레톤 default, fork 가 교체):** scheduled=daily(`0 6 * * *`); 차단=≥High; EPSS=0.1(비차단); suppression 창=90일; patch auto-merge; license=deny-list(GPL/AGPL, LGPL 허용); SLA=KEV/Critical 7d·High 30d·Medium 90d. `verifyPublicPathSnapshot` 의 문서화 방식과 동일.
|
||
|
||
**경계 준수:** `dependencyLocking`/lockfile 생성 미추가(supply-chain D8 owner) — Trivy fs 는 lockfile 커밋 전까지 Gradle deps no-op, 그 사이 `dependency-submission` graph 가 transitive backstop. image scan **wiring** 은 `vars.RELEASE_IMAGE_REF` seam 으로 container-runtime 에 위임. CI gate `needs:`/`if:` 배선은 ci-gates owner(본 파일은 정책만).
|
||
|
||
### 2026-06-20 — 코드 리뷰 수정 2건 (workflow correctness)
|
||
|
||
- **TRIVY_EXIT_CODE 주석 오기 정정 (correctness):** `trivy-fs` 잡의 `TRIVY_EXIT_CODE: "1"` 는 `exit-code: "1"` 입력과 동일 knob(취약점 *발견 시* 종료코드)이라 중복이었고, 주석이 이를 "DB fetch 실패 시 fail" 메커니즘으로 *오기*했다. 제거하고, DB-fetch 실패→fail 은 Trivy **기본 동작**(캐시 없으면 DB 다운로드 실패 시 non-zero)이며 설정 플래그가 아님 + 여전히 `needs-confirmation` 임을 정직하게 주석화. §Claims To Verify "스캐너 DB fetch 실패가 silent pass 가 아니라 job fail" 은 **여전히 미검증(`planned`)** — 이전 주석이 충족을 거짓 주장했던 것을 철회. 실검증: CI 에서 DB endpoint 차단 후 non-zero exit 단언.
|
||
- **Medium "warn/advisory" 티어 실현:** policy §2 표는 Medium=warn(advisory)/Low=report 인데 두 Trivy 잡이 `severity: CRITICAL,HIGH` 만 스캔해 Medium/Low 를 보고조차 안 했음(정책-구현 gap). `trivy-fs` 에 비차단 advisory step(`severity: MEDIUM,LOW`, `exit-code: "0"`) 추가로 보고만 하고 차단 안 하는 티어 실현. policy §2 운영 구현 줄도 정합.
|
||
- **D3 KEV override 실효 강제 (실효 강제 0 → 실제 차단):** severity 필터가 `CRITICAL,HIGH` 라 §2 matrix 의 "KEV 등재 시 모든 밴드 block" 의도가 Low/Medium 에서 미실현이었음(실효 강제 0). `trivy-fs` 에 (1) 전체 밴드 JSON 스캔(`severity: CRITICAL,HIGH,MEDIUM,LOW,UNKNOWN`, `exit-code:0`, `format: json`) + (2) `KEV override gate` run step(CISA KEV JSON feed `curl -fsSL --retry 3` → `jq`/`comm` 으로 발견 CVE ∩ KEV → 교집합 있으면 `exit 1`) 추가. suppression(`.trivyignore.yaml`)은 그대로 적용 → KEV CVE 는 거버넌스된 suppression 으로만 수용. feed 미가용 = `curl -f` fail-closed(silent pass 금지, §Edge·Failure JSON feed 가용성 충족). policy §3 을 posture→실효 강제로 갱신. **Open Risk(유지):** KEV 등재 지연, feed CI 의존.
|
||
- 검증: workflow YAML 재유효성 OK; `TRIVY_EXIT_CODE` 제거 + advisory/KEV step 존재 grep 확인; **KEV cross-check 로직 mock 3-케이스 검증** — KEV 등재 CVE 발견 시 exit1(block), 빈 발견셋(lockfile 부재) pass, 비-KEV CVE pass. (Java/Gradle 코드·게이트 로직 무변경이라 `./gradlew check` 재실행 불요. CI 러너 실제 동작은 `needs-confirmation`.)
|
||
|
||
### 2026-06-20 — Gitea/act 플랫폼 적응 (CI 실패 1건 해소)
|
||
|
||
사용자가 commit `cb12207` push 후 self-hosted **Gitea + act_runner**(k8s 내부, `gitea-http.platform.svc.cluster.local`)에서 워크플로 실행 → 2개 잡 실패. 타깃 플랫폼 = Gitea 확정.
|
||
|
||
- **`dependency-review` 실패 (원인 확정):** `::error::Dependency review could not obtain dependency data...`. dependency-review-action 은 **GitHub Dependency Graph compare API**(GitHub.com/GHES 전용)에 의존 → Gitea 에 API 부재 + `dependency-submission`(graph 제출, push-only)이 PR 이벤트라 skip 돼 graph 도 비어있음. **수정:** `dependency-review`·`dependency-submission` 두 잡에 `&& github.server_url == 'https://github.com'` 가드 추가 → Gitea 에선 skip(실패 아님), GitHub.com 에선 그대로 동작. Gitea 의 PR-time 의존성 검사는 플랫폼 독립적 `trivy-fs`(매 PR)가 커버(D7 단독 게이트 금지 설계가 backstop 제공). policy §8 에 플랫폼 호환성 note 추가.
|
||
- **`trivy-fs` 실패 (원인 확정 — egress 가설 철회):** trivy-fs step 로그 입수 → `git clone 'https://github.com/aquasecurity/trivy-action' # ref=0.28.0` → `Unable to resolve 0.28.0: reference not found`. **egress 문제 아님**(러너가 actions/checkout·trivy-action 을 github.com 에서 정상 clone — github.com·ghcr 접근 가능). 진짜 원인은 **액션 태그 오타**: `aquasecurity/trivy-action` 의 실제 태그는 `v` 접두사(`v0.28.0`)인데 `@0.28.0`(v 없이)로 핀해 404. GitHub API 로 실제 태그 확인(`tags/0.28.0`=404, `tags/v0.28.0`=200; 최신 `v0.36.0`). **수정:** 워크플로 4곳 `@0.28.0`→`@v0.28.0`(replace_all). 내 1차 "egress 차단" 진단은 4s 빠른 실패만 보고 세운 가설이었고 로그가 반증 — *증거 우선* 위반 사례.
|
||
- skip 정상: `dependency-submission`(push-only)·`trivy-image`(release-only)는 PR 이벤트라 의도된 skip(회색).
|
||
- 검증: workflow YAML 재유효성 OK, server_url 가드 2건 + trivy-action `@v0.28.0` 4건 grep 확인, GitHub API 로 `v0.28.0` 존재 확인. (YAML 변경만 — `./gradlew` 무관.) **재실행 후 trivy-fs 완전 통과(Trivy DB pull + KEV step cisa.gov curl 포함)는 `needs-confirmation`.**
|
||
- **`trivy-fs` 2차 실패 → CLI 전환 (act 의 trivy-action 미지원):** 태그 수정 후 재실행하니 액션 resolve 는 통과했으나 `entrypoint.sh: line 44: trivy: command not found`. `aquasecurity/trivy-action` 은 setup-trivy 서브액션 + DB 캐시로 Trivy 를 설치하는 **composite** 인데 act 가 그 설치 스텝을 안 돌려 바이너리 부재. **수정:** trivy-action 폐기 → **Trivy + jq CLI 정적 바이너리를 github.com 에서 직접 설치**(`trivy v0.71.2`, `jq 1.8.1`, API 로 태그/자산명 사전 확인) 후 `trivy fs`/`trivy image` CLI 직접 호출. `--file-patterns` 제거(`**/*.lockfile` 는 CLI 에서 invalid regex 위험 + 표준 `gradle.lockfile` 명명은 Trivy 기본 탐지로 충분; 비표준 명명만 Claims To Verify). KEV step 에 `KEV_FEED_URL` repo-var override(폐쇄망 미러) + fetch 실패 시 명시적 fail-closed 메시지 추가. CLI 는 GitHub.com·Gitea/act 공통.
|
||
- skip 정상: `dependency-submission`(push-only)·`trivy-image`(release-only)는 PR 이벤트라 의도된 skip(회색).
|
||
- 검증: workflow YAML 재유효성 OK(CLI 전환 후); `uses: aquasecurity/trivy-action` 제거(주석만 잔존) + `trivy fs`/`trivy image` CLI step grep 확인; GitHub API 로 `trivy v0.71.2`·`jq-1.8.1` 자산 존재 확인; KEV jq/comm 로직 mock 3-케이스 재확인. (YAML 변경만 — `./gradlew` 무관.) **남은 egress 의존(재실행 시 다음 관문): github.com=확인됨, ghcr.io(Trivy DB)·KEV feed 호스트=`needs-confirmation`(폐쇄망이면 `TRIVY_DB_REPOSITORY`/`KEV_FEED_URL` 미러).**
|
||
- 파생: [[raw/errors/gitea-act-action-tag-and-dependency-graph-2026-06-20]] (CI 실패 근본원인 + 수정, 2-iteration).
|
||
|
||
## 결정 사항
|
||
|
||
> 추후 면접/회고에서 "왜 이렇게 했나" 답할 근거. 대안과 함께 기록. 각 결정의 근거는 위 Sources 또는 새로 추가된 raw 자료를 가리킬 것. 상세 매핑은 아래 Decision Evidence Map.
|
||
|
||
- 2026-06-15: **SCA 스캐너 = Trivy** (fs 의존성 + image 동일 바이너리, `aquasecurity/trivy-action`). 이유: OSS(Apache 2.0) + gradle.lockfile 공식 지원 + NVD API 키 불필요 + image 동일 도구 + `exit-code`/`severity` 로 release-blocking 즉시 구성. 검토한 대안: OWASP Dependency-Check(멀티모듈 aggregate 성숙하나 NVD 키 필요), Grype(FP 최저·KEV/EPSS 내장하나 gradle.lockfile 지원 불명확), Snyk(상용 — OSS 스켈레톤 부적합 제외), dependency-review-action(PR 보완 전용). 근거: [[raw/official-docs/trivy-java-language-coverage]], [[raw/official-docs/trivy-action-github-actions]]. (ci-gates D5 의 `OWNER_AMBIGUITY`/미결 해소 — D1)
|
||
- 2026-06-15: **차단 심각도 = CVSS v3.1 base score, High(≥7.0)·Critical(≥9.0) 차단**, Medium/Low 는 warning-only. 이유: 스캐너·NVD 커버리지 완전 + FIRST.org 권위 표준 밴드 + industry de-facto 임계값. 검토한 대안: CVSS v4.0(스캐너 미성숙 — 2026-12 재평가). 근거: [[raw/official-docs/vuln-severity-cvss-v31-spec-first-official]]. (supply-chain D2 에 외부 표준 부여 — D2)
|
||
- 2026-06-15: **KEV override** — CISA KEV 등재 CVE 는 CVSS 점수 무관 차단. 이유: exploited-in-the-wild 는 점수보다 실위험이 큼(CISA `dueDate` 부여). 근거: [[raw/official-docs/vuln-severity-cisa-kev-catalog-official]]. (D3)
|
||
- 2026-06-15: **Suppression governance** — `.trivyignore(.yaml)` + 만료일 강제 + `statement` 사유 + PR 승인 + 무단변경 차단 정적 게이트. 이유: 만료 없는 영구 ignore 차단(2026-05-25 ca-tmpl audit finding 해소). 근거: [[raw/official-docs/trivy-filtering-suppression-policy]]. (D5)
|
||
- 2026-06-15: **의존성 보안 업데이트 = Renovate primary / Dependabot 조건부**. 이유: version-catalog+lockfile 동시 사용 시 Dependabot lockfile 미갱신 버그(#12557)가 supply-chain D8 locking 과 충돌; Renovate 는 security-only preset + patch auto-merge 단순. 검토한 대안: Dependabot(조직 표준/단순 구조 시 허용). 근거: [[raw/official-docs/renovate-vulnerability-alerts-gradle-official]], [[raw/official-docs/dependabot-security-updates-gradle-official]]. (supply-chain D3 정합 — D6)
|
||
- 2026-06-15: **PR-time 보완 게이트 = dependency-review-action** (`fail-on-severity: high`, required). 단독 릴리즈 게이트 금지(PR diff 전용). 근거: [[raw/official-docs/github-dependency-review-action]]. (D7)
|
||
- 2026-06-15: **의존성 라이선스 준수 스캔 = Trivy license(이미 toolchain) + dependency-review-action allow/deny**. 이유: D1 Trivy 가 `*gradle.lockfile` license 도 스캔하므로 별도 도구 불필요; governing §35-E L2052 가 license scan 을 본 branch 영역으로 명시. 근거: [[raw/official-docs/trivy-java-language-coverage]], [[raw/official-docs/github-dependency-review-action]]. (D10)
|
||
|
||
## 결정-근거 매핑
|
||
|
||
> 각 결정이 어떤 raw source claim 으로 뒷받침되는지 명시한다.
|
||
> `Decision ID` 는 이 branch-note 안에서 안정적으로 유지한다. 예: `D1`, `D2`.
|
||
> `Supporting Claims` 는 `raw/<category>/<slug>.md#C1` 형식으로 연결한다.
|
||
|
||
> `선택 조건` 열(R2): "이 조건일 때 이 결정, 다른 조건이면 어떤 대안". 분기 없으면 `N/A`.
|
||
|
||
| Decision ID | Decision | 선택 조건 (언제 이 결정 / 언제 대안) | Supporting Claims | Evidence Strength | Open Risk |
|
||
|---|---|---|---|---|---|
|
||
| D1 | **SCA 스캐너 = Trivy** (fs 의존성 스캔 + image 동일 바이너리, `aquasecurity/trivy-action`, `exit-code:1`+`severity:CRITICAL,HIGH`=release-blocking) | OSS + NVD 키 불필요 + gradle.lockfile 지원 + image 동일 도구 → **Trivy**. 멀티모듈 `dependencyCheckAggregate` 공식 지원 + CVSS 소수점 임계값 제어가 더 중요 → **OWASP Dependency-Check** (NVD API 키+캐싱 감수). FP 최저+EPSS/KEV 내장이 최우선 → **Grype**(단 gradle.lockfile POC 선행) | `raw/official-docs/trivy-java-language-coverage.md#C1` (`*gradle.lockfile` SBOM/Vuln/License ✓), `raw/official-docs/trivy-java-language-coverage.md#C2` (오프라인 스캔), `raw/official-docs/trivy-action-github-actions.md#C1`·`#C2` (exit-code/severity release-blocking), `raw/official-docs/trivy-action-github-actions.md#C4` (`trivyignores`) | `official-vendor-doc` (Aqua Trivy) — 대안(OWASP DC/Grype/Snyk) 비교는 §Sources Deferred 아카이브 | 멀티모듈 lockfile 탐지 버그 → `--file-patterns "gradle-lockfile:*.lockfile"` workaround(공식 문서 미명시, Claims To Verify); Gradle `force=true` 재정의 false positive; **lockfile 생성이 선행조건** → [[raw/branch-notes/feature-build-release-supply-chain-contract]] D8(dependency-locking) 의존 |
|
||
| D2 | **차단 심각도 = CVSS v3.1 base score; High(≥7.0)·Critical(≥9.0)=release-blocking**, Medium(4.0–6.9)/Low(0.1–3.9)=warning-only(비차단 advisory) | 스캐너 지원·NVD 커버리지 완전 → **v3.1**. 스캐너 v4.0 파싱 안정 + NVD/Vulnrichment v4.0 커버리지 확보 후 → **v4.0**(밴드 수치 동일, 2026-12 재평가) | `raw/official-docs/vuln-severity-cvss-v31-spec-first-official.md#C1` (Table 14 밴드 None/Low/Medium/High/Critical), `raw/official-docs/vuln-severity-cvss-v31-spec-first-official.md#C2` (정성 등급=조직 vuln mgmt 프로세스 입력), `#C3` (base score=intrinsic) | `official-standard` (FIRST.org) — **단 밴드만 표준**; "≥High 차단" 임계값 선택은 industry de-facto(`team-policy`) | "≥High 차단"의 industry de-facto 근거 미아카이브 → `UNSUPPORTED_IMPL_DECISION`(§구현가이드 §2); v3.1 Scope metric 불일치 알려짐; NVD enrichment 정책 변경(2026-04) → 신규 CVE CVSS 공백 가능(Claims To Verify) |
|
||
| D3 | **KEV override** — CISA KEV catalog 등재 CVE = CVSS 점수 무관 release-blocking | N/A (항상 적용 — exploited-in-the-wild 가 점수보다 우선) | `raw/official-docs/vuln-severity-cisa-kev-catalog-official.md#CISA-KEV-C1` (catalog 존재), `#CISA-KEV-C3` (`dueDate`=CISA 우선 시한 부여), `#CISA-KEV-C4` (ransomware 연관 식별) | `official-vendor-doc` (CISA JSON feed) — "exploited in the wild" 정의·비연방 권고·BOD 26-04 4-factor 는 CISA HTML **403 으로 미확보**(needs-confirmation, Deferred) | KEV 등재 지연(악용→catalog entry 간격); JSON feed 가용성 CI 의존; BOD rationale 미아카이브 |
|
||
| D4 | **소스 우선순위 tie-break**: Java/Gradle 의존성 → GitHub Advisory Database(GHSA) 우선 → NVD fallback | NVD 와 GHSA/벤더 점수 충돌 시 GHSA 우선(Trivy 기본). KEV 등재면 tie-break 무관 차단(D3) | `raw/official-docs/trivy-java-language-coverage.md#C5` (Java 취약점 소스 = GitHub Advisory Database (Maven)) | `official-vendor-doc` (**부분**) — *GHSA 를 소스로 씀* 만 확인; *충돌 시 GHSA 가 NVD override* 명시는 coverage 페이지에 없음(OS 패키지만 명시) → 부분 `UNSUPPORTED_DECISION` | language-package vendor>NVD 우선순위 verbatim 미확보 → Trivy scanner/vulnerability 페이지 보강 필요(Deferred + Claims To Verify) |
|
||
| D5 | **Suppression governance** — `.trivyignore`/`.trivyignore.yaml` + **만료일 필수**(`exp:YYYY-MM-DD`/`expired_at`) + `statement` 사유 + PR review approval + **무단 `.trivyignore` 변경 차단 정적 CI 게이트** | false-positive/accepted-risk suppress 필요 시 — 만료 없는 영구 ignore 금지 | `raw/official-docs/trivy-filtering-suppression-policy.md#C1` (CVE 한 줄+만료 지원), `#C3` (`exp:YYYY-MM-DD`), `#C4` (`expired_at`, 미지정시 영구유효), `#C5` (`statement`=사유 기록) | `official-vendor-doc` (Trivy filtering) | 만료 기간 길이(예: 90d)·PR 승인 권한(CODEOWNERS)·무단변경 차단 게이트 구현(regex)은 team-policy → `UNSUPPORTED_IMPL_DECISION`(§구현가이드 §3). 2026-05-25 ca-tmpl audit `.trivyignore` 무단 우회 finding 해소 대상 |
|
||
| D6 | **의존성 보안 업데이트 = Renovate primary** (`security:only-security-updates` preset → `vulnerabilityAlerts`+`osvVulnerabilityAlerts`), **Dependabot 조건부** | `gradle/libs.versions.toml` version catalog + Gradle lockfile 동시 사용 → **Renovate** (Dependabot #12557 lockfile 미갱신 버그가 supply-chain D8 locking 과 충돌). 조직이 Dependabot 표준 또는 lockfile 미사용 단순 구조 → **Dependabot** 허용 | `raw/official-docs/renovate-vulnerability-alerts-gradle-official.md#C1`·`#C2` (`security:only-security-updates`→osv+vulnerabilityAlerts), `raw/official-docs/dependabot-security-updates-gradle-official.md#C1` (security updates 정의), `#C2` (security vs version 구분), `#C3` (grouped per-ecosystem), `#C5` (manifest/lock 한정 트리거) | `official-vendor-doc` (Renovate + GitHub) | Renovate `osvVulnerabilityAlerts` experimental 상태 + vuln-alert schedule-ignore 는 presets 페이지 **미확인**(needs-confirmation); Dependabot Gradle 지원·#12557·native auto-merge 부재는 researcher finding(이 페이지 미확인); **transitive 취약점은 둘 다 직접 의존성만** → Gradle dependency constraint 수동 override 필요(§구현가이드 §4) |
|
||
| D7 | **PR-time 보완 게이트 = GitHub dependency-review-action** (`fail-on-severity: high`, required check) | 모든 PR(feature + 보안 PR). **단독 릴리즈 게이트 금지** — PR diff 전용이라 기존 의존성 전수 스캔 못함, 그건 D1 Trivy fs | `raw/official-docs/github-dependency-review-action.md#C1` (catch before introduce), `#C2` (PR 도입 취약 버전 스캔), `#C3` (default fail + required 시 merge block), `#C4` (REST API base..head diff), `#C5` (severity 커스터마이즈) | `official-vendor-doc` (GitHub) | Gradle dependency graph 가 GitHub 에 제출돼야 diff 유의미(Claims To Verify); `fail-on-severity` 정확 값은 별도 config 페이지(needs-confirmation, Deferred) |
|
||
| D8 | **EPSS escalation signal (optional, 비차단)** — EPSS ≥ 0.1 인 Low/Medium CVE → 즉시 review ticket(P1). **하드 차단 아님** | D2 에서 비차단(Low/Medium)인데 EPSS≥0.1 → escalate. High/Critical 은 이미 D2 차단 | `UNSUPPORTED_DECISION` — FIRST EPSS 페이지 미아카이브(Deferred); 0.1 임계값은 FIRST top-decile practitioner 합의일 뿐 공식 차단 mandate 없음 | `team-policy` (외부 reference: FIRST EPSS, deferred) | EPSS=확률 추정 → false positive; 0.1 임계값=조직 정책; 본 결정 자체 optional(미도입 가능) |
|
||
| D9 | **Remediation SLA by severity** — KEV/Critical: 즉시(≤Xd), High: ≤Yd, Medium: ≤Zd | 차단/escalation 된 취약점 수정 기한 | `UNSUPPORTED_DECISION` — 비-KEV SLA 수치는 외부 표준 부재(team-policy). KEV 항목만 `raw/official-docs/vuln-severity-cisa-kev-catalog-official.md#CISA-KEV-C3` (`dueDate`) 외부 anchor | `team-policy` (+ KEV 항목 official-vendor-doc anchor) | 정량 일수(X/Y/Z)는 조직 결정 — 임의 trade-off 제시 시 `UNSUPPORTED_IMPL_DECISION` |
|
||
| D10 | **의존성 라이선스 준수 스캔(license/NOTICE)** = Trivy license scanner(이미 toolchain) + dependency-review-action allow/deny license list. 금지(strong-copyleft) 라이선스 = release-blocking, allow-list 정책 | Trivy 가 이미 D1 로 채택됐고 `*gradle.lockfile` license 스캔 → **별도 license 도구 불필요**(통합). PR-time 신규 라이선스 도입 차단은 dependency-review-action allow/deny | `raw/official-docs/trivy-java-language-coverage.md#C1` (gradle.lockfile **License ✓**), `raw/official-docs/github-dependency-review-action.md#C6` (allow/deny list for licenses) | `official-vendor-doc` (Trivy + GitHub) | **금지/허용 SPDX 라이선스 목록**(어떤 id 가 release-blocking 인지)은 조직 정책 → `UNSUPPORTED_IMPL_DECISION`(§구현가이드 §5); Trivy license 감지는 Gradle cache 디렉터리(`$GRADLE_USER_HOME/caches`) 의존(`trivy-java-language-coverage` 메모 — dependency-tree EXPERIMENTAL) → Claims To Verify |
|
||
|
||
## 구현 가이드
|
||
|
||
> *결정 (Decisions)* 이 "*무엇* 을 할 것인가" 라면, 본 §는 "*어디에 어떻게* 구현될 것인가" 의 사전 명세 — *문서가 모호해서 구현자가 임의로 정해야 했던 결정* 카탈로그. 작성 목표는 다음 구현자가 *되묻지 않아도 코드를 작성할 수 있는 수준*.
|
||
>
|
||
> **본 §는 일률적 anchor list 를 강제하지 않는다.** branch 마다 구현 내용·범위가 다르므로 sub-section 은 *이 branch 의 결정과 근거에서 도출되는 것만* 작성. 어떤 branch 는 error mapping 표 + 정적 강제 카탈로그, 어떤 branch 는 migration 단계 + wiring, 어떤 branch 는 sequence + state machine. 형식 예시는 [[raw/branch-notes/feature-boundary-validation-mapping-contract]] 의 §구현 가이드 참조.
|
||
>
|
||
> **3-rule meta principle (필수 준수)**:
|
||
>
|
||
> 1. **R1. Reference 필수** — 각 sub-section / row / cell 은 본 branch 의 `Decision ID` (예: D1, D2) + 그 결정의 `Supporting Claim ID` (예: `RAW-SLUG-C1`) 를 reference. *근거 없는 결정 금지* — 모든 구현 detail 은 결정 + 근거의 *도출* 이어야 함.
|
||
> 2. **R2. UNSUPPORTED_IMPL_DECISION 명시** — 근거 raw 가 *원칙* 만 권고하고 *detail* (메커니즘 선택 / 클래스/rule 명명 / glob 패턴 / algorithm / factory API 모양 등) 은 권고하지 않는 cell 은 `UNSUPPORTED_IMPL_DECISION` 라벨 + 사용자 trade-off 근거 한 줄. 이게 *근거 있는 결정 vs 사용자 임의 trade-off* 의 경계.
|
||
> 3. **R3. OUT_OF_BRANCH_SCOPE 정제** — 본 branch 결정 범위 밖 cell 은 §구현 가이드에 *남기지 않음*. 별도 branch 또는 canonical SSOT 로 이관 (이관 history 는 별도 § "Audit & Findings" 등에 보존). 도메인 특화 detail (ca-tmpl skeleton 범위 밖) 도 동일하게 정제.
|
||
>
|
||
> **각 sub-section 의 권장 헤더 패턴**:
|
||
>
|
||
> ```markdown
|
||
> ### N. <sub-section 제목>
|
||
>
|
||
> > **Trace**: <In-scope row 들 + Decision ID + Supporting Claim ID 의 매핑 (한 줄/한 단락)>
|
||
> >
|
||
> > - **UNSUPPORTED_IMPL_DECISION**: <근거 없는 사용자 임의 결정 항목들 + 각각의 trade-off 근거 한 줄>
|
||
>
|
||
> <표 또는 명확한 구조 — 자유 텍스트 = 모호함 = 되묻기 원인>
|
||
> ```
|
||
|
||
### 1. 스캔 배선 — 단계별 스캐너 실행 (3-stage)
|
||
|
||
> **Trace**: D1 (`trivy-java-language-coverage#C1`·`#C2`, `trivy-action-github-actions#C1`·`#C2`·`#C3`), D7 (`github-dependency-review-action#C2`·`#C3`). gate 의 *release-blocking 배선*(`needs:`/`if:`) 자체는 [[raw/branch-notes/feature-ci-quality-gates-contract]] owner — 본 §는 *무엇을 어느 단계에서 스캔하는지* 만 정의하고 ci-gates 가 wiring.
|
||
>
|
||
> - **UNSUPPORTED_IMPL_DECISION**: scheduled 재스캔 **주기**(아래 표의 daily) — Trivy DB 는 ~6h 갱신이나 재스캔 cron 빈도는 외부 표준 없음(team-policy). trade-off: daily = 신규 CVE 노출 ≤24h vs CI 비용. 더 잦으면 noise/비용↑.
|
||
> - **UNSUPPORTED_IMPL_DECISION**: 멀티모듈 lockfile `--file-patterns "gradle-lockfile:*.lockfile"` — Trivy 공식 문서 미명시 workaround(GitHub Discussion #9740). trade-off: ca-tmpl 실제 lockfile 명명(`gradle.lockfile` vs `gradle/dependency-locks/*.lockfile`)에 맞춰야 함 → Claims To Verify.
|
||
|
||
| 단계(stage) | 도구 | scan-type | trigger | severity gate | 잡는 것 |
|
||
|---|---|---|---|---|---|
|
||
| PR — 신규 도입 차단 | dependency-review-action | (REST API diff) | `pull_request` | `fail-on-severity: high` | PR diff 로 *새로 들어온* 취약 의존성 (D7) |
|
||
| PR — 전체 스냅샷 | Trivy | `fs` (lockfile) | `pull_request` | `exit-code:1` + `severity:CRITICAL,HIGH` | 기존+신규 전체 의존성 CVE (D1) |
|
||
| scheduled 재스캔 | Trivy | `fs` (lockfile) | `schedule`(daily) | 동일 | 의존성 불변이라도 **새 CVE DB** 로 새로 매치된 취약점 |
|
||
| pre-release | Trivy | `image` | release tag | 동일 | 컨테이너 이미지 OS/런타임 패키지 취약점 — *severity 정책만* 본 branch, wiring 은 [[raw/branch-notes/feature-container-runtime-contract]] |
|
||
|
||
### 2. Severity 판정 매트릭스 (CVSS + KEV + EPSS)
|
||
|
||
> **Trace**: D2 (`vuln-severity-cvss-v31-spec-first-official#C1`·`#C2`·`#C3`), D3 (`vuln-severity-cisa-kev-catalog-official#CISA-KEV-C1`·`#C3`), D8 (UNSUPPORTED — FIRST EPSS deferred), D4 (`trivy-java-language-coverage#C5`). 이 매트릭스는 ci-gates·container-runtime·supply-chain 이 공유 consume 하는 **단일 severity 표준**.
|
||
>
|
||
> - **UNSUPPORTED_IMPL_DECISION**: "≥High 차단" 임계값 — FIRST.org 는 밴드(C1)만 표준화하고 *어느 등급부터 차단인지* 는 소비자 책임(C2)으로 명시. ≥High 차단은 industry de-facto(GitHub/Snyk/OSV-Scanner default). trade-off: ≥Medium 차단 시 FP noise 급증; Critical-only 차단 시 exploit code 있는 High 누수.
|
||
> - **UNSUPPORTED_IMPL_DECISION**: EPSS 임계값 `0.1` — FIRST top-decile practitioner 합의, 공식 차단 mandate 없음. trade-off: 낮추면 FP↑. (D8 자체가 optional)
|
||
|
||
| 입력 | None 0.0 | Low 0.1–3.9 | Medium 4.0–6.9 | High 7.0–8.9 | Critical 9.0–10.0 |
|
||
|---|---|---|---|---|---|
|
||
| 기본 게이트 결정 | pass | pass(report) | **warn**(advisory) | **block** | **block** |
|
||
| KEV 등재 시(D3) | block | block | block | block | block |
|
||
| EPSS ≥ 0.1 시(D8) | — | review ticket | review ticket | (이미 block) | (이미 block) |
|
||
|
||
- **소스 우선순위(D4)**: 동일 CVE 의 점수가 NVD vs GHSA 로 다르면 Java/Gradle 패키지는 GHSA 우선 → NVD fallback. (단 §Open Risk: 언어-패키지 override 명시 verbatim 미확보.)
|
||
|
||
### 3. Suppression governance
|
||
|
||
> **Trace**: D5 (`trivy-filtering-suppression-policy#C1`·`#C3`·`#C4`·`#C5`). 2026-05-25 ca-tmpl audit `.trivyignore` 무단 우회 finding 해소.
|
||
>
|
||
> - **UNSUPPORTED_IMPL_DECISION**: 만료 **기간 상한**(예: 90일)·승인 권한(CODEOWNERS 대상)·무단변경 차단 게이트의 **구현 메커니즘**(CI step regex vs CODEOWNERS protected path) — Trivy 문서는 `expired_at` 필드 *존재*만 보장(C4), 정책 수치는 권고 안 함. trade-off: 짧으면 재검토 부담↑, 길면 사실상 영구 ignore.
|
||
|
||
| 규칙 | 강제 방법 | 근거 |
|
||
|---|---|---|
|
||
| suppression 은 `.trivyignore.yaml` 단일 파일 | CI 가 인라인 ignore/CLI `--ignore` 사용 금지 검사 | C2 (구조화 YAML) |
|
||
| 각 항목 **만료일 필수** (`expired_at` 누락 금지) | CI 정적 검사: `expired_at` 없는 row fail (C4: 미지정시 영구유효 → 금지) | C4 |
|
||
| 각 항목 **`statement` 사유 필수** | CI 정적 검사: `statement` 빈 row fail | C5 |
|
||
| `.trivyignore.yaml` 변경은 **PR 승인 필수** | **역할 분리(둘 다 필요)**: ① CODEOWNERS protected path + branch protection = *merge-time* 승인 강제(GitHub native), ② CI step regex = `expired_at`/`statement` 필드 검증(CODEOWNERS 가 못 하는 내용 검증) | audit finding |
|
||
|
||
> **UNSUPPORTED_IMPL trade-off (위 표 ② 보강)**: 무단 변경 차단의 1차 메커니즘은 **CODEOWNERS protected path**(GitHub-native, merge 차단). 단 CODEOWNERS 는 *파일 변경 승인*만 강제하고 *만료일·사유 누락*은 못 잡으므로 CI regex step 이 병행 필수 — 둘은 대체재가 아니라 보완재.
|
||
|
||
### 4. 의존성 보안 업데이트 자동화 + transitive 처리
|
||
|
||
> **Trace**: D6 (`renovate-vulnerability-alerts-gradle-official#C1`·`#C2`, `dependabot-security-updates-gradle-official#C1`·`#C2`·`#C3`·`#C5`). supply-chain D3(Renovate/Dependabot) 정합.
|
||
>
|
||
> - **UNSUPPORTED_IMPL_DECISION**: patch-level 보안 PR **auto-merge** — Renovate `automerge`+`matchUpdateTypes:["patch"]` 조합은 일반 기능이나, *patch 만 auto-merge / minor·major 는 human review* 경계는 team-policy(이 페이지 미아카이브). trade-off: CI 커버리지 낮으면 취약 patch 자동 merge 위험.
|
||
> - **UNSUPPORTED_IMPL_DECISION**: `osvVulnerabilityAlerts` on/off — experimental 상태(needs-confirmation). 기본 `vulnerabilityAlerts`(GitHub Alerts, stable) primary, osv 는 maven 커버리지 검증 후 opt-in.
|
||
|
||
| 항목 | 정책 | 비고 |
|
||
|---|---|---|
|
||
| primary 도구 | Renovate `security:only-security-updates` preset | C1 (osv+vulnerabilityAlerts 활성) |
|
||
| 조건부 대안 | Dependabot (조직 표준 또는 lockfile 미사용) | #12557 lockfile+catalog 충돌 회피가 Renovate 선택 이유 |
|
||
| patch 보안 PR | CI green 시 auto-merge | UNSUPPORTED_IMPL (위) |
|
||
| minor/major 보안 PR | human review 필수 | breaking 위험 |
|
||
| **transitive 취약점** | Renovate/Dependabot 미커버(직접 의존성만) → Gradle `dependencies { constraints { } }` 또는 `resolutionStrategy.force` 로 수동 override | UNSUPPORTED_IMPL: Gradle 메커니즘 선택. supply-chain D8 locking 과 정합 필요 |
|
||
|
||
### 5. 의존성 라이선스 준수 스캔 (license/NOTICE)
|
||
|
||
> **Trace**: D10 (`trivy-java-language-coverage#C1` — `*gradle.lockfile` License ✓; `github-dependency-review-action#C5` — allow/deny license list). governing §35-E L2052 가 license scan 을 본 branch 영역으로 명시.
|
||
>
|
||
> - **UNSUPPORTED_IMPL_DECISION**: **금지/허용 SPDX 라이선스 목록** — 어떤 라이선스(예: GPL-3.0/AGPL-3.0 strong-copyleft)가 release-blocking 인지는 조직 법무/정책. Trivy/GitHub 문서는 *스캔·allow/deny 메커니즘*만 보장. trade-off: 보수적(allow-list only) = 신규 의존성 마찰↑; 관대(deny-list) = 누락 위험.
|
||
|
||
| 단계 | 도구 | 동작 | 근거 |
|
||
|---|---|---|---|
|
||
| PR-time 신규 라이선스 차단 | dependency-review-action | `allow-licenses`/`deny-licenses` 목록으로 PR diff 의 새 의존성 라이선스 검사 | `github-dependency-review-action#C6` |
|
||
| 전체 스냅샷 license scan | Trivy (D1 과 동일 fs scan) | `*gradle.lockfile` License 컬럼 — 별도 도구 불필요 | `trivy-java-language-coverage#C1` |
|
||
| forbidden 라이선스 발견 | release-blocking | CVE 차단(D2)과 동일 게이트 계열 | 정책(UNSUPPORTED_IMPL: 목록) |
|
||
|
||
## Audit & Findings — Single-Owner 정합 (cross-branch)
|
||
|
||
> 본 branch 가 §25 SSOT Owner Map 에 부재하던 **dependency vulnerability *정책* owner** 로 신설되며 해소하는 cross-branch finding. consistency-contract §전파의 *역참조 비차단 알림* 대상(쓰기 시 hook 이 ci-gates:255 → D5 참조를 3회 알림). 아래는 owner 확정 + sibling 갱신 권고(비차단 — 본 branch 머지와 독립).
|
||
|
||
**1. OWNER 확정 (Cross-Branch Conflict Procedure §25 통과)**
|
||
- §25 SSOT Owner Map `contract area` grep: "vulnerability"/"dependency vulnerability" owner **부재** 확인 → 본 branch 가 new owner 자격.
|
||
- sibling grep 결과 동일 영역 스텁 3건 발견(모두 UNSUPPORTED, 검증 깊이 0 → 시간순·도메인 우선 원칙상 전용 branch 가 SSOT):
|
||
- ci-gates **D5** + §Audit `OWNER_AMBIGUITY`: "scanner *tool 선택* 미결 → dependency-vulnerability 또는 supply-chain 으로 위임" → **본 branch D1 이 Trivy 로 확정**(미결 해소).
|
||
- supply-chain **D2** (high/critical=release-blocking, UNSUPPORTED, "CVSS 외부 표준 보강 권고") → **본 branch D2/D3 이 CVSS v3.1 + KEV 표준 부여**.
|
||
- supply-chain **D3** (Renovate/Dependabot, ~~UNSUPPORTED~~ → 2026-06-15 `official-vendor-doc` 로 전환: [[raw/official-docs/renovate-gradle-manager-official]] RENOV-GRAD-C1~C4) → **본 branch D6 이 security-update 정책 owner 로 확정** (supply-chain D3 는 Gradle 지원 범위·lockfile·supply-chain 제약 raw 소유).
|
||
|
||
**2. Sibling 역참조 갱신 권고 (비차단, 다음 작업자/`/sync`)**
|
||
|
||
| 대상 | 현재 | 갱신 후 |
|
||
|---|---|---|
|
||
| ci-gates D5 / §Audit OWNER_AMBIGUITY | "scanner tool 선택 미결" | "scanner = [[feature-dependency-vulnerability-management-contract]] D1 (Trivy, 결정 완료)" |
|
||
| ci-gates Gate 매트릭스 "vulnerability scan" owner 열 | severity=supply-chain / tool=dependency-vuln(미결) | severity·tool·suppression 정책 = dependency-vuln D1~D5; *gate 배선* 만 ci-gates |
|
||
| supply-chain D2 | UNSUPPORTED (severity 표준 보강 권고) | "severity 표준 = dependency-vuln D2(CVSS v3.1)+D3(KEV); 본 D2 는 release-block *시점/posture* 만 소유" |
|
||
| supply-chain D3 | ~~UNSUPPORTED~~ → `official-vendor-doc` 로 갱신됨 (2026-06-15: [[raw/official-docs/renovate-gradle-manager-official]] RENOV-GRAD-C1~C4 등록) | "security-update 정책 owner = dependency-vuln D6; supply-chain D3 는 Gradle 파일 패턴·lockfile 갱신·supply-chain 제약 근거를 소유" |
|
||
| **container-runtime (image-scan Decision 부재)** | image scan/Trivy/severity 결정 0건 → 본 branch 의 consumer 링크가 dangling | container-runtime 에 "image vuln scan = Trivy image, severity 정책 = dependency-vuln D2/D3 consume" Decision 신설 권고(없으면 §구현가이드 §1 pre-release row 의 wiring owner 가 미존재) |
|
||
| 프로젝트노트 §25 SSOT Owner Map | (row 없음) | 신규 row: `dependency vulnerability policy \| feature-dependency-vulnerability-management-contract \| consumers: ci-gates(gate wiring)·container-runtime(image scan)·supply-chain(release-block posture)` — **본 루프에서 프로젝트노트에 직접 추가함**(coverage Should-fix 해소) |
|
||
|
||
**3. Producer/Consumer 경계 (재진술 금지 — Reference-Only)**
|
||
- 본 branch = **producer** of severity 표준 + scanner + suppression + update 정책.
|
||
- ci-gates·container-runtime·supply-chain = **consumer** (배선/시점만). 본 branch 는 그들의 wiring 을 재진술하지 않고, 그들은 본 branch 정책을 재진술하지 않고 `[[...]] D<n>` 포인터로만 인용.
|
||
|
||
**4. OUT_OF_BRANCH_SCOPE (본 branch 로 끌어오지 않음)**
|
||
- secret scan(gitleaks) → secrets-config-source. container base image 선택 + image scan *wiring* → container-runtime. CI gate `needs:`/`if:` 배선 → ci-gates. SBOM/서명/version-locking → supply-chain. (본 branch 는 정책만 — 위 항목의 detail 을 §구현가이드에 남기지 않음.)
|
||
- **정정(2026-06-15 coverage 루프)**: `license/NOTICE scan` 은 OUT_OF_BRANCH_SCOPE 가 *아님* — governing §35-E L2052 가 본 branch 영역으로 명시했고 supply-chain 은 license 결정 0건이라 delegated owner 부재였음. → **D10 으로 본 branch 가 covered-here**.
|
||
|
||
## 엣지·실패·의존
|
||
|
||
> R4(깊이 게이트) 캡처용. 정상 경로 외에 *구현 중 부딪힐* 실패/엣지/다른 계약 의존을 미리 열거.
|
||
|
||
- **실패·엣지 경로**:
|
||
- **스캐너 DB 미가용/네트워크 차단** (CI 러너 air-gap, Trivy DB pull 실패) → 스캔이 silent pass 하면 안 됨. 기대: DB fetch 실패 = job fail (취약점 0 보고와 구분). Trivy `--exit-code` 와 별개로 DB 갱신 실패 fail-fast 검증 필요(Claims To Verify).
|
||
- **False positive 차단** (Gradle `force=true` 재정의, backport patch 미인식) → 잘못된 release block. 기대: D5 suppression 으로 만료일+사유 달고 우회, 영구 ignore 금지.
|
||
- **Transitive 취약점에 직접 fix 없음** → Renovate/Dependabot PR 생성 실패(직접 의존성만). 기대: Gradle constraint 수동 override (§구현가이드 §4), supply-chain D8 lock 재생성.
|
||
- **NVD enrichment 공백** (2026-04 정책 변경, 신규 CVE CVSS 미부여) → severity 미상으로 게이트 통과. 기대: GHSA fallback(D4) + KEV(D3) 가 점수 없는 악용 CVE 를 잡음.
|
||
- **Multi-module lockfile 미탐지** → 일부 subproject 스캔 누락(취약점 silent miss). 기대: `--file-patterns` + 각 subproject lockfile 커밋 검증.
|
||
- **`.trivyignore` 무단 추가로 긴급 우회** → 2026-05-25 audit finding. 기대: D5 정적 게이트가 무단 변경 차단.
|
||
- **dependency-review-action fail-open** (Gradle dependency graph 미제출 → 빈 diff = 0 취약점 pass) → PR 게이트가 거짓 통과. Trivy DB fail-open 과 동일 계열. 기대: graph 제출 검증 step(없으면 fail) + D1 Trivy fs 전체 스캔이 backstop(D7 단독 게이트 금지 이유).
|
||
- **다른 계약 의존 (cross-contract)**:
|
||
- **소비자 (본 branch 정책을 consume)**: [[raw/branch-notes/feature-ci-quality-gates-contract]] D5(gate wiring — vuln scan 의 release-blocking 배선), [[raw/branch-notes/feature-container-runtime-contract]] (image scan wiring, 동일 severity 정책 consume), [[raw/branch-notes/feature-build-release-supply-chain-contract]] D2(release-block 시점에 본 branch severity 표준 사용).
|
||
- **생산자 (본 branch 가 consume)**: [[raw/branch-notes/feature-build-release-supply-chain-contract]] **D8**(Gradle dependency-locking — Trivy `*gradle.lockfile` 스캔의 *선행조건*; lock 없으면 D1 스캔 불가) + **D5**(container base = Temurin JRE slim — image scan 대상). 이 계약이 바뀌면(예: lockfile 명명/위치 변경) 본 branch 의 `--file-patterns` 와 D1 스캔이 영향.
|
||
- **owner 정합 필요 (비차단 전파, §Audit)**: supply-chain D2/D3, ci-gates D5 의 `UNSUPPORTED`/`OWNER_AMBIGUITY` 스텁이 본 branch 를 정책 owner 로 가리키도록 갱신돼야 single-owner 완결.
|
||
|
||
## 검증해야 할 주장
|
||
|
||
> 공식 문서나 사례는 근거지만, 내 프로젝트에서의 동작을 자동으로 보장하지 않는다.
|
||
> 구현 전/중/후에 실제로 검증해야 하는 주장을 분리한다.
|
||
|
||
| Claim | Why uncertain | How to verify | Status |
|
||
|---|---|---|---|
|
||
| Trivy `--file-patterns "gradle-lockfile:*.lockfile"` 가 ca-tmpl 실제 lockfile 명명을 탐지 | 공식 문서 미명시 workaround(#9740); ca-tmpl lockfile 명명(`gradle.lockfile` vs `gradle/dependency-locks/*.lockfile`) 미확정 | ca-tmpl 에 `gradle dependencies --write-locks` 실행 → lockfile 생성 후 `trivy fs --file-patterns ...` 가 각 subproject 탐지하는지 verify | `needs-confirmation` |
|
||
| Java/Gradle 패키지에서 GHSA 점수가 NVD 점수를 override (D4 tie-break) | coverage 페이지는 OS 패키지만 vendor>NVD 우선 명시; 언어 패키지 override verbatim 미확보 | `trivy.dev/docs/latest/scanner/vulnerability/` 소스 우선순위 페이지 아카이브 + NVD/GHSA 점수 다른 known CVE 로 Trivy 출력 severity 확인 | `needs-confirmation` |
|
||
| Renovate `vulnerabilityAlerts` 가 schedule 을 무시하고 즉시 PR + `osvVulnerabilityAlerts` maven 커버 | presets 페이지에서 schedule-ignore·osv experimental·maven datasource 미확인(summarizer 폐기) | `configuration-options#vulnerabilityalerts`·`#osvvulnerabilityalerts` 아카이브 + 실제 repo 에 known-vuln dep 추가 → 즉시 PR 생성 verify | `needs-confirmation` |
|
||
| Dependabot Gradle security update 가 `libs.versions.toml`+lockfile 동시 사용 시 lockfile 갱신 (#12557) | about 페이지는 Gradle 지원을 링크로 위임; #12557 미해결(2025-07) | supported-ecosystems 페이지 + #12557 상태 확인; 테스트 repo 로 Dependabot security PR 이 lockfile drift 유발하는지 verify | `needs-confirmation` |
|
||
| Dependabot 은 dependabot.yml native auto-merge 없음 → Renovate 대비 복잡 | about 페이지에 `auto-merge` 키워드 0건(summarizer 확인) | `automating-dependabot-with-github-actions` 페이지 아카이브로 auto-merge 가 Actions workflow 필요함 확정 | `needs-confirmation` |
|
||
| KEV "exploited in the wild" 정의 + 비연방 권고 + BOD 26-04 4-factor | CISA HTML 403 으로 JSON feed 만 확보(정의·권고 미인용) | CISA 카탈로그 About + BOD 26-04 페이지 접근 가능 시 별도 raw 아카이브(`bod-26-04-...`) | `needs-confirmation` |
|
||
| dependency-review-action 이 Gradle 의존성 diff 를 보려면 dependency graph 제출 필요 | Gradle dependency graph 자동 추출 vs submission API 경로 불확실 | GitHub dependency graph 가 Gradle 프로젝트를 인식하는지 + `dependency-submission` action 필요 여부 확인 | `needs-confirmation` |
|
||
| 스캐너 DB fetch 실패가 silent pass 가 아니라 job fail | Trivy `--exit-code` 는 취약점 발견용; DB 갱신 실패 시 동작 미확정 | CI 에서 DB endpoint 차단 후 Trivy 실행 → exit code 검사; fail-fast 안 되면 `--exit-on-eol`/DB 검증 step 추가 | `planned` |
|
||
| scheduled 재스캔이 의존성 불변 상태에서 신규 CVE 를 실제로 잡음 | CVE DB 갱신만으로 새 매치가 생기는지 실증 필요 | known-clean dep 고정 후 일정 기간 뒤 재스캔 → 그 사이 공개된 CVE 가 잡히는지 verify | `planned` |
|
||
| `.trivyignore.yaml` 무단 변경 차단 정적 게이트가 우회 불가 (D5/audit 해소) | 게이트 구현(regex/CODEOWNERS) 미확정 | `.trivyignore.yaml` 에 만료일·사유 없는 row 추가 PR → CI fail + CODEOWNERS 승인 없이 merge 불가 verify | `planned` |
|
||
|
||
|
||
## 관심사 커버리지 (coverage-auditor 자동 생성 — 있을 때)
|
||
|
||
> `/coverage` 가 채우는 **생성물** — 손으로 유지하지 않는다. governing 문서(frontmatter `governing_docs`)가 요구하는 관심사를 이 브랜치가 빠짐없이 덮는지의 결과. 기준: `rules/coverage-gate.md`.
|
||
> 상태: `covered-here`(이 브랜치 결정) / `delegated`(다른 owner 브랜치) / `missing`(아무도 안 맡음 → Blocking).
|
||
|
||
> 출처: `/coverage` (coverage-auditor, 2026-06-15, governing = `raw/project-notes/ca-skeleton-operational-contract` §18 + §35-E L2052). 1차 Not-covered(missing 1: license scan) → 본 루프에서 D10 추가로 covered-here 전환 → Covered.
|
||
|
||
| 관심사 | 상태 | owner | 심각도 | 근거 |
|
||
|--------|------|-------|--------|------|
|
||
| CVE scan 도구 선택(SCA 스캐너) | covered-here | — | — | D1 (Trivy) |
|
||
| severity별 release-block 기준(CVSS 임계값) | covered-here | — | — | D2 (CVSS v3.1 ≥High) |
|
||
| KEV override | covered-here | — | — | D3 |
|
||
| 소스 우선순위 tie-break(GHSA vs NVD) | covered-here | — | — | D4 |
|
||
| Suppression governance | covered-here | — | — | D5 |
|
||
| 의존성 보안 업데이트 자동화(Renovate/Dependabot) | covered-here | — | — | D6 |
|
||
| PR-time 보완 게이트(dependency-review-action) | covered-here | — | — | D7 |
|
||
| EPSS escalation(비차단) | covered-here | — | — | D8 (UNSUPPORTED, optional) |
|
||
| Remediation SLA by severity | covered-here | — | — | D9 (UNSUPPORTED, team-policy) |
|
||
| **license/NOTICE compliance scan** | covered-here | — | — | **D10** (Trivy license + dep-review allow/deny; governing §35-E L2052) |
|
||
| Transitive 취약점 처리 | covered-here | — | — | §구현가이드 §4 (D6 도출) |
|
||
| Scheduled re-scan(CVE DB 갱신) | covered-here | — | — | §구현가이드 §1 |
|
||
| CI gate wiring(blocking vs warning) | delegated | [[raw/branch-notes/feature-ci-quality-gates-contract]] | OK | Out of scope; ci-gates §Coverage L283 역참조 존재 |
|
||
| dependency version locking | delegated | [[raw/branch-notes/feature-build-release-supply-chain-contract]] | OK | supply-chain D8 |
|
||
| SBOM·서명(Cosign/SLSA)·versioning·rollback | delegated | [[raw/branch-notes/feature-build-release-supply-chain-contract]] | OK | supply-chain D4/D6/D7/D9/D11 |
|
||
| container image scan wiring + base image | delegated | [[raw/branch-notes/feature-container-runtime-contract]] | Should-fix | §Audit — container-runtime 에 image-scan Decision *부재*(dangling consumer link) → 신설 권고 |
|
||
| secret scan(gitleaks) | delegated | [[raw/branch-notes/feature-secrets-config-source-contract]] | OK | Out of scope |
|
||
|
||
## 마주친 문제
|
||
|
||
> 짧은 메모만. 깊이 있는 트러블슈팅은 `raw/errors/` 로 분리하고 아래 Cluster에 연결.
|
||
|
||
- 이슈 1
|
||
- 원인:
|
||
- 시도:
|
||
- 해결: (또는 미해결이면 `needs-confirmation`)
|
||
- 별도 에러 노트로 분리됨: `[[raw/errors/<...>]]` (생성 시)
|
||
|
||
## 묶음 (이 branch에서 파생된 자료)
|
||
|
||
<!-- GENERATED: sources:start -->
|
||
- [[raw/official-docs/dependabot-security-updates-gradle-official]]
|
||
- [[raw/official-docs/github-dependency-review-action]]
|
||
- [[raw/official-docs/renovate-vulnerability-alerts-gradle-official]]
|
||
- [[raw/official-docs/trivy-action-github-actions]]
|
||
- [[raw/official-docs/trivy-filtering-suppression-policy]]
|
||
- [[raw/official-docs/trivy-java-language-coverage]]
|
||
- [[raw/official-docs/vuln-severity-cisa-kev-catalog-official]]
|
||
- [[raw/official-docs/vuln-severity-cvss-v31-spec-first-official]]
|
||
<!-- GENERATED: sources:end -->
|
||
|
||
<!-- GENERATED: interviews:start -->
|
||
- [[raw/interviews/trivy-suppression-dual-control-governance-2026-06-20]]
|
||
<!-- GENERATED: interviews:end -->
|
||
|
||
<!-- GENERATED: errors:start -->
|
||
- [[raw/errors/gitea-act-action-tag-and-dependency-graph-2026-06-20]]
|
||
<!-- GENERATED: errors:end -->
|
||
|
||
<!-- GENERATED: blog-topics:start -->
|
||
- [[raw/blog-topics/gitea-act-dependency-security-gate-portability-2026-07-02]]
|
||
- [[raw/blog-topics/trivy-suppression-governance-static-gate-2026-06-20]]
|
||
<!-- GENERATED: blog-topics:end -->
|
||
|
||
> 이 branch는 단일 노트가 아니라 **작업 묶음의 entry point**. 이 branch에서 파생된 모든 raw 노트를 카테고리별로 명시. 자식 노트가 forward link만 박아도 Obsidian backlink로 자동 발견되지만, 읽기 흐름과 분류를 위해 hub가 명시적으로 그룹화한다.
|
||
|
||
### Sub-branches (세부 작업)
|
||
|
||
- 없음 — 단일 branch 로 구현. 세부 작업 분기 불필요.
|
||
|
||
### 오류 기록 (이 branch 작업 중 발생)
|
||
|
||
- [[raw/errors/gitea-act-action-tag-and-dependency-graph-2026-06-20]] — commit 후 Gitea/act 첫 실행에서 CI 2개 잡 실패: trivy-action 태그 오타(`@0.28.0`→`@v0.28.0`) + dependency-review 의 Gitea dependency-graph API 부재(server_url 가드). egress 가설을 로그로 반증한 evidence-first 사례.
|
||
- (구현 단계 자체는 blocking 오류 없음 — lockfile 부재로 Trivy fs 가 Gradle deps no-op 인 것은 오류가 아니라 문서화된 cross-contract 선행조건, supply-chain D8.)
|
||
|
||
### 면접 준비 (이 작업에서 나올 수 있는 면접 질문)
|
||
|
||
- [[raw/interviews/trivy-suppression-dual-control-governance-2026-06-20]] — suppression 영구 우회 구멍을 CODEOWNERS(merge-gate) + `verifyTrivyignore`(CI field-gate) 이중 통제로 막은 설계, Renovate vs Dependabot 선택 근거.
|
||
|
||
### 강의 (이 작업을 위해 학습한 강의)
|
||
|
||
- 없음 — 외부 강의 학습 없이 공식 문서(Trivy/CISA-KEV/FIRST/Renovate/GitHub) 근거로 구현.
|
||
|
||
### job-posting tie-ins (이 작업에서 파생된 글감)
|
||
|
||
- [[raw/blog-topics/trivy-suppression-governance-static-gate-2026-06-20]] — Gradle 정적 게이트로 supply-chain suppression 거버넌스(만료일·사유 강제) 강제하기 + audit finding 해소.
|
||
- derived blog: 생성 전. 생성 시 `wiki/blog/<slug>-YYYY-MM-DD.md` 후보
|
||
|
||
## 관련 일일 노트
|
||
|
||
> 이 브랜치를 작업한 날짜들. 양방향 nav 유지.
|
||
|
||
- `[[raw/daily-notes/YYYY-MM-DD]]`
|
||
- `[[raw/daily-notes/YYYY-MM-DD]]`
|
||
|
||
## 완료 후 정리
|
||
|
||
> 머지/종료 시점에 채움. `/ingest`가 이 섹션을 기준으로 wiki/projects/에 추출.
|
||
|
||
- PR 링크:
|
||
- 리뷰 메모:
|
||
- 머지 결과 / 배포 환경: (로컬/dev/staging/prod 어디까지 검증됐는지)
|
||
- **wiki 추출 대상** (verified만, `wiki/projects/`로만 추출):
|
||
- `actually-implemented` 항목:
|
||
- `locally-verified` 항목:
|
||
- `prod-verified` 항목:
|
||
- **추출하지 않을 항목** (planned / documented-only / abandoned):
|