render_summary_table() 을 이미지 알파벳순(리포트 파일명 순) 대신 차트 이름
오름차순으로 묶고, 같은 차트 안에서는 실효 CRITICAL/HIGH 내림차순으로 정렬한다.
scan-sbom.sh 의 trivy-summary.md 는 이미 차트별로 묶여 있는데 cve-gate.md/brief 는
아니어서 두 리포트의 정렬 기준이 서로 달랐다.
이 과정에서 report_stem_to_image() 와 같은 종류의 문제를 발견해 같이 고쳤다 —
이미지 하나가 여러 차트에 쓰이면 리포트 파일명→차트 매핑이 마지막 차트만 남겨,
차트별로 묶었을 때 다른 차트의 노출이 조용히 빠졌을 것이다(scan-sbom.sh 에서
실측으로 확인된 것과 동일한 패턴). 신규 charts_of_image() 로 sbom-index.tsv 를
전부 읽어 이미지→차트 목록을 보존하고, render_summary_table 표시에서만 이걸로
펼친다 — 게이트 판정(evaluate 등)에 쓰이는 대표 차트/버전은 안 건드린다.
로컬에서 (a) flowise/cnpg-cluster/etcd 3개 차트 실제 데이터로 정렬 확인
(b) 이미지 하나가 차트 두 개에 쓰이는 합성 케이스로 양쪽에 다 나오는지 확인.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
"실패 \$nf개" — \$nf 뒤에 중괄호 없이 한글이 바로 붙어 있어, LANG=C.UTF-8 로케일에서
bash가 변수명 경계를 잘못 인식해 "nf<한글 바이트>: unbound variable"로 죽었다
(set -u). 로컬에서 flowise 차트 SBOM 생성 중 실제로 재현됨 — SBOM 생성 자체(6/6
성공)는 끝난 뒤 재시도 필요 여부를 보고하는 로그 문장에서만 발생해 데이터 손상은
없었다. \${nf}개 로 중괄호 처리해 고쳤다. 같은 패턴(바인딩 안 된 \$var 뒤에 한글이
구분자 없이 붙는 경우)이 다른 파이프라인 스크립트에도 있는지 전수 검색했고 이
한 곳뿐이었다.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
trivy-summary.md/tsv 를 이미지 심각도 건수 내림차순 flat 목록 대신 차트 이름별로
묶고, 차트마다 합계 행(이미지 수 + 심각도별 합)을 붙인다.
- 이미지 하나가 여러 차트에 쓰이면(예: busybox) 예전엔 sbom-index.tsv 를 접어(마지막
차트만 남김) 요약해 다른 차트의 노출이 조용히 빠졌다 — 이제 $INDEX 를 직접 읽어
차트마다 한 행씩 보여준다(CHARTMAP 중간 파일은 더 필요 없어져 제거).
- 카탈로그는 같은 차트의 여러 버전을 동시에 보관하는 "버전 보관소"라, 요약 표는
차트 이름별 최신 버전만 표시한다(표를 "차트 종류" 단위로 읽기 쉽게 하려는 목적).
구버전은 표에서만 빠지고 실제 스캔·게이트 판정 대상에서는 빠지지 않는다 —
cve-gate.md/json 은 전 버전을 그대로 판정한다. 몇 건이 빠졌는지는 요약 상단에 표시.
로컬에서 (a) 이미지 하나가 차트 두 개에 쓰이는 경우 양쪽 합계에 정확히 반영되는지
(b) 같은 차트 이름에 버전이 두 개일 때 최신만 남고 구버전 건수가 안내되는지
(c) 실제 flowise 차트(이미지 6개) 대상 로컬 파이프라인 실행
으로 확인했다.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
전체 카탈로그(45+ 차트) 스캔을 실제로 CI에서 돌려보니 GITHUB_STEP_SUMMARY 가
1MB 제한에 걸려 cve-gate.md(2.2MB) 업로드가 중단됐다 — CVE 개별 상세(차단
항목·벤더 하향 등급 등)가 이미지당 CVE 수에 비례해 불어나는 게 원인이다.
render_summary_table()로 차트·이미지별 건수 표를 뽑아 render_md(전체)와
render_brief_md(신규, Job Summary용) 양쪽에서 재사용한다. brief 는 건수 표 +
누락/커버리지 이상 건수만 담고, CVE 개별 상세는 아티팩트(cve-gate.md/json)를
보라고 안내한다 — 이미지 수에는 선형으로 늘지만 이미지당 CVE 수에는 무관해
카탈로그가 커져도 1MB 제한에 걸리지 않는다.
sbom.yml 의 Job Summary 스텝을 --brief-md 출력으로 교체했다.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
security-catalog 프로젝트에서 자체 빌드 이미지 3종을 실제로 로컬 빌드·게이트
검증하는 과정에서 발견한 문제들:
- extract-helm-images.sh 가 `image:` 필드만 잡고 `imageName:`(CNPG Cluster CRD 관례)
은 놓쳐, cnpg-cluster 차트의 이미지가 SBOM·스캔·게이트 어디에도 안 나타났다.
- patch-catalog-tag.py 의 split 포맷 패처가 registry 필드가 따로 없고 repository 에
registry+repo 를 합쳐 쓰는 차트(cloudnative-pg 오퍼레이터, 업스트림 템플릿이
image.registry 를 아예 참조하지 않음)에서 tag 만 조용히 갱신하고 repository 는
그대로 남겨 깨진 참조를 만들 수 있었다.
- CoverageProbe(센티널 패키지 주입 재스캔으로 "0건"과 "측정 안 됨"을 구분)가
이식되지 않아, 전 심각도 0건인 자체 빌드 이미지가 실제로는 깨끗한데도 게이트가
"데이터 커버리지 이상"으로 오탐 처리했다 — security-catalog 의 scan-sbom.sh 를
이식해 해소. cve-gate.py 는 이미 이 키를 읽도록 구현돼 있어 소비 쪽 변경은 없다.
rpm(SUSE)·deb(Debian)·apk(Alpine) 세 센티널 경로와 병렬 스캔 회귀를 로컬에서
확인했고, 이식 후 cloudnative-pg·cnpg-postgresql 게이트가 실제로 FAIL→PASS 로
바뀌는 것도 확인했다.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
scan-sbom.sh 에 커버리지 자가진단이 없는데도 체크리스트가 cov= 확인을 지시해
같은 문서 104-106줄과 모순됐다. 실제 동작(findings 0건 시 보수적 실패)과 판단
방법으로 교체. Dockerfile 헤더 주석의 doc/scripts/ 경로도 scripts/pipeline/ 로
갱신(경로 이전 시 누락됨).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
xargs -I{} 가 탭을 공백으로 바꿔 이미지명·SBOM 경로가 한 덩어리가 되고
"failed to open sbom file" 로 스캔이 실패했다(로컬 macOS 검증 중 발견).
security-catalog 프로젝트에서 이미 확인된 동일 버그 — read 루프 +
배치 wait 방식으로 교체하고, 대상/결과 수 불일치 시 실패시키는 누락
검출 가드를 추가했다(스캔 안 됨이 취약점 없음으로 오인되는 것을 막기 위함).
로컬에서 main 모드로 재검증: 2/2 성공, 이전 우회 실행과 동일한 집계치.