React CVE-2025-55182 보안 이슈, 배포 단계에서 자동으로 차단하기
React CVE-2025-55182 취약점 발견을 계기로, Trivy를 도입하여 위험한 배포를 자동으로 차단하고 슬랙으로 알림을 받는 파이프라인 구축 과정을 공유합니다.
2025년 12월 30일
최근 React 관련 보안 취약점인 CVE-2025-55182 소식을 접했습니다. 무려 CVSS 점수 10점짜리 크리티컬 이슈였습니다. 10점이면 묻지도 따지지도 말고 바로 업데이트해야 하는 수준인데요.
이 이슈를 쉽게 풀어서 설명하면 다음과 같습니다.
- 대상:
react-server-dom-webpack등 서버 컴포넌트(RSC) 관련 패키지 19.x 버전 - Pre-authentication: 해커가 아이디/비밀번호를 몰라도, 로그인 안 한 상태에서도 공격 가능합니다.
- Remote Code Execution (원격 코드 실행): 해커가 내 서버에 심어둔 명령어를 실행할 수 있습니다. (예: DB 삭제, 데이터 탈취, 채굴 프로그램 설치 등)
- Unsafe Deserialization (안전하지 않은 역직렬화): 사용자가 보낸 데이터(Payload)를 서버가 믿고 바로 객체로 변환하다가, 그 안에 숨겨진 악성 코드가 실행되어 버리는 문제입니다.
한마디로 19 버전 RSC를 돌리고 있는 서버는 그냥 다 털릴 수 있는 수준입니다. 엄청 많이 사용하는 리액트에서 이런 이슈가 발생했다는게 충격적이었습니다. 근데 이 이슈를 보면서 문득 드는 생각이 있었습니다.
- 의존성 지옥: 프로젝트의 의존성이 복잡하게 얽혀 있다면 버전을 올리는 것 자체가 큰일입니다.
- 정보의 비대칭: 더 큰 문제는 "애초에 이런 보안 이슈를 모른다면?" 입니다.
저조차 이 이슈를 유튜브 알고리즘을 통해 우연히 알게 되었습니다. 매일 쏟아지는 수많은 CVE 정보를 개발자가 일일이 확인하고 수동으로 패치하는 것은 불가능에 가깝습니다. 프로젝트에서 사용하는 라이브러리가 한두 개가 아니니까요.
그럼 배포 파이프라인에서 위험한 버전이 감지되면, 취약점 데이터베이스와 대조해서 알아서 배포를 멈춰줄 순 없을까라는 생각에 찾아보니 도커 컨테이너 배포단에서 보안 취약점을 체크해주는 Trivy라는 도구가 있었습니다.
1. Trivy란?
Trivy는 컨테이너 이미지와 파일 시스템을 검사해주는 올인원 오픈소스 보안 스캐너입니다.
작동 원리
- 데이터베이스 동기화: NVD(미국 국립 취약점 DB) 등 전 세계 보안 DB를 실시간으로 가져옵니다.
- 스캔: Docker 이미지나 파일 시스템을 뜯어서 두 가지를 확인합니다.
- OS 패키지: 리눅스 시스템 패키지 (OpenSSL, CURL 등)
- 애플리케이션 의존성:
package-lock.json,yarn.lock등을 분석해 사용 중인 라이브러리(React, Next.js 등) 버전 확인.
- 매칭: 내 프로젝트 속 라이브러리 버전과 보안 DB의 취약점 정보를 대조하여 경고를 띄웁니다.
2. 전략: 위험도에 따른 "Two-Track" 대응
보안도 중요하지만, 사소한 경고 하나 때문에 모든 배포가 막히면 개발 생산성이 떨어집니다. 특히 Node.js 생태계 특성상, 내가 직접 설치하지 않은 하위 의존성에서 High 취약점이 쏟아져 나오기도 하고, 아직 라이브러리 제작자가 패치를 내놓지 않은 경우도 많습니다.
따라서 위험도(Severity) 에 따라 대응 방식을 다르게 가져가기로 했습니다.
A. 차단
- 대상:
CRITICAL(치명적, 점수 9.0~10.0) - 예시: Log4Shell, RCE, 이번 React 이슈 같은 결함.
- 조치: 취약점 발견 시 배포 파이프라인 즉시 중단. (귀찮아도 이건 고쳐야 배포 가능)
B. 경고
- 대상:
HIGH,MEDIUM(높음/중간) - 조치: 취약점을 발견해도 배포는 허용하되, 슬랙으로 리포트를 전송.
- 목적: 당장 서비스가 죽진 않으니 배포는 하되, 개발자가 인지하고 권고 시일 내에 수정하도록 유도.
3. GitHub Actions 적용 코드
deploy.yml의 빌드 단계에 아래 코드를 추가했습니다.
Trivy로 파일 시스템을 스캔하고, 그 결과를 텍스트 파일로 저장한 뒤 쉘 스크립트로 분석하여 분기 처리하는 방식입니다.
# ----------------------------------------------------------------
# 1. Trivy 파일시스템 스캔 (fs)
# ----------------------------------------------------------------
- name: Run Trivy (Filesystem Scan)
uses: aquasecurity/trivy-action@0.29.0
with:
scan-type: "fs"
scan-ref: "."
format: "table"
output: "trivy-report.txt"
exit-code: "0" # 일단 0으로 통과시키고, 뒤에서 쉘 스크립트로 직접 제어
severity: "CRITICAL,HIGH,MEDIUM"
env:
TRIVY_DISABLE_VEX_NOTICE: "true"
# ----------------------------------------------------------------
# 2. 결과 분석 및 알림 (Block or Notify)
# ----------------------------------------------------------------
- name: Analyze Trivy Results & Notify
id: security_check
run: |
# 보고서 내용 읽기 (너무 길면 슬랙 전송 실패하므로 앞부분만 자름)
REPORT=$(cat trivy-report.txt | head -c 2000)
# [함수] 슬랙 전송용 함수
send_slack() {
local color=$1
local icon=$2
local message=$3
jq -n \
--arg username "$SLACK_USERNAME" \
--arg icon "$icon" \
--arg text "$message" \
--arg report "$REPORT" \
--arg color "$color" \
'{
username: $username,
icon_emoji: $icon,
text: $text,
attachments: [{
color: $color,
title: "Trivy Scan Report",
text: ("```" + $report + "```")
}]
}' > payload.json
curl -X POST -H 'Content-type: application/json' --data @payload.json "$SLACK_WEBHOOK_URL"
}
# 1. 취약점 없음 (Total: 0)
if grep -q "Total: 0" trivy-report.txt; then
echo "✅ No vulnerabilities found."
exit 0
fi
# 2. CRITICAL 발견 -> 배포 차단 (Exit 1)
# "CRITICAL: 0"은 무시하고, "CRITICAL: 1" 이상인 경우(숫자 1~9)만 잡습니다.
if grep -E -q "CRITICAL: [1-9]" trivy-report.txt; then
echo "🚨 Critical issues found!"
send_slack "#ff0000" ":rotating_light:" "🚨 *치명적인 보안 취약점(CRITICAL) 발견! 배포를 중단합니다.*"
exit 1
fi
# 3. HIGH/MEDIUM 발견 -> 경고만 함 (Exit 0)
# 여기도 마찬가지로 개수가 1개 이상일 때만 반응하도록 수정
if grep -E -q "HIGH: [1-9]|MEDIUM: [1-9]" trivy-report.txt; then
echo "⚠️ Non-critical issues found."
send_slack "#ffcc00" ":warning:" "⚠️ *보안 경고(High/Medium)가 있습니다.* (배포는 진행됨)"
exit 0
fi
참고: Trivy의 자동 감지 능력
Trivy의 파일시스템(fs) 스캔 모드는 지정된 폴더(scan-ref: ".")를 샅샅이 뒤지면서 파일을 자동으로 찾습니다.
pnpm-lock.yamlpackage-lock.jsonyarn.lockrequirements.txt(Python)pom.xml(Java)
이 파일들이 보이면 의존성 파일인줄 알고 알아서 파싱합니다. 특히 pnpm-lock.yaml 같은 Lock 파일은 pnpm의 트리구조 덕분에 라이브러리의 족보(Transitive Dependency)가 전부 적혀 있기 때문에,
Trivy는 이 족보를 수천 개의 CVE 데이터베이스와 대조하여 숨어있는 취약점까지 찾아낼 수 있습니다.
4. 실제 적용 결과
상황 1: Critical 이슈 발견 시 (배포 중단)
슬랙으로 "🚨 치명적인 보안 취약점 발견! 배포를 중단합니다" 라는 알림이 오고, 실제로 GitHub Actions가 실패 처리됩니다. 해당 이슈 Url 클릭 시 nvd 정보 페이지로 이동합니다.
상황 2: High/Medium 이슈 발견 시 (배포 진행)
배포는 정상적으로 진행되지만, 슬랙으로 경고 알림이 옵니다. GitHub Actions 로그에서 상세 링크를 타고 들어가면 어떤 라이브러리가 문제인지 확인할 수 있습니다.
마무리
이번 React 이슈(CVE-2025-55182)를 보며 다시 한번 느꼈습니다. 아무리 많이 쓰는 메이저 라이브러리라도 언제든 털릴 수 있고, 이를 빨리 알아채고 대응하는 것이 중요합니다.
하지만 이를 인간이 직접 매일 체크하는 것은 불가능합니다. 귀찮아서, 혹은 몰라서 지나칠 확률이 매우 높으니까요. 보안 검사를 자동화해서 파이프라인에 심어두는 것부터 시작해야 될 것 같습니다..