Add CISA-KEV and Cloudflare Radar source adapters
CISA Known Exploited Vulnerabilities catalog — tracks CVEs actively
exploited in the wild. No auth required. Provides vendor breakdown,
ransomware linkage, recent additions, and actionable signals.
Cloudflare Radar — internet outages, traffic anomalies, and DDoS attack
trends. Requires a free API token (CLOUDFLARE_API_TOKEN). Monitors
watchlist countries (RU, UA, CN, IR, KP, etc.) for internet shutdowns
and sustained disruptions.
Both sources slot into Tier 6: Cyber & Infrastructure. Source count
updated from 27 to 29.
2026-03-21 14:42:17 -07:00
// Cloudflare Radar — Internet traffic anomalies and outages
// Requires a free Cloudflare API token (CLOUDFLARE_API_TOKEN).
// Get one at: https://dash.cloudflare.com/profile/api-tokens
2026-03-21 14:56:03 -07:00
// Create a custom token with Account → Account Analytics → Read permission.
Add CISA-KEV and Cloudflare Radar source adapters
CISA Known Exploited Vulnerabilities catalog — tracks CVEs actively
exploited in the wild. No auth required. Provides vendor breakdown,
ransomware linkage, recent additions, and actionable signals.
Cloudflare Radar — internet outages, traffic anomalies, and DDoS attack
trends. Requires a free API token (CLOUDFLARE_API_TOKEN). Monitors
watchlist countries (RU, UA, CN, IR, KP, etc.) for internet shutdowns
and sustained disruptions.
Both sources slot into Tier 6: Cyber & Infrastructure. Source count
updated from 27 to 29.
2026-03-21 14:42:17 -07:00
//
// Monitors internet outages, traffic anomalies, and attack trends
// that correlate with conflict, censorship, and infrastructure disruption.
import { safeFetch } from '../utils/fetch.mjs' ;
import '../utils/env.mjs' ;
const RADAR _BASE = 'https://api.cloudflare.com/client/v4/radar' ;
// Countries of intelligence interest for internet monitoring
const WATCHLIST _COUNTRIES = [
'RU' , 'UA' , 'CN' , 'IR' , 'KP' , 'SY' , 'MM' , 'ET' , 'SD' ,
'YE' , 'AF' , 'IQ' , 'LB' , 'PS' , 'TW' , 'BY' , 'VE' , 'CU'
] ;
function getAuthHeaders ( ) {
const token = process . env . CLOUDFLARE _API _TOKEN ;
if ( ! token ) return null ;
return { Authorization : ` Bearer ${ token } ` } ;
}
async function fetchAnnotations ( ) {
const headers = getAuthHeaders ( ) ;
if ( ! headers ) return { error : 'no_credentials' } ;
// Cloudflare Radar Annotations — internet outages and government shutdowns
const url = ` ${ RADAR _BASE } /annotations/outages?dateRange=30d&format=json ` ;
const data = await safeFetch ( url , { timeout : 15000 , headers } ) ;
if ( data . error ) return { error : data . error } ;
const annotations = data . result ? . annotations || [ ] ;
return annotations . map ( a => ( {
id : a . id ,
description : ( a . description || '' ) . substring ( 0 , 500 ) ,
startDate : a . startDate ,
endDate : a . endDate ,
linkedUrl : a . linkedUrl || null ,
scope : a . scope || null ,
asns : a . asns || [ ] ,
locations : a . locations || [ ] ,
eventType : a . eventType || 'outage' ,
} ) ) ;
}
async function fetchAttackSummary ( ) {
const headers = getAuthHeaders ( ) ;
if ( ! headers ) return { error : 'no_credentials' } ;
2026-03-21 14:56:03 -07:00
// Layer 3 DDoS attack summaries by protocol and vector
// API requires a dimension: /summary/{dimension}
const [ byProtocol , byVector ] = await Promise . all ( [
safeFetch ( ` ${ RADAR _BASE } /attacks/layer3/summary/protocol?dateRange=7d&format=json ` , { timeout : 15000 , headers } ) ,
safeFetch ( ` ${ RADAR _BASE } /attacks/layer3/summary/vector?dateRange=7d&format=json ` , { timeout : 15000 , headers } ) ,
] ) ;
Add CISA-KEV and Cloudflare Radar source adapters
CISA Known Exploited Vulnerabilities catalog — tracks CVEs actively
exploited in the wild. No auth required. Provides vendor breakdown,
ransomware linkage, recent additions, and actionable signals.
Cloudflare Radar — internet outages, traffic anomalies, and DDoS attack
trends. Requires a free API token (CLOUDFLARE_API_TOKEN). Monitors
watchlist countries (RU, UA, CN, IR, KP, etc.) for internet shutdowns
and sustained disruptions.
Both sources slot into Tier 6: Cyber & Infrastructure. Source count
updated from 27 to 29.
2026-03-21 14:42:17 -07:00
2026-03-21 14:56:03 -07:00
const result = { } ;
if ( ! byProtocol . error && byProtocol . result ) {
result . byProtocol = byProtocol . result . summary _0 || byProtocol . result ;
}
if ( ! byVector . error && byVector . result ) {
result . byVector = byVector . result . summary _0 || byVector . result ;
}
if ( ! result . byProtocol && ! result . byVector ) {
return { error : byProtocol . error || byVector . error || 'No attack data returned' } ;
}
Add CISA-KEV and Cloudflare Radar source adapters
CISA Known Exploited Vulnerabilities catalog — tracks CVEs actively
exploited in the wild. No auth required. Provides vendor breakdown,
ransomware linkage, recent additions, and actionable signals.
Cloudflare Radar — internet outages, traffic anomalies, and DDoS attack
trends. Requires a free API token (CLOUDFLARE_API_TOKEN). Monitors
watchlist countries (RU, UA, CN, IR, KP, etc.) for internet shutdowns
and sustained disruptions.
Both sources slot into Tier 6: Cyber & Infrastructure. Source count
updated from 27 to 29.
2026-03-21 14:42:17 -07:00
2026-03-21 14:56:03 -07:00
return result ;
Add CISA-KEV and Cloudflare Radar source adapters
CISA Known Exploited Vulnerabilities catalog — tracks CVEs actively
exploited in the wild. No auth required. Provides vendor breakdown,
ransomware linkage, recent additions, and actionable signals.
Cloudflare Radar — internet outages, traffic anomalies, and DDoS attack
trends. Requires a free API token (CLOUDFLARE_API_TOKEN). Monitors
watchlist countries (RU, UA, CN, IR, KP, etc.) for internet shutdowns
and sustained disruptions.
Both sources slot into Tier 6: Cyber & Infrastructure. Source count
updated from 27 to 29.
2026-03-21 14:42:17 -07:00
}
async function fetchTrafficAnomalies ( ) {
const headers = getAuthHeaders ( ) ;
if ( ! headers ) return { error : 'no_credentials' } ;
// Traffic anomalies — significant deviations from normal patterns
const url = ` ${ RADAR _BASE } /traffic_anomalies?dateRange=7d&format=json&limit=50 ` ;
const data = await safeFetch ( url , { timeout : 15000 , headers } ) ;
if ( data . error ) return { error : data . error } ;
const anomalies = data . result ? . trafficAnomalies || [ ] ;
return anomalies . map ( a => ( {
startDate : a . startDate ,
endDate : a . endDate ,
type : a . type || 'unknown' ,
status : a . status ,
asnDetails : a . asnDetails || null ,
locationDetails : a . locationDetails || null ,
visibleInAllDataSources : a . visibleInAllDataSources || false ,
} ) ) ;
}
function buildSignals ( outages , anomalies ) {
const signals = [ ] ;
if ( ! Array . isArray ( outages ) ) return signals ;
// Check for outages in watchlist countries
const watchlistOutages = outages . filter ( o => {
const locations = o . locations || [ ] ;
return locations . some ( l => WATCHLIST _COUNTRIES . includes ( l ) ) ;
} ) ;
if ( watchlistOutages . length > 0 ) {
const countries = [ ... new Set ( watchlistOutages . flatMap ( o => o . locations ) ) ] . filter ( l => WATCHLIST _COUNTRIES . includes ( l ) ) ;
signals . push ( {
severity : 'high' ,
signal : ` Internet outages detected in ${ countries . join ( ', ' ) } — possible government shutdown or infrastructure attack ` ,
} ) ;
}
// Multiple outages in same country = sustained disruption
const locationCounts = { } ;
for ( const o of outages ) {
for ( const loc of ( o . locations || [ ] ) ) {
locationCounts [ loc ] = ( locationCounts [ loc ] || 0 ) + 1 ;
}
}
const repeated = Object . entries ( locationCounts )
. filter ( ( [ , count ] ) => count >= 3 )
. map ( ( [ loc ] ) => loc ) ;
if ( repeated . length > 0 ) {
signals . push ( {
severity : 'medium' ,
signal : ` Sustained internet disruptions in ${ repeated . join ( ', ' ) } — ${ repeated . length } locations with 3+ outage events in 30 days ` ,
} ) ;
}
// Traffic anomalies
if ( Array . isArray ( anomalies ) && anomalies . length > 10 ) {
signals . push ( {
severity : 'medium' ,
signal : ` ${ anomalies . length } traffic anomalies detected globally in last 7 days — elevated internet instability ` ,
} ) ;
}
return signals ;
}
export async function briefing ( ) {
if ( ! process . env . CLOUDFLARE _API _TOKEN ) {
return {
source : 'Cloudflare-Radar' ,
timestamp : new Date ( ) . toISOString ( ) ,
status : 'no_credentials' ,
2026-03-21 14:56:03 -07:00
message : 'Set CLOUDFLARE_API_TOKEN in .env. Get a free token at https://dash.cloudflare.com/profile/api-tokens with Account → Account Analytics → Read permission.' ,
Add CISA-KEV and Cloudflare Radar source adapters
CISA Known Exploited Vulnerabilities catalog — tracks CVEs actively
exploited in the wild. No auth required. Provides vendor breakdown,
ransomware linkage, recent additions, and actionable signals.
Cloudflare Radar — internet outages, traffic anomalies, and DDoS attack
trends. Requires a free API token (CLOUDFLARE_API_TOKEN). Monitors
watchlist countries (RU, UA, CN, IR, KP, etc.) for internet shutdowns
and sustained disruptions.
Both sources slot into Tier 6: Cyber & Infrastructure. Source count
updated from 27 to 29.
2026-03-21 14:42:17 -07:00
} ;
}
const [ outages , attacks , anomalies ] = await Promise . all ( [
fetchAnnotations ( ) ,
fetchAttackSummary ( ) ,
fetchTrafficAnomalies ( ) ,
] ) ;
// Handle complete failure
if ( outages ? . error && attacks ? . error && anomalies ? . error ) {
return {
source : 'Cloudflare-Radar' ,
timestamp : new Date ( ) . toISOString ( ) ,
error : outages . error || attacks . error || anomalies . error ,
} ;
}
const outageList = Array . isArray ( outages ) ? outages : [ ] ;
const anomalyList = Array . isArray ( anomalies ) ? anomalies : [ ] ;
// Separate active vs resolved outages
const now = new Date ( ) ;
const activeOutages = outageList . filter ( o => ! o . endDate || new Date ( o . endDate ) > now ) ;
const recentResolved = outageList . filter ( o => o . endDate && new Date ( o . endDate ) <= now ) . slice ( 0 , 10 ) ;
// Group outages by location
const outagesByLocation = { } ;
for ( const o of outageList ) {
for ( const loc of ( o . locations || [ 'unknown' ] ) ) {
if ( ! outagesByLocation [ loc ] ) outagesByLocation [ loc ] = [ ] ;
outagesByLocation [ loc ] . push ( o ) ;
}
}
const topAffectedLocations = Object . entries ( outagesByLocation )
. sort ( ( a , b ) => b [ 1 ] . length - a [ 1 ] . length )
. slice ( 0 , 15 )
. map ( ( [ location , events ] ) => ( {
location ,
eventCount : events . length ,
activeCount : events . filter ( e => ! e . endDate || new Date ( e . endDate ) > now ) . length ,
} ) ) ;
const signals = buildSignals ( outageList , anomalyList ) ;
return {
source : 'Cloudflare-Radar' ,
timestamp : new Date ( ) . toISOString ( ) ,
outages : {
total : outageList . length ,
active : activeOutages . length ,
activeEvents : activeOutages . slice ( 0 , 20 ) ,
recentResolved : recentResolved ,
topAffectedLocations ,
} ,
anomalies : {
total : anomalyList . length ,
events : anomalyList . slice ( 0 , 20 ) ,
} ,
attacks : attacks ? . error ? { error : attacks . error } : attacks ,
signals ,
} ;
}
// Run standalone
if ( process . argv [ 1 ] ? . endsWith ( 'cloudflare-radar.mjs' ) ) {
const data = await briefing ( ) ;
console . log ( JSON . stringify ( data , null , 2 ) ) ;
}