
CISA KEV, ThreatFox, URLhaus, MalwareBazaar 피드를 집계하는 위협 인텔리전스 관측소로, 검색, 변경 추적 및 STIX/CSV/JSONL 내보내기를 지원합니다.
현재 소스 상태, 자료 변경 이벤트, 운영 수집 원격 측정(telemetry)을 의미론적으로 분리하여 유지하는 증거 우선 위협 관측 시스템입니다. 누락, 오래됨, 비활성화 또는 사용 불가능한 데이터는 계속해서 누락으로 표시됩니다. 인터페이스는 데모 레코드나 추론된 귀속 정보를 대체하지 않습니다.
이번 릴리스는 증거 날짜와 장치 로컬 확인 상태를 강화하고, 모든 중요한 읽기 실패를 성공적인 제로 결과 상태와 명확히 구분하며, 상관관계 요청을 안정화하고, 증거 서랍, 범위가 제한된 조사 필터, 소스 해석, 모바일 컨트롤 및 내보내기 계산을 강화합니다. 모든 애니메이션 재생 표시는 여전히 보존된 NEW, UPDATED 또는 REMOVED 이벤트에 대응하며, 장식용 네트워크 트래픽이 아닙니다.

Pulse — 소스 간 관계, 소스 상태, 현재 상태 분석.

Replay — 보존된 NEW, UPDATED, REMOVED 전환을 페이지 단위로 재구성.
추가 라이브 표면에는 대략적인 공인 IP 인프라 지리 정보와 자사 URLhaus / MalwareBazaar 증거 뷰가 포함됩니다. 이러한 표면은 이 README에서 의도적으로 플레이스홀더나 중복 스크린샷으로 표현되지 않습니다.
프로덕션 캡처는 라이브 v1.2.0 Observatory의 소스 보존 스크린샷입니다. 프레젠테이션을 위해 크롭 및 크기 조정/압축되었습니다. 표시되는 증거, 타임스탬프, 카운트, IOC 값 및 인터페이스 상태는 재생성되거나 대체되지 않습니다.
프로덕션 Worker는 Cloudflare D1로 백업됩니다. 피드 자격 증명은 서버 전용 Cloudflare Worker 시크릿으로 유지되며 브라우저에서 절대 필요하지 않습니다.
1.2.022.13.0 이상이 배포는 demand-driven 모드로 실행됩니다. 리포지토리는 이제 표준 Cloudflare Workers를 직접 대상으로 합니다. v1.2.0에서는 예약된 트리거가 의도적으로 활성화되지 않으므로 애플리케이션이 지속적인 수집을 주장하지 않습니다. 향후 스케줄러는 별도의 정확성 및 운영 검증 후 동일한 runIngestionCycle() 작업을 호출할 수 있습니다.
브라우저는 초기 사용 시와 열려 있는 동안 5분마다 명시적인 범위 제한 유지보수 요청을 수행합니다:
POST /api/ingest
↓
runIngestionCycle()
↓
configuration → TTL → backoff → D1 lease → fetch → normalize → validate
↓
snapshot cache + current observations + material events + cycle statistics
일반 읽기는 별도의 로컬 작업입니다:
GET /api/observations → D1 current state, scoped before pagination
GET /api/search → D1 current state, scoped before pagination
GET /api/kev → D1 current CISA catalog
GET /api/events → D1 material change ledger
GET /api/geo → local observations + bounded cached IP enrichment
이러한 GET 경로 중 어떤 것도 소스 어댑터를 호출하지 않습니다. 이 프로젝트가 나중에 실제로 지원되는 스케줄러를 갖게 되면 두 번째 새로고침 구현을 만들지 않고 동일한 runIngestionCycle() 작업을 호출할 수 있습니다.
범위는 소스별로 표시됩니다. 제한된 API는 완전한 카탈로그로 제시되지 않습니다.
DB 바인딩은 별개의 데이터셋을 소유합니다:
threat_source_cache 및 threat_source_cache_chunks: 세대별 키 청크에 저장된 소스별 최신 검증 스냅샷.observations: 안정적인 소스 ID별 최신 정규화된 현재 상태. 최초 수집, 최신 소스 목격, 마지막 자료 변경, 현재 해시, 개정 횟수 및 최신 수집 결과를 보존합니다.observation_events: 의미 있는 NEW, UPDATED 및 방어 가능한 REMOVED 증거 이벤트. 이전 및 현재 정규화된 페이로드, 해시 및 결정적 필드 차이는 이전 상태를 재구성 가능하게 만듭니다.source_fetch_log: 응답 본문이나 자격 증명이 없는 범위 제한 수집 시도 원격 측정.source_ingest_cycles: 가져옴, 유효함, 거부됨, 신규, 업데이트됨, 변경 없음 및 제거됨 레코드에 대한 소스별 범위 제한 새로고침 카운트.source_refresh_lease: 동시 isolate가 업스트림 새로고침을 중복하지 못하도록 하는 소스별 짧은 D1 지원 임대.ingestion_runtime: 최신 전체 수집 주기 상태.geo_ip_cache: 검증된 대략적인 IP 지리 정보 결과와 범위 제한 부정 캐시 항목. 성공한 결과는 30일 후 만료되고, 실패한 조회는 5분 후 재시도됩니다. 만료된 D1 행은 GEO 요청 중 기회적으로 제거되며, isolate 폴백은 2,000개 항목으로 제한됩니다.런타임 스키마 정의는 db/schema.ts에 있습니다. 초기화는 종속 인덱스를 만들기 전에 기존 observations 테이블에 새로운 현재 상태 열을 추가합니다.
이 질문들은 의도적으로 다릅니다:
observations와 검증된 소스 스냅샷이 이에 답합니다./api/observations?window=...는 업스트림 observedAt로 현재 관측치를 필터링합니다.observation_events와 /api/revisions가 이에 답합니다.현재 상태는 7일 기록 테이블로 부정확하게 설명되지 않습니다. 자료 이벤트 원장은 7일 동안 보존됩니다. 수집 및 주기 원격 측정은 2일 동안 보존되며 소스당 200행으로 제한됩니다. 7일 동안 다시 나타나지 않은 비카탈로그 현재 관측치는 정리됩니다. CISA는 모든 성공적인 응답이 전체 카탈로그이므로 최신 상태로 유지됩니다. 해당 카탈로그에서 제거된 행은 정리 전 30일 동안 사용할 수 있습니다.
현재 REMOVED 이벤트를 만들 수 있는 것은 CISA 부재뿐입니다. 그 이유는 해당 어댑터가 전체 최신 카탈로그를 검색하기 때문입니다. 범위가 제한된 ThreatFox, URLhaus 또는 MalwareBazaar 결과의 부재는 삭제로 처리되지 않습니다.
변경 없는 목격은 현재 lastObservedInSnapshotAt/lastIngestedAt를 진행시키지만 이벤트를 만들거나 revisionCount를 증가시키지 않습니다. lastChangedAt는 이후의 변경 없는 목격 후에도 유지됩니다.
Exploited 뷰는 다음을 분리합니다:
dateAdded가 명시적 TODAY, 7D 또는 30D 범위 안에 있는 레코드. 하루 미만 단위의 Observatory 창은 CISA 정밀도로 제시되지 않습니다.현재 카탈로그는 서버 측 검색, 공급업체, 제품, 최신 추가, 랜섬웨어 연관, 날짜 추가 필터 및 불투명 커서 페이지네이션을 지원합니다. CVE, 공급업체, 제품, 취약점 이름, 추가 날짜, 기한 날짜, 랜섬웨어 연관 및 요구 조치를 표시합니다. CVSS 점수를 만들어내지 않습니다.
콘텐츠 해시는 Observatory 장부 기록이 아닌 정규화된 증거 필드를 다룹니다. 변경된 해시는 이전 정규화된 페이로드, 새 정규화된 페이로드, 이전/새 해시 및 다음에 대한 결정적 diff와 함께 UPDATED 이벤트를 생성합니다:
출처 서랍은 /api/revisions?id=...를 쿼리하고 현재 해시, 마지막 자료 변경, 개정 횟수, 보존된 이벤트 및 필드 수준 diff를 표시합니다. 휘발성 수집 타임스탬프는 콘텐츠 diff에 나타나지 않습니다.
서랍은 또한 모든 수용된 레코드에 대한 버전화된 증거 추적을 표시합니다: 수용된 정규화된 필드, 부재 상태로 남은 선택적 필드, 표시 전용 변환, 분류 근거 및 안정적인 ID 근거. 이 추적은 보존된 증거만 설명합니다. 거부된 업스트림 값은 보존되지 않으며 합성 Observatory ID를 절대 할당받지 않습니다. 거부는 범위 제한 필드 및 사유 코드가 있는 주기별 집계 카운트로 별도로 표시됩니다. 해당 스키마 이전에 수집된 오래된 주기는 재구성되는 대신 분석 정보가 없는 것으로 표시됩니다.
Recent Events는 자료 변경만 표시합니다. 전체 CISA 새로고침 후 수백 개의 변경 없는 SEEN 행을 내보내지 않습니다. 그러한 목격은 소스 주기 통계로 요약됩니다.
기본 Briefing 뷰는 보존된 자료 이벤트 원장을 현재 브라우저에만 저장된 버전화된 확인 커서와 비교합니다. 첫 사용 및 저장소 지움은 새 활동이 아닌 초기 기준선으로 표시됩니다. 저장된 커서가 보존된 원장보다 오래된 경우 인터페이스는 완전한 델타를 증명할 수 없다고 명시합니다.
확인은 서버 이벤트를 변경하거나 삭제하지 않습니다. 커서는 의도적인 장치 전송을 위해 JSON으로 내보내고 가져올 수 있습니다. 계정 동기화 상태로 제시되지 않으며 생성된 장치 식별자는 서버로 전송되지 않습니다.
Briefing 합계는 현재 반환된 원장 페이지를 설명하며 표시/페이지 범위로 라벨링됩니다. 완전한 보존 원장의 합계로 제시되지 않습니다.
가져온 확인 타임스탬프는 저장 또는 비교 전에 엄격하게 검증되고 UTC ISO-8601로 정규화됩니다. 브라우저 저장소는 선택 사항으로 처리됩니다. 차단되거나 실패한 로컬 저장소는 간결한 인라인 오류를 생성하며 Briefing을 절대 중단시키지 않습니다.
Export 작업대는 이미 로드된 검증된 표시 페이지를 CSV, JSONL, STIX 2.1, defanged 텍스트 또는 적용된 정책과 사용 가능한 레코드 해시가 포함된 증거 매니페스트로 포맷합니다. 활성 로컬 검색 및 소스 범위는 Export로 전달됩니다. 빈 소스 허용 목록은 0개 레코드를 내보냅니다. STIX는 CISA CVE를 Vulnerability 객체로, 검증된 파일 해시(MalwareBazaar SHA-256 값 포함)를 Indicator 객체로 표현합니다. 선택, 발행 및 지원되지 않는 카운트는 구별됩니다. 지원되지 않는 레코드는 조용히 삭제되는 대신 번들 메타데이터에 공개됩니다. Export는 업스트림 수집을 수행하지 않습니다. 누락된 신뢰도는 누락으로 유지되고, 소스 간 불일치는 별도 레코드로 유지되며, 제거된 원장 이벤트는 현재 상태 내보내기에 조용히 들어가지 않습니다. 이러한 아티팩트는 방화벽 차단 권장 사항이 아닌 증거 전송 수단입니다.
만료된 소스는 1, 2, 5, 15 및 30분의 범위 제한 재시도 지연을 사용합니다. 유효한 더 큰 Retry-After는 최대 1시간까지 존중됩니다. 백오프 동안 유효한 이전 스냅샷은 stale로 제공됩니다. 빈 실패 소스는 오프라인 상태로 유지됩니다.
가져오기 전에 적격 소스는 짧은 조건부 D1 임대를 획득합니다. 다른 isolate는 만료되지 않은 보유자를 대체할 수 없으므로 하나의 새로고침만 진행됩니다. D1을 사용할 수 없는 경우 시스템은 저하된 스냅샷 전용 모드와 isolate 메모리 임대를 명시적으로 보고합니다. 해당 폴백은 분산형으로 설명되지 않습니다.
현재 관측치, 소스별 작업 영역, 로컬 검색, CISA 카탈로그, 자료 이벤트 및 레코드 개정은 범위 제한 서버 측 커서 쿼리를 사용합니다. 소스 및 종류 제약은 정렬 및 페이지네이션 전에 적용됩니다. 커서는 안정적인 정렬 튜플을 인코딩하고 길이/문자/스키마 검증되며 잘못된 형식이면 HTTP 400으로 안전하게 실패합니다. 브라우저는 로컬 페이지네이션을 위해 완전한 7일 데이터셋을 절대 수신하지 않습니다.
API 제한기는 Worker isolate로 범위가 지정된 인메모리 고정 창 카운터입니다. 전역적으로 권위 있는 Cloudflare 속도 제한이 아닌 최선 노력의 isolate 로컬 보호로 정확하게 보고됩니다. 일반 읽기는 보고된 클라이언트 IP당 분당 120회 요청으로 제한됩니다. 수집은 별도의 분당 6회 요청 버킷을 가지며 지리 정보는 별도의 분당 12회 요청 버킷을 가집니다. 이 컨트롤을 과장하기 위해 모든 읽기에 D1 쓰기가 추가되지는 않습니다.
POST /api/ingest — 명시적 수요 기반 유지보수 주기; TTL, 백오프 및 D1 임대를 존중합니다.GET /api/observations?window=24h&scope=urlhaus&limit=100&cursor=... — 페이지네이션된 로컬 현재 상태 창; 검증된 범위는 all, urlhaus, malwarebazaar 및 infrastructure입니다.GET /api/search?q=indicator&window=24h&scope=urlhaus&limit=100&cursor=... — 페이지네이션된 범위 제한 로컬 검색; 업스트림 호출 0회.GET /api/kev?limit=50&q=...&vendor=...&product=...&ransomware=known&addedSince=YYYY-MM-DD&cursor=... — 전체 현재 CISA 카탈로그.GET /api/events?limit=50&cursor=... — 자료 이벤트 원장.GET /api/revisions?id=...&limit=50&cursor=... — 현재 레코드 및 보존된 개정.GET /api/correlations?id=... — 데이터셋 수준 현재 상태의 정확한 지표 동료.로컬 Cloudflare 개발은 .dev.vars에서 서버 전용 자격 증명을 읽습니다. .dev.vars.example를 .dev.vars로 복사하고 권한이 있는 피드만 채우십시오:
THREATFOX_AUTH_KEY=
URLHAUS_AUTH_KEY=
MALWAREBAZAAR_AUTH_KEY=
프로덕션 자격 증명은 Cloudflare Worker 시크릿으로 저장되어야 하며, 커밋된 소스나 클라이언트에 노출된 GitHub 변수로 절대 저장되어서는 안 됩니다. 애플리케이션은 Workers 런타임 바인딩 표면을 통해서만 이에 접근합니다. NEXT_PUBLIC_*, 클라이언트 컴포넌트, HTML, 로그, 픽스처 또는 커밋된 파일에 절대 나타나서는 안 됩니다.
리포지토리는 표준 Cloudflare Workers를 직접 대상으로 합니다. wrangler.jsonc는 Worker 구성의 소스이며 DB라는 초안 D1 바인딩을 선언합니다. Wrangler 4는 첫 번째 인증된 배포 시 해당 D1 리소스를 자동으로 프로비저닝하고 이후 배포에서 바인딩을 연결된 상태로 유지합니다. 계정별 D1 식별자는 커밋되지 않습니다.
개발 및 프로덕션 명령:
npm ci
npm run dev
npm run build
npm run preview
# authenticated Cloudflare session / CI only
npm run deploy
GitHub Actions 검증은 모든 풀 리퀘스트와 main 푸시에서 실행됩니다. 프로덕션 배포는 의도적으로 deploy production 워크플로를 통해 수동으로 진행되며 CLOUDFLARE_API_TOKEN 및 CLOUDFLARE_ACCOUNT_ID라는 리포지토리 시크릿이 필요합니다. 이는 검토되지 않은 브랜치나 불완전한 자격 증명 설정이 자동으로 게시되는 것을 방지합니다.
npm ci
npm audit --omit=dev --audit-level=high
npm audit --audit-level=high
npm test
npm run lint
npm test는 지원되는 테스트 진입점입니다. 결정적 스위트 전에 전체 프로덕션 빌드를 수행하여 아티팩트 수준 클라이언트 시크릿 격리가 dist/client를 검사할 수 있게 합니다. 클린 체크아웃에서 직접 node --test를 실행하면 필요한 빌드 아티팩트가 의도적으로 생략됩니다. 테스트는 엄격한 달력 및 확인 타임스탬프 파싱, 선택적 장치 저장소, 안정적인 상관관계 종속성, 정규화된 증거, 정규 태그 해싱, 자료 이벤트 생성, 변경 없는 재수집, 이전 페이로드 보존, 마지막 변경 내구성, 필드 diff, 이벤트 보존 및 원장 공백, 증거 추적, 빈 소스 내보내기 정책, STIX 표현/카운트 무결성, TTL/백오프 적격성, 새로고침 임대, 서버 측 범위-전-페이지네이션 배선, 전용 GEO/Recent-KEV 쿼리, 커서 검증, 읽기 경로 격리, 소스 범위, 외부 참조 정책, 속도 제한 정확성, 소스 실패 격리 및 클라이언트 시크릿 격리를 다룹니다.
GEO 모드는 검증된 공인 IPv4/IPv6 관측치만 표시합니다. 전용 D1 쿼리는 일반 관측치 페이지를 재사용하는 대신 요청된 현재 상태 창 전체에서 적격 IP 레코드를 선택합니다. 응답은 후보 레코드 합계와 2,000레코드 안전 상한에 도달했는지 여부를 보고합니다. 호출자는 임의의 업스트림 대상이나 IP 목록을 제공할 수 없습니다. GeoJS는 고정 기본 제공자이고 FreeIPAPI는 고정 폴백입니다. 임의의 업스트림 URL은 불가능합니다. 애플리케이션은 12주소 요청 상한, 30일 D1 성공 캐시, 5분 재시도 캐시 및 전용 경로 제한기를 통해 외부 작업을 제한합니다. 표시된 모든 포인트는 실제 제공자 출처를 유지하며 기본 로컬 레코드를 열 수 있습니다.
MIT 라이선스 하에 공개되었습니다. LICENSE를 참조하십시오.
GEO 모드를 선택하면 서버가 각 검증된 공인 IP 후보를 일반 HTTPS 요청 메타데이터와 함께 GeoJS로 보내고 폴백이 필요할 때 FreeIPAPI로 보냅니다. 따라서 해당 제공자는 어떤 공인 주소가 조회되는지 관찰할 수 있습니다. 사설, 예약, 문서 및 클라이언트 제공 주소는 절대 전송되지 않습니다. 관계 모드는 지리 정보 요청을 수행하지 않습니다.
Replay 작업 영역은 Observatory 탐지 시간 순서로 현재 페이지의 자료 원장 전환을 재구성합니다. NEW, UPDATED 및 REMOVED 모션은 저장된 이벤트에 의해서만 구동됩니다. 명시적으로 페이지 범위로 제한되며 완전한 역사적 스냅샷이나 네트워크 트래픽 볼륨을 재구성한다고 주장하지 않습니다.
Natural Earth 파생 world-atlas 패키지는 로컬 기본 지도를 제공합니다. 지도는 동일 위치 IP를 클러스터링하고, 호버 세부 정보 및 출처 클릭 연결을 지원하며, 지리 정보가 확인된, 제외된, 사용 불가능한 및 대기 중인 카운트를 보고합니다. 사설, 예약, 문서, 멀티캐스트 및 기타 비공인 범위는 제공자 호출 전에 제외됩니다.
IP 지리 정보는 명시적으로 대략적인 인프라 위치로 제시됩니다. 행위자 위치, 이벤트 출처, 국적, 소유권 조사 결과 또는 귀속 주장이 아닙니다. 실패한 보강은 부재 상태로 유지됩니다. 애플리케이션은 대체 좌표를 절대 생성하지 않습니다.
기본 시각화는 개별 관측치를 해당 소스 및 명시적으로 제공된 악성코드 패밀리에 연결하는 대화형 힘-방향 필드로 유지됩니다. 캔버스는 노드 드래그, 필드 패닝, 줌, 애니메이션 링크 트래픽 및 직접 출처 검사를 지원합니다. GEO는 자체 출처 및 실패 의미론을 가진 별도의 증거 표면입니다.
| 소스 | 자격 증명 | TTL | 실제 범위 |
|---|
| CISA KEV | 없음 | 30분 | 전체 유효한 최신 카탈로그 |
| ThreatFox | THREATFOX_AUTH_KEY | 15분 | 요청된 24시간 IOC 창 |
| URLhaus | URLHAUS_AUTH_KEY | 15분 | 최근 엔드포인트가 반환한 최신 500개 레코드 |
| MalwareBazaar | MALWAREBAZAAR_AUTH_KEY | 15분 | 엔드포인트가 반환한 최신 100개 메타데이터 레코드 |
GET /api/geo?window=24h — 검증된 로컬 공인 IP 관측치에서만 후보를 파생하고, 요청당 최대 12개의 캐시되지 않은 제공자 결과를 검색하며, 출처가 있는 캐시된 대략적인 WGS84 포인트를 반환합니다.GET /api/status — 소스, 현재 상태, 신선도, 수집 모드, 주기, 임대 및 속도 제한 의미론.