시스템별 CVE 영향도 / 패치 상태 / 조치 진행 / 조치결과 검증을 단일 Go 바이너리 로 자동화하는 CLI 감사 도구.
Audit CVE impact, remediation, and verification across systems with a single static Go binary.
본 도구는 임시 조치(모듈 차단, 설정 토글 등) 경로에 집중한다. 영구 조치(패키지 업데이트)는 사용자가 배포판 패키지 매니저로 별도 적용해야 한다. 정책: 도구가 자동 실행하는 것은 임시조치뿐이며
apt/dnf/zypper는 호출하지 않는다 — 패키지 업데이트가 불가한 상황에서 즉시 적용 가능한 조치를 제공하는 것이 본 도구의 역할.
| CVE | 별칭 | 영향 컴포넌트 | 임시 조치 (도구 자동) |
|---|---|---|---|
| CVE-2026-31431 | Copy Fail (CISA KEV 2026-05-01) | Linux 커널 algif_aead (AF_ALG + splice) |
로더블(=m): 모듈 차단·언로드 · built-in(=y, RHEL 흔함, Stage 11): grubby --update-kernel=ALL --args=initcall_blacklist=algif_aead_init + 재부팅 |
| CVE-2026-43284 | Dirty Frag #1 | Linux 커널 esp4/esp6 (IPsec) |
두 모듈 차단·언로드 (IPsec 사용 환경 주의) |
| CVE-2026-43500 | Dirty Frag #2 | Linux 커널 rxrpc/afs |
두 모듈 차단·언로드 |
| CVE-2026-46300 | Fragnesia | Linux 커널 XFRM ESP-in-TCP (esp4/esp6/rxrpc) |
세 모듈 차단·언로드 (43284/43500과 모듈 일부 공유) |
| CVE-2026-23918 | Apache HTTP/2 double-free | Apache HTTPD mod_http2 (< 2.4.67) — Stage 12 추가 |
<IfModule http2_module>Protocols http/1.1</IfModule> 드롭인 conf + systemctl reload (모듈은 적재 유지, HTTP/2 협상만 차단) |
| CVE-2026-46333 | ssh-keysign-pwn (ptrace exit-race) | Linux 커널 __ptrace_may_access() (Yama LSM) — Stage 13 추가 |
/etc/sysctl.d/cpa-cve-2026-46333.conf 드롭인 + sysctl -w kernel.yama.ptrace_scope=2 (즉시 적용 + 재부팅 후 유지). ⚠ 부분 차단 — 벤더 커널 패치 권장 |
처음 4개 CVE는 Linux 커널 모듈 LPE, CVE-2026-23918은 첫 비-커널(데몬) 사례, CVE-2026-46333은 첫 비-모듈 커널 CVE(Yama LSM sysctl). 영구 해결은 모두 벤더 패키지 업데이트.
본 도구가 검토한 CVE는 4가지로 분류한다. 위 "지원하는 CVE" 표는 §1만 보여주며, 나머지 분류·근거·출처는 doc/CVE-STATUS.md에서 단일 색인으로 관리한다.
| § | 분류 | 현재 항목 (2026-05-22) | cpa --list |
|---|---|---|---|
| §1 | 처리 반영 (Implemented) | 위 표의 6건 | ✅ 노출 |
| §2 | 영향 있으나 이미 차단됨 | CVE-2026-31635 (DirtyDecrypt) — rxrpc 변종, CVE-2026-43500/46300 임시조치로 함께 차단 |
❌ 미노출 |
| §3 | 처리 예정 (Backlog) | 현재 없음 (Stage 13 완료로 CVE-2026-46333은 §1로 이동) | ❌ 미노출 |
| §4 | 조치 안 함 (Reviewed — No Action) | CVE-2025-34291 (Langflow CORS, KEV 2026-05-21) · CVE-2026-2005/-2006 (PostgreSQL pgcrypto) · CVE-2026-32710 (MariaDB JSON) · CVE-2026-33032 (nginx-ui MCP) · CVE-2026-34926 (Trend Micro Apex One, KEV 2026-05-21) · CVE-2026-42945 (NGINX Rift) · CVE-2026-20182 (Cisco SD-WAN) · CVE-2026-3854 (GitHub Enterprise) · CVE-2026-35414 (SplitSSHell) | ❌ 미노출 |
각 항목의 분류 근거·자동화 적합성 평가·인용 출처는 doc/CVE-STATUS.md 본문, 외부 자료 URL은 doc/references.md 참조.
각 커널 CVE 플러그인은 자체 conf 파일을 /etc/modprobe.d/에 별도로 작성하므로(cpa-cve-<id>.conf), 모듈이 겹쳐도 한 CVE의 rollback이 다른 CVE의 차단을 의도치 않게 해제하지 않는다. 차단 라인은 install X /bin/false (modprobe 호출 시 명시적 exit 1) + blacklist X (udev/aliases 자동 로드 차단)를 동시 기록 (defense-in-depth).
CVE-2026-31431은 algif_aead의 빌드 형태에 따라 두 경로를 자동 분기 — 로더블(=m)이면 modprobe 차단, RHEL 계열에 흔한 built-in(=y)이면 커널 명령행에 initcall_blacklist=algif_aead_init 인자 추가 (grubby 미존재 시 /etc/default/grub 수기 가이드).
CVE-2026-23918은 detected Apache binary(apache2/httpd)에 따라 /etc/apache2/conf-enabled/ 또는 /etc/httpd/conf.d/에 드롭인 파일을 작성. graceful reload(systemctl reload)로 무중단 적용 — 워커가 받는 새 연결부터 HTTP/1.1만 협상.
CVE-2026-46333 (ssh-keysign-pwn / ptrace exit-race)은 Yama LSM 활성 여부를 먼저 확인 (/proc/sys/kernel/yama/ptrace_scope 존재). 활성이면 /etc/sysctl.d/cpa-cve-2026-46333.conf 드롭인을 작성하고 sysctl -w kernel.yama.ptrace_scope=2로 즉시 반영 — 재부팅 후에는 systemd-sysctl.service가 자동 재적용하므로 재부팅 불요. conf 본문에 # previous=N을 기록해 rollback 시 이전 값을 복원한다. Yama LSM 미활성 커널에서는 임시조치 불가로 안내만 표기. 결함의 본질이 __ptrace_may_access() 논리 결함이므로 ptrace_scope=2는 부분 차단 — 운영자는 가능한 빨리 벤더 커널 패키지 업데이트를 적용해야 한다.
SHA256SUMS 의 항목은 원본 파일명(cpa-linux-amd64 / cpa-linux-arm64)으로 기록되므로, 다운로드 시 원본 파일명을 유지해야 검증이 동작한다 (아래 참고 박스).
# linux/amd64 예시 — 원본 파일명으로 받아 검증 후 이름 변경
curl -L -O https://github.com/barmi/cve-patch-auditor/releases/latest/download/cpa-linux-amd64
curl -L -O https://github.com/barmi/cve-patch-auditor/releases/latest/download/SHA256SUMS
# 무결성 검증 (`cpa-linux-amd64: OK` 가 출력돼야 함)
shasum -a 256 -c SHA256SUMS --ignore-missing
# 검증 통과 후 실행 편의를 위해 짧은 이름으로 변경
mv cpa-linux-amd64 cpa
chmod +x cpa
./cpa --version참고 —
no file was verified에러가 난다면 (#1)curl -L -o cpa ...(소문자-o)로 받으면 작업 디렉토리에cpa-linux-amd64파일이 없어shasum -c --ignore-missing이 SHA256SUMS의 모든 항목을 "missing"으로 건너뛰고 검증된 파일이 0개 →shasum: SHA256SUMS: no file was verified로 종료된다 (WSL/Ubuntu 등에서 동일). 위 예시처럼-O(대문자)로 원본 파일명을 유지한 채 먼저 검증하고, 그 다음mv로 이름을 바꿔야 한다.또는 SHA256SUMS를 받지 않고 한 줄로 해시만 대조해도 된다:
# 기대 해시 (SHA256SUMS의 cpa-linux-amd64 행) 와 실측 해시를 직접 비교 curl -sL https://github.com/barmi/cve-patch-auditor/releases/latest/download/SHA256SUMS \ | awk '$2=="cpa-linux-amd64"{print $1}' shasum -a 256 cpa | awk '{print $1}'
git clone https://github.com/barmi/cve-patch-auditor.git
cd cve-patch-auditor
make build # 호스트용
make dist # linux amd64+arm64 정적 바이너리 (bin/)요구사항: Go 1.23 이상 (현재 개발은 1.26). 외부 모듈 의존 0.
$ cpa --help
USAGE
cpa [flags]
FLAGS
-h, --help 이 도움말 표시
-v, --version 버전 정보 표시
--list 내장된 CVE 플러그인 목록 표시
--cve=ID 처리할 CVE 지정 (반복 가능; 미지정 시 전체)
--phase=NAMES 처리할 phase 쉼표 구분
(assess,remediate,verify,rollback;
기본 assess,remediate,verify)
--rollback 기본 phase 대신 rollback만 수행
(--apply 또는 --dry-run 명시 필수: 파괴적 작업)
--apply 실제 변경 적용 (없으면 dry-run으로 강제)
--dry-run dry-run 모드 (--apply가 있어도 우선 적용)
--no-elevate sudo 자동 권한 상승 비활성
--json 결과를 stdout에 한 줄당 JSON으로 출력
--report=FILE 마크다운 리포트 파일 경로
--log-file=FILE 로그 파일 경로 (기본: 실행파일 옆 cpa.log)
--verbose DEBUG 레벨 로그
--no-log 파일 로그 비활성 (stderr만)
--lang=LANG 언어 강제 지정 (en|ko; 기본 환경에서 자동 감지)
--upgrade 최신 릴리즈 확인 (--apply 없으면 정보만 출력)
(--upgrade --apply: GitHub Release 자산 다운로드 + SHA256 검증 + 원자적 교체)
cpa --upgrade로 최신 GitHub Release를 확인하고 (--apply와 함께 쓰면) 자기 자신을 안전하게 교체할 수 있다.
# 1) 새 버전 확인만 (root 불필요)
cpa --upgrade
# 출력 예:
# GitHub에서 최신 릴리즈 확인 중...
# 업그레이드 가능: v0.2.0 → v0.2.1 (자산 cpa-linux-amd64, 6342144 bytes)
# sha256: 1a2b3c4d...
# 2) 실제 교체 (필요 시 sudo 자동 재실행)
sudo cpa --upgrade --apply
# 또는 사용자 디렉토리(~/bin 등)에 설치돼 있으면 sudo 없이도 동작
cpa --upgrade --apply동작:
- GitHub
/releases/latest에서 최신 메타데이터 조회 (인증 불필요). - 현재 OS/ARCH에 해당하는 자산 선택 — 현재 배포 자산은
cpa-linux-amd64/cpa-linux-arm64만 제공. macOS/Windows에서는 "unsupported platform" 안내. - 자산과
SHA256SUMS를 함께 다운로드 → 자산의 실측 SHA256과 기대 해시 일치 검증. 불일치 시 즉시 실패하고 임시 파일을 삭제, 실행 중인 바이너리는 그대로 보존. os.Rename으로 원자적 교체. 실행 중이던 프로세스는 그대로 종료 후 다음 실행부터 새 바이너리 사용.
--apply 사용 시 binary가 위치한 디렉토리에 쓰기 권한이 없으면 자동으로 sudo 재실행. --no-elevate 지정 시에는 명시적 에러로 종료(자동 sudo 비활성).
- 환경 자동 감지:
LC_ALL>LC_MESSAGES>LANG.ko또는ko_*이면 한국어, 그 외(또는 미설정)면 영어. --lang=ko/--lang=en으로 강제 가능. 그 외 값은 거부 (exit 2).- 사용자-보이는 모든 메시지(usage, CLI 안내·에러, plugin Summary, 마크다운 리포트 헤더·배지)가 두 언어를 모두 지원.
- 단, JSON 로그(
cpa.log)의msg필드는 기계 가독 키로 의도되어 다국어화하지 않음.
참고 — 한글 설명이 필요한 분들은
--lang=ko를 추가하세요.$LANG을 자동으로 읽어서 처리하지만, 대부분의 서버 환경은LANG=en_US.UTF-8또는C.UTF-8로 설정돼 있어 기본은 영어로 보입니다. (실제로 본 저장소 운영자의 환경도LANG=en.) 예시:cpa --lang=ko --help
# 1) 영향 평가만 (root 불필요, 변경 없음)
cpa --phase assess
# 2) 전부 한 번에 (dry-run; 무엇이 일어날지 미리 확인)
cpa
# 3) 실제 적용 — sudo로 재실행되며 모듈 차단·언로드 수행
cpa --apply
# 4) 특정 CVE만
cpa --cve CVE-2026-31431 --apply
# 5) 롤백 (적용한 차단 파일 제거) — --apply 또는 --dry-run 명시 필수
cpa --rollback --dry-run --cve CVE-2026-31431 # 미리보기
cpa --rollback --apply --cve CVE-2026-31431 # 실제 롤백 (sudo)
# 6) 마크다운 리포트 생성
cpa --report /tmp/cpa-report.md
# 7) JSON 라인 출력 (다른 도구·SIEM 연동)
cpa --json각 CVE는 4 단계 라이프사이클을 갖는다:
assess → 호스트가 취약한지 판단 (비-root 가능)
remediate → 조치 적용 (root 필요. 미지정 시 자동 sudo 재실행)
verify → 조치 후 재평가
rollback → (선택) 적용한 변경의 역연산
옵션이 없으면 내장된 모든 CVE에 대해 assess → remediate → verify를 순차 실행한다 (단, --apply가 없으면 dry-run으로 강제).
- 셸 인터폴레이션 금지. 외부 명령은 항상 인자 배열로만 호출.
--apply없이는 어떤 변경도 발생하지 않음 (기본 dry-run).- 외부 사용자 작성 파일 보호:
/etc/modprobe.d/에 cpa 표식이 없는 파일은 절대 덮어쓰거나 삭제하지 않음. - 모듈 자동 재로드 안 함: rollback 시 파일만 제거. modprobe는 시스템 관리자 결정.
- 자체 PoC 미동봉. 외부 PoC 코드 인용·실행 안 함.
- 민감정보 마스킹 인터페이스 마련 (로깅 계층에서 일괄).
- 한 줄당 1 JSON, 키:
ts(RFC3339Nano),level,msg,host,pid,uid, 그리고 phase별cve/phase/action/result/details. - 위치 결정:
--log-file> 실행파일 옆cpa.log>$XDG_STATE_HOME/cve-patch-auditor/cpa.log> stderr 폴백.
cve-patch-auditor/
├── cmd/cpa/ ← CLI 엔트리
├── internal/
│ ├── cve/ ← Plugin 인터페이스, 레지스트리, 오케스트레이터
│ ├── plugins/
│ │ ├── cve_2026_23918/ ← Apache HTTP/2 double-free (Stage 12 — 첫 비-커널)
│ │ ├── cve_2026_31431/ ← Copy Fail (Stage 3 + Stage 11 grubby 분기)
│ │ ├── cve_2026_43284/ ← Dirty Frag #1
│ │ ├── cve_2026_43500/ ← Dirty Frag #2
│ │ ├── cve_2026_46300/ ← Fragnesia (Stage 9)
│ │ └── cve_2026_46333/ ← ptrace LPE (Stage 13 — Pattern D sysctl)
│ ├── privilege/ ← root 확인 + sudo 재실행
│ ├── exec/ ← 외부 명령 안전 래퍼 (인자 배열, 타임아웃, dry-run)
│ ├── system/ ← uname / /proc/modules / /etc/os-release / 패키지 매니저 / built-in 감지
│ ├── upgrade/ ← 자체 업그레이드 (GitHub Release + SHA256 + atomic rename, Stage 10)
│ ├── i18n/ ← KO/EN 메시지 (--lang, env 자동 감지)
│ └── audit/
│ ├── log/ ← slog 기반 JSON 라인 로깅
│ └── report/ ← 마크다운 리포터
├── doc/
│ ├── PLAN.md ← 마스터 계획 (Stage 1~12)
│ ├── CVE-STATUS.md ← CVE 분류·상태 마스터 색인 (§1 처리 반영 / §2 이미 차단됨 / §3 처리 예정 / §4 조치 안 함)
│ ├── references.md ← 외부 인용 자료 인덱스
│ ├── cve/ ← CVE 별 사실 정리 + 자동화 계약
│ └── stages/ ← Phase 별 결정·검증 기록 (stage-1 ~ stage-12)
└── .github/workflows/ ← ci / release
make build # 빌드
make test # 단위 테스트
make vet # go vet
make cover # 커버리지
make dist # 배포용 (linux amd64/arm64 + SHA256SUMS)
make cleanCI는 push/PR마다 vet + test -race + 크로스 빌드를 수행 (.github/workflows/ci.yml).
- Linux 전용 실 동작 (kernel modules, /proc/modules, /etc/modprobe.d 의존).
- macOS/Windows에서는 빌드·단위 테스트만 가능; 실 phase 메서드는
ErrUnsupported. - 패키지 매니저를 통한 영구 커널 패치 자동 적용은 본 도구 범위 외 (사용자 안내만).
- 자체 PoC 비포함.
미정 (TBD). 운영 도입 전 라이선스 결정 필요.
- 외부 인용 자료 전체:
doc/references.md - 상세 계획·결정 이력:
doc/PLAN.md,doc/stages/ - CVE 분류·상태 마스터 색인:
doc/CVE-STATUS.md