업데이트로 돌아가기
New releaseJul 24, 2026

fleet-cve-scanner v1.1.0

RMM으로 관리되는 환경을 위한 오픈소스 단일 스크립트 CVE 스캐너입니다. 순수 PowerShell 7 기반 — RMM 소프트웨어 인벤토리를 NVD, CISA KEV, EPSS, SSVC와 결합하여 이 버전이 취약한지, 그리고 얼마나 긴급한지에 답합니다.

공유

fleet-cve-scanner

RMM으로 관리되는 플릿을 위한 오픈소스 단일 스크립트 CVE 스캐너입니다. 순수 PowerShell 7, 에이전트 불필요, 어플라이언스 불필요, 라이선스 비용 없음.

관리하는 모든 엔드포인트의 모든 소프트웨어에 대해 한 가지 질문에 답합니다: 설치된 버전이 알려진 취약점을 가지고 있는지, 그리고 그 긴급성은 어느 정도인지? — RMM의 소프트웨어 인벤토리를 무료 공식 보안 피드와 결합하여.

  • NIST NVD — 알려진 CVE 및 영향을 받는 버전 범위
  • CISA KEV — 실제 환경에서 활발히 악용됨 (점수 임계값 우회)
  • EPSS — 향후 30일 내 악용 확률
  • CISA SSVC — 행동/관찰/추적 우선순위 결정
  • MSRC — Microsoft 패치가 이미 해당 발견을 포함하고 있다는 증거
  • endoflife.date — 더 이상 패치되지 않을 소프트웨어

출력물: 장치별 CSV 보고서, SLA 시계 및 주간 변경 이벤트가 있는 SQLite 히스토리, 독립형 HTML 대시보드, 그리고 선택적 마크다운 노출 보고서.

상태

v1.0.0. 엔진은 Windows 플릿을 대상으로 프로덕션에서 주간 실행되던 스캐너에서 클린룸 방식으로 포팅되었습니다. (docs/HISTORY.md 참조). 이 릴리스 이전에 두 스캐너를 동일한 실제 플릿에 대해 실행하고 행별로 비교했습니다. 수만 건의 결과 중 두 스캐너가 동일한 *(장치, 소프트웨어, 버전)*을 확인한 경우, 모든 계산된 필드(상태, CVSS, 심각도, KEV 플래그, SSVC 결정, 수정 버전)가 정확히 일치했습니다.

이 비교는 판결(verdict) 로직을 다룹니다. 히스토리/SLA 계층을 테스트하지 않았으며, 자체 환경에서 도구를 검증하는 것을 대체하지 않습니다. 신뢰하기 전에 docs/known-limitations.md를 읽으십시오 — 이 문서는 아첨보다는 정직하게 작성되었습니다.

빠른 시작

PowerShell 7 (pwsh)이 필요합니다. 두 가지 실행 방법:

A. 라이브 NinjaOne 스캔

cp config.example.json config.json
# edit config.json: fill ninjaone.client_id / client_secret / base_url,
# set output.report_dir, and (recommended) nvd.api_key
pwsh -File fleet-cve-scan.ps1

B. 오프라인 — 모든 RMM, SCCM, Intune (API 접근 불필요)

인벤토리를 hostname, software, version 열(선택 사항 device_id, os)을 가진 CSV로 내보낸 후:

cp config.example.json config.json   # only output.report_dir is needed here
pwsh -File fleet-cve-scan.ps1 -InputCsv inventory.csv

-InputCsv는 전혀 NinjaOne 호출을 하지 않습니다 — OAuth 없음, API 없음. 여전히 NVD 및 기타 공개 피드를 쿼리하므로 config.json에 nvd.api_key가 필요하고 유효한 output.report_dir이 필요합니다. 입력 계약 및 RMM별 내보내기 방법은 docs/rmm-adapters.md를 참조하십시오.

필수 구성 요소 설치

  • PowerShell 7 — macOS: brew install powershell; Windows: winget install Microsoft.PowerShell; Debian/Ubuntu: Microsoft 패키지 저장소(packages.microsoft.com)에서 설치.
  • sqlite3 (선택 사항, 히스토리/트렌드 지원) — macOS: 사전 설치 또는 brew install sqlite; Debian/Ubuntu: apt-get install sqlite3; Windows: sqlite.org에서 SQLite "tools" 번들을 다운로드하고 sqlite3.exe를 PATH에 또는 스크립트 옆에 배치. 없어도 스캔은 실행됩니다. first_seen은 실행 날짜로 대체됩니다.

요구 사항

  • PowerShell 7 (7.4+ 권장). 병렬 스캔에는 7.0+가 필요합니다.
  • sqlite3 — 선택 사항; 히스토리 DB, 트렌드, SLA first_seen 추적을 활성화합니다. 없으면 해당 기능이 건너뛰고 스캔은 계속 완료됩니다.
  • 네트워크 아웃바운드 — NVD, CISA(KEV), epss.empiricalsecurity.com (EPSS 벌크 점수 호스트 — FIRST가 EPSS 데이터 호스팅을 이전), MSRC, endoflife.date, GitHub raw (CVE Program cvelistV5) — 라이브 모드에서는 NinjaOne API도 필요.
  • 자격 증명 — 라이브 모드는 NinjaOne OAuth2 클라이언트 ID/비밀 필요; 오프라인 모드는 인벤토리 CSV만 필요. NVD API 키는 기술적으로 선택 사항이지만 플릿 규모에서는 사실상 필수: NVD는 키 사용 시 30초에 50개 요청, 키 없이 5개 요청을 허용합니다. 스캐너는 키 유무를 감지하여 속도를 조절하므로, 키 없이 실행해도 올바르지만 약 10배 느려집니다 — 소수의 제품에는 괜찮지만 실제 플릿에는 비현실적입니다. 키는 무료입니다.

구성 참조

구성은 JSON 파일입니다(기본값은 스크립트 옆의 config.json; -ConfigPath로 재정의 가능). config.example.json에서 시작하십시오. 스캐너가 읽는 모든 키, 생략 시 기본값 및 역할:

ninjaone (라이브 모드)

KeyDefaultPurpose
ninjaone.client_id""NinjaOne API OAuth2 클라이언트 ID. 라이브 스캔에 필요; -InputCsv의 경우 비워 둠.
ninjaone.client_secret""NinjaOne API OAuth2 클라이언트 시크릿.
ninjaone.base_url— (example ships https://app.ninjarmm.com)NinjaOne API 기본 URL; 라이브 스캔에 필요, 내장 대체 없음. 지역 호스트 사용(예: eu.ninjarmm.com, oc.ninjarmm.com).

nvd

KeyDefaultPurpose
nvd.api_key""NVD API 키, apiKey 헤더로 전송. 비워두면 인증되지 않은 상태로 실행되어 nvd_rate_limit 및 nvd_min_spacing_ms의 기본값이 인증된 값(48/30s, 700ms) 대신 NVD의 익명 상한(4/30s, 6500ms)으로 낮아집니다. 무료이며 약 10배 빠릅니다.

스캔 및 점수

KeyDefaultPurpose
cvss_threshold7.0점수가 있는 CVE가 VULNERABLE로 보고되기 위한 최소 CVSS 기본 점수. KEV 목록에 있는 CVE는 이 하한을 우회합니다.
ssvc_mission_prevalencehighSSVC Mission Prevalence 이해관계자 입력(low / medium / high).
ssvc_public_wellbeinghighSSVC Public Well-being 이해관계자 입력(low / medium / high).

캐싱 및 속도 제한

KeyDefaultPurpose
nvd_cache_ttl_days7NVD 결과(소프트웨어 이름별)가 재조회 전에 캐시에 유지되는 일수.
nvd_cache_flush_every500N개 항목 완료 시마다 NVD 캐시를 디스크에 체크포인트하여 중단된 스캔도 가져온 내용을 유지합니다. 0은 비활성화(스캔 종료 저장은 여전히 실행).
nvd_min_spacing_ms700 with an API key, 6500 withoutNVD 호출 간 최소 밀리초. 바인딩 속도 제약 — 이것부터 조정하십시오.
nvd_rate_limit48 with an API key, 4 without30초당 NVD 호출의 슬라이딩 윈도우 상한(백스톱). 최소 1.
parallel_throttle20ForEach-Object -Parallel 런스페이스 수. NVD 호출은 관계없이 직렬화됨; 캐시 히트 동시성만 제한. 최소 1.
kev_cache_ttl_hours24캐시된 CISA KEV 카탈로그의 TTL.
epss_cache_ttl_hours24캐시된 FIRST.org EPSS 점수 파일의 TTL.
eol_cache_ttl_days7캐시된 endoflife.date 조회의 TTL.
msrc_cache_ttl_days30캐시된 MSRC CVRF 데이터의 TTL.
cvelist_cache_ttl_days7캐시된 CVE Program (cvelistV5) / CISA-ADP SSVC 데이터의 TTL.
cvelist_fetch_budget300SSVC/vulnrichment 강화를 위한 실행당 최대 CVE 레코드 가져오기; 나머지는 다음 실행으로 연기.

nvd_min_spacing_ms, nvd_rate_limit, parallel_throttle은 스캐너가 읽지만 config.example.json에는 없습니다 — 조정이 필요한 경우에만 추가하십시오. docs/rate-limiting.md 참조.

강화 및 SLA

KeyDefaultPurpose
epss_spike_threshold0.10스캔 간 발견 항목의 EPSS 점수 상승 최소치, EPSS_SPIKE 변경 이벤트를 발생시킴.
sla_days_critical14CRITICAL 발견 항목에 대한 SLA 기간(first_seen 기준 일수).
sla_days_high30기타 점수 심각도에 대한 SLA 기간.
denied_software_csv""선택적 거부 소프트웨어 CSV 교차 검사 경로. 비어 있으면 검사 비활성화.

output

KeyDefaultPurpose
output.report_dir(required)모든 출력물(CSV, 히스토리 DB, 대시보드, 캐시)을 위한 디렉터리.
output.wiki_security_page""선택적 마크다운 노출 페이지 경로. 설정된 경우에만 작성.
output.dashboard_share""각 실행 시 대시보드 복사본을 받는 선택적 경로/공유. 비어 있으면 로컬 전용.

출력물

아래 모든 항목은 output.report_dir에 저장됩니다.

  • vuln-report-YYYY-MM-DD.csv — 발견 항목별 보고서. 28개 열(스키마는 아래 참조).
  • vuln-history.db — SQLite 히스토리(sqlite3 필요): runs(실행별 집계), findings(각 (device, software, cve)별 열린 발견 히스토리, first_seen/last_seen/resolved_date/epss_score 포함), changes(유형화된 주간 이벤트).
  • cve-dashboard.html — 독립형 HTML 대시보드(차트 라이브러리 인라인, 외부 요청 없음). 선택적으로 output.dashboard_share에 복사.
  • eol-report-YYYY-MM-DD.csv — 수명 종료 제품군이 감지되면 작성.
  • denied-report-YYYY-MM-DD.csv — denied_software_csv가 구성되고 일치할 때 작성.
  • 캐시 파일 — nvd-cache.json, kev-cache.json, epss-cache.json, eol-cache.json, msrc-cache.json, cvelist-cache.json(모두 gitignore됨).
  • 마크다운 노출 페이지 — output.wiki_security_page에, 설정된 경우에만.

CSV 스키마 (28개 열)

열 세트는 고정되어 있으며 게이트에서 강제됩니다. 순서:

카테고리