콘텐츠로 이동

의존성·이미지 취약점 검사

원천 · framework/evomind/web/workflow-project-evo-service기준 · 릴리스 v0.12.0커밋 · 2e32c6cc파일 · docs/operations/vulnerability-scan.md기준선 · 2026-11-12

CI 가 evo-api·evo-chat·작업 이미지(evo-workspace)와 프론트 npm 잠금 파일의 알려진 취약점(HIGH·CRITICAL)을 Trivy 로 찾고 보고서를 남긴다. 지금은 파이프라인을 막지 않고 알리기만 한다. 통과 기준(차단 조건)은 보고서를 몇 번 본 뒤 사용자가 정한다(§4).

대상 방법 보고서
evo-api 이미지 backend_build 가 만든 jar 로 Dockerfile.release 를 빌드해(게시하지 않음) 이미지 검사 — 기반 이미지의 OS 패키지와 jar 안 라이브러리 reports/trivy-evo-api.txt
evo-chat 이미지 frontend_build 의 dist 로 Dockerfile.web 을 빌드해 이미지 검사(nginx 기반 이미지) reports/trivy-evo-chat.txt
프론트 npm 의존성 package.json·package-lock.json 을 Trivy fs 로 검사(빌드 결과에는 라이브러리 버전이 남지 않으므로 잠금 파일을 본다) reports/trivy-npm.txt
evo-workspace 이미지(workspace-runner 포함) scripts/workspace/build.sh 로 빌드해 이미지 검사 reports/trivy-evo-workspace.txt
  • 보고서 끝의 --- 검사한 대상 --- 목록이 실제로 본 대상(OS 패키지, jar 안 Java 라이브러리, npm 등)이다. 취약점이 0건이어도 이 목록에 Java (jar) 같은 대상이 있으면 그 라이브러리까지 검사한 것이다.
  • reports/summary.txt 에 보고서마다 HIGH h, CRITICAL c 요약이 있다. 검사기를 실행하지 못한 보고서는 결과 없음 이다.
  • job 이름은 vuln_scan(stage release)이고 보고서는 파이프라인 아티팩트(30일 보관)로 받는다. 작업 이미지는 MR 의 workspace_image_test·develop 의 dev_workspace 도 같은 스크립트로 검사한다(trivy-report.txt).
상황 동작
develop push, 릴리스 태그 항상
MR 의존성·Dockerfile·검사 스크립트·CI 설정이 바뀐 경우에만(백엔드 *.kts·gradle.properties, 프론트 package*.json, Dockerfile*, docker/**, scripts/security/**, scripts/workspace/**, .gitlab-ci.yml)
예약 파이프라인(주 1회) 코드가 바뀌지 않아도 새로 공개된 취약점을 잡는다. 예약 파이프라인은 게시·배포 job(dev_*·deploy_dev*·cleanup_old_names_*)을 돌리지 않는다
  • 예약 일정(2026-10-30 등록): 이 프로젝트의 파이프라인 일정 취약점 검사(GH-171) — 주 1회 새벽 — 대상 브랜치 develop, 주기 0 2 * * 1, 시간대 Seoul(매주 월요일 02:00 KST). 일정은 만든 사용자의 권한으로 돌고, 일정 시간대 기본값은 UTC 라서 시간대를 지정하지 않으면 9시간 뒤(낮)에 돈다. GitLab 의 일정 확인 주기 때문에 정시가 아니라 몇 분 뒤(예: 02:03)에 시작한다. 새로 만들 때는 프로젝트 빌드 → 파이프라인 일정 에서 같은 값으로 만든다. 한 번 수동으로 실행해 보면 게시·배포 job 이 만들어지지 않는 것을 확인할 수 있다(dev_*·deploy_dev*·sonarqube_* 없이 빌드·검증·vuln_scan 만 돈다 — 2026-10-30 #4925 로 확인).
  • 전체 프로젝트가 같은 시간대에 몰리지 않게 새벽 02:00~05:00 안에서 프로젝트마다 30분씩 나눈다(evo-service 02:00, evo-cli 02:30, evo-dispatch 03:00, evo-emulator 03:30, evo-mac 04:00, evo-windows 04:30, evo-docs 05:00).
  • 검사가 결과 없음으로 끝나면 vuln_scan 이 이미지를 다시 빌드해 한 번 더 시도한다. 개발 러너는 다른 프로젝트 CI 와 Docker 를 같이 써서 빌드한 이미지가 검사 직전에 사라진 적이 있다(스케줄 #4925 의 evo-chat, 원인 미확인). 두 번 다 실패하면 결과 없음으로 남기고 계속한다.
  • 검사기(TRIVY_IMAGE, 기본 aquasec/trivy:0.57.1)나 취약점 DB 를 받을 수 없는 환경이면 보고서에 결과 없음 을 적고 job 은 실패하지 않는다. 폐쇄망은 미러 이미지와 DB 를 준비해 TRIVY_IMAGE 를 바꾼다.
  • 표의 Library(라이브러리)·Installed Version·Fixed Version 으로 무엇을 올려야 하는지 안다. Fixed Version 이 비어 있으면(affected·fix_deferred) 아직 고쳐진 버전이 없다 — 기반 이미지가 갱신될 때까지 기다리거나 그 패키지를 이미지에서 뺄 수 있는지 본다.
  • 조치는 이슈로 한다: 백엔드는 Gradle 의존성·Spring Boot 버전, 프론트는 npm audit·npm update, 이미지는 기반 이미지 태그 갱신, 바이너리(evo·glab)는 해당 프로젝트에 알린다(작업 이미지의 evo·glab 취약점은 evo-cli 에 알렸다).
  • Trivy 가 보고한 심각도와 실제 위험은 다를 수 있다(그 코드 경로를 쓰지 않는 경우). 판단 근거를 이슈에 적는다.
  1. 몇 주 동안 보고서를 모아 어떤 항목이 반복되는지 본다.
  2. 고칠 수 있는 항목은 이슈로 처리하고, 고칠 수 없는 항목(상위 프로젝트 수정 대기)은 예외 목록(.trivyignore)에 이유와 함께 둔다.
  3. 사용자가 기준(예: CRITICAL 이 수정 가능하면 실패)을 정하면 scripts/security/ 의 검사 스크립트에 종료 코드 규칙을 넣고 vuln_scan 을 차단으로 바꾼다. 그 전에는 차단하지 않는다.
터미널 창
sh scripts/security/test-scan.sh # 스크립트 시험(도커 대역, 도커 없이)
sh scripts/security/scan-image.sh <이미지:태그> trivy-image.txt # 이미지 검사
sh scripts/security/scan-fs.sh <폴더> trivy-fs.txt # 폴더(npm 잠금 파일 등) 검사

검사기 이미지를 받을 수 있는 환경과 Docker 가 필요하다.