pub const TAG_PHISHING: u8 = 0x01;
pub const TAG_C2: u8 = 0x02;
pub const TAG_DOWNLOAD: u8 = 0x04;
pub const TAG_EXFIL: u8 = 0x08;
pub const TAG_EXPLOIT: u8 = 0x10;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(
feature = "serde",
derive(serde::Serialize, serde::Deserialize),
serde(rename_all = "snake_case")
)]
pub enum SiteCategory {
CodeRepository,
CloudStorage,
Cdn,
Messaging,
PasteService,
CloudHosting,
Collaboration,
UrlShortener,
DnsService,
Other,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(
feature = "serde",
derive(serde::Serialize, serde::Deserialize),
serde(rename_all = "snake_case")
)]
pub enum BlockingRisk {
Low,
Medium,
High,
Critical,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
pub struct AbusableSite {
pub domain: &'static str,
pub provider: &'static str,
pub legitimate_category: SiteCategory,
pub abuse_tags: u8,
pub blocking_risk: BlockingRisk,
pub mitre_techniques: &'static [&'static str],
}
impl AbusableSite {
#[inline]
pub fn is_c2(&self) -> bool {
self.abuse_tags & TAG_C2 != 0
}
#[inline]
pub fn is_phishing(&self) -> bool {
self.abuse_tags & TAG_PHISHING != 0
}
#[inline]
pub fn is_download(&self) -> bool {
self.abuse_tags & TAG_DOWNLOAD != 0
}
#[inline]
pub fn is_exfil(&self) -> bool {
self.abuse_tags & TAG_EXFIL != 0
}
}
pub const ABUSABLE_SITES: &[AbusableSite] = &[
AbusableSite {
domain: "raw.githubusercontent.com",
provider: "GitHub",
legitimate_category: SiteCategory::CodeRepository,
abuse_tags: TAG_C2 | TAG_DOWNLOAD | TAG_PHISHING,
blocking_risk: BlockingRisk::Critical,
mitre_techniques: &["T1102", "T1105", "T1583.001"],
},
AbusableSite {
domain: "github.com",
provider: "GitHub",
legitimate_category: SiteCategory::CodeRepository,
abuse_tags: TAG_DOWNLOAD | TAG_PHISHING,
blocking_risk: BlockingRisk::Critical,
mitre_techniques: &["T1105", "T1583.001"],
},
AbusableSite {
domain: "*.amazonaws.com",
provider: "Amazon Web Services",
legitimate_category: SiteCategory::CloudStorage,
abuse_tags: TAG_PHISHING | TAG_DOWNLOAD | TAG_EXFIL | TAG_C2,
blocking_risk: BlockingRisk::Critical,
mitre_techniques: &["T1102", "T1105", "T1567.002", "T1583.006"],
},
AbusableSite {
domain: "*.blob.core.windows.net",
provider: "Microsoft Azure",
legitimate_category: SiteCategory::CloudStorage,
abuse_tags: TAG_PHISHING | TAG_DOWNLOAD | TAG_EXFIL,
blocking_risk: BlockingRisk::Critical,
mitre_techniques: &["T1105", "T1567.002"],
},
AbusableSite {
domain: "*.azurewebsites.net",
provider: "Microsoft Azure",
legitimate_category: SiteCategory::CloudHosting,
abuse_tags: TAG_PHISHING | TAG_DOWNLOAD | TAG_EXFIL | TAG_C2,
blocking_risk: BlockingRisk::Critical,
mitre_techniques: &["T1102", "T1105", "T1567.002"],
},
AbusableSite {
domain: "drive.google.com",
provider: "Google",
legitimate_category: SiteCategory::CloudStorage,
abuse_tags: TAG_PHISHING | TAG_DOWNLOAD | TAG_EXFIL,
blocking_risk: BlockingRisk::Critical,
mitre_techniques: &["T1105", "T1567.002"],
},
AbusableSite {
domain: "docs.google.com",
provider: "Google",
legitimate_category: SiteCategory::Collaboration,
abuse_tags: TAG_PHISHING | TAG_C2,
blocking_risk: BlockingRisk::Critical,
mitre_techniques: &["T1102", "T1566.002"],
},
AbusableSite {
domain: "storage.googleapis.com",
provider: "Google Cloud",
legitimate_category: SiteCategory::CloudStorage,
abuse_tags: TAG_PHISHING | TAG_DOWNLOAD | TAG_EXFIL | TAG_C2,
blocking_risk: BlockingRisk::Critical,
mitre_techniques: &["T1102", "T1105", "T1567.002"],
},
AbusableSite {
domain: "*.cloudfront.net",
provider: "Amazon CloudFront",
legitimate_category: SiteCategory::Cdn,
abuse_tags: TAG_PHISHING | TAG_C2 | TAG_DOWNLOAD,
blocking_risk: BlockingRisk::Critical,
mitre_techniques: &["T1102", "T1105"],
},
AbusableSite {
domain: "sharepoint.com",
provider: "Microsoft",
legitimate_category: SiteCategory::Collaboration,
abuse_tags: TAG_PHISHING | TAG_DOWNLOAD | TAG_EXFIL,
blocking_risk: BlockingRisk::Critical,
mitre_techniques: &["T1105", "T1566.002", "T1567.002"],
},
AbusableSite {
domain: "*.github.io",
provider: "GitHub",
legitimate_category: SiteCategory::CodeRepository,
abuse_tags: TAG_PHISHING | TAG_C2,
blocking_risk: BlockingRisk::High,
mitre_techniques: &["T1102", "T1583.001"],
},
AbusableSite {
domain: "gitlab.com",
provider: "GitLab",
legitimate_category: SiteCategory::CodeRepository,
abuse_tags: TAG_DOWNLOAD | TAG_PHISHING | TAG_C2,
blocking_risk: BlockingRisk::High,
mitre_techniques: &["T1102", "T1105", "T1583.001"],
},
AbusableSite {
domain: "bitbucket.org",
provider: "Atlassian",
legitimate_category: SiteCategory::CodeRepository,
abuse_tags: TAG_DOWNLOAD | TAG_PHISHING,
blocking_risk: BlockingRisk::High,
mitre_techniques: &["T1105", "T1583.001"],
},
AbusableSite {
domain: "gist.github.com",
provider: "GitHub",
legitimate_category: SiteCategory::PasteService,
abuse_tags: TAG_C2 | TAG_DOWNLOAD,
blocking_risk: BlockingRisk::High,
mitre_techniques: &["T1102", "T1105"],
},
AbusableSite {
domain: "1drv.ms",
provider: "Microsoft OneDrive",
legitimate_category: SiteCategory::CloudStorage,
abuse_tags: TAG_PHISHING,
blocking_risk: BlockingRisk::High,
mitre_techniques: &["T1566.002"],
},
AbusableSite {
domain: "dropbox.com",
provider: "Dropbox",
legitimate_category: SiteCategory::CloudStorage,
abuse_tags: TAG_PHISHING | TAG_DOWNLOAD | TAG_EXFIL | TAG_C2,
blocking_risk: BlockingRisk::High,
mitre_techniques: &["T1102", "T1105", "T1567.002"],
},
AbusableSite {
domain: "firebasestorage.googleapis.com",
provider: "Google Firebase",
legitimate_category: SiteCategory::CloudStorage,
abuse_tags: TAG_PHISHING | TAG_EXFIL | TAG_C2 | TAG_DOWNLOAD,
blocking_risk: BlockingRisk::High,
mitre_techniques: &["T1102", "T1105", "T1567.002"],
},
AbusableSite {
domain: "*.workers.dev",
provider: "Cloudflare Workers",
legitimate_category: SiteCategory::CloudHosting,
abuse_tags: TAG_PHISHING | TAG_C2 | TAG_DOWNLOAD,
blocking_risk: BlockingRisk::High,
mitre_techniques: &["T1102", "T1105", "T1090.002"],
},
AbusableSite {
domain: "*.pages.dev",
provider: "Cloudflare Pages",
legitimate_category: SiteCategory::CloudHosting,
abuse_tags: TAG_PHISHING | TAG_C2,
blocking_risk: BlockingRisk::High,
mitre_techniques: &["T1102"],
},
AbusableSite {
domain: "*.web.app",
provider: "Google Firebase",
legitimate_category: SiteCategory::CloudHosting,
abuse_tags: TAG_PHISHING | TAG_C2,
blocking_risk: BlockingRisk::High,
mitre_techniques: &["T1102"],
},
AbusableSite {
domain: "slack.com",
provider: "Slack",
legitimate_category: SiteCategory::Messaging,
abuse_tags: TAG_C2,
blocking_risk: BlockingRisk::High,
mitre_techniques: &["T1102"],
},
AbusableSite {
domain: "notion.so",
provider: "Notion",
legitimate_category: SiteCategory::Collaboration,
abuse_tags: TAG_PHISHING | TAG_C2,
blocking_risk: BlockingRisk::High,
mitre_techniques: &["T1102"],
},
AbusableSite {
domain: "mega.nz",
provider: "Mega Limited",
legitimate_category: SiteCategory::CloudStorage,
abuse_tags: TAG_PHISHING | TAG_DOWNLOAD | TAG_EXFIL,
blocking_risk: BlockingRisk::Medium,
mitre_techniques: &["T1105", "T1567.002"],
},
AbusableSite {
domain: "*.herokuapp.com",
provider: "Heroku",
legitimate_category: SiteCategory::CloudHosting,
abuse_tags: TAG_PHISHING | TAG_DOWNLOAD | TAG_EXFIL | TAG_C2,
blocking_risk: BlockingRisk::Medium,
mitre_techniques: &["T1102", "T1105", "T1567.002"],
},
AbusableSite {
domain: "*.replit.app",
provider: "Replit",
legitimate_category: SiteCategory::CloudHosting,
abuse_tags: TAG_PHISHING | TAG_C2 | TAG_DOWNLOAD,
blocking_risk: BlockingRisk::Medium,
mitre_techniques: &["T1102", "T1105"],
},
AbusableSite {
domain: "discord.com",
provider: "Discord",
legitimate_category: SiteCategory::Messaging,
abuse_tags: TAG_C2 | TAG_EXFIL | TAG_DOWNLOAD,
blocking_risk: BlockingRisk::Medium,
mitre_techniques: &["T1102", "T1567.002"],
},
AbusableSite {
domain: "cdn.discordapp.com",
provider: "Discord",
legitimate_category: SiteCategory::Cdn,
abuse_tags: TAG_DOWNLOAD | TAG_C2,
blocking_risk: BlockingRisk::Medium,
mitre_techniques: &["T1102", "T1105"],
},
AbusableSite {
domain: "api.telegram.org",
provider: "Telegram",
legitimate_category: SiteCategory::Messaging,
abuse_tags: TAG_C2 | TAG_EXFIL,
blocking_risk: BlockingRisk::Medium,
mitre_techniques: &["T1102", "T1567"],
},
AbusableSite {
domain: "trello.com",
provider: "Atlassian",
legitimate_category: SiteCategory::Collaboration,
abuse_tags: TAG_C2 | TAG_PHISHING,
blocking_risk: BlockingRisk::Medium,
mitre_techniques: &["T1102"],
},
AbusableSite {
domain: "t.co",
provider: "Twitter/X",
legitimate_category: SiteCategory::UrlShortener,
abuse_tags: TAG_PHISHING,
blocking_risk: BlockingRisk::Medium,
mitre_techniques: &["T1566.002"],
},
AbusableSite {
domain: "pastebin.com",
provider: "Pastebin",
legitimate_category: SiteCategory::PasteService,
abuse_tags: TAG_C2 | TAG_DOWNLOAD | TAG_PHISHING,
blocking_risk: BlockingRisk::Low,
mitre_techniques: &["T1102", "T1105"],
},
AbusableSite {
domain: "paste.ee",
provider: "Paste.ee",
legitimate_category: SiteCategory::PasteService,
abuse_tags: TAG_C2 | TAG_DOWNLOAD,
blocking_risk: BlockingRisk::Low,
mitre_techniques: &["T1102", "T1105"],
},
AbusableSite {
domain: "hastebin.com",
provider: "Hastebin",
legitimate_category: SiteCategory::PasteService,
abuse_tags: TAG_C2 | TAG_DOWNLOAD,
blocking_risk: BlockingRisk::Low,
mitre_techniques: &["T1102", "T1105"],
},
AbusableSite {
domain: "bit.ly",
provider: "Bitly",
legitimate_category: SiteCategory::UrlShortener,
abuse_tags: TAG_PHISHING | TAG_DOWNLOAD,
blocking_risk: BlockingRisk::Low,
mitre_techniques: &["T1566.002"],
},
AbusableSite {
domain: "tinyurl.com",
provider: "TinyURL",
legitimate_category: SiteCategory::UrlShortener,
abuse_tags: TAG_PHISHING | TAG_DOWNLOAD,
blocking_risk: BlockingRisk::Low,
mitre_techniques: &["T1566.002"],
},
AbusableSite {
domain: "graph.microsoft.com",
provider: "Microsoft",
legitimate_category: SiteCategory::CloudStorage,
abuse_tags: TAG_C2 | TAG_EXFIL | TAG_DOWNLOAD,
blocking_risk: BlockingRisk::Critical,
mitre_techniques: &["T1071.001", "T1530", "T1567.002"],
},
AbusableSite {
domain: "onedrive.live.com",
provider: "Microsoft OneDrive",
legitimate_category: SiteCategory::CloudStorage,
abuse_tags: TAG_PHISHING | TAG_DOWNLOAD | TAG_EXFIL,
blocking_risk: BlockingRisk::Critical,
mitre_techniques: &["T1105", "T1567.002", "T1566.002"],
},
AbusableSite {
domain: "*.trycloudflare.com",
provider: "Cloudflare",
legitimate_category: SiteCategory::CloudHosting,
abuse_tags: TAG_C2 | TAG_DOWNLOAD | TAG_PHISHING,
blocking_risk: BlockingRisk::Critical,
mitre_techniques: &["T1090.003", "T1102", "T1105"],
},
AbusableSite {
domain: "*.netlify.app",
provider: "Netlify",
legitimate_category: SiteCategory::CloudHosting,
abuse_tags: TAG_PHISHING | TAG_C2 | TAG_DOWNLOAD,
blocking_risk: BlockingRisk::Critical,
mitre_techniques: &["T1102", "T1105", "T1583.006"],
},
AbusableSite {
domain: "*.ngrok.io",
provider: "ngrok",
legitimate_category: SiteCategory::Other,
abuse_tags: TAG_C2 | TAG_DOWNLOAD,
blocking_risk: BlockingRisk::High,
mitre_techniques: &["T1090.003", "T1102"],
},
AbusableSite {
domain: "*.ngrok-free.app",
provider: "ngrok",
legitimate_category: SiteCategory::Other,
abuse_tags: TAG_C2 | TAG_DOWNLOAD,
blocking_risk: BlockingRisk::High,
mitre_techniques: &["T1090.003", "T1102"],
},
AbusableSite {
domain: "*.box.com",
provider: "Box",
legitimate_category: SiteCategory::CloudStorage,
abuse_tags: TAG_PHISHING | TAG_EXFIL | TAG_DOWNLOAD,
blocking_risk: BlockingRisk::High,
mitre_techniques: &["T1567.002", "T1105", "T1566.002"],
},
AbusableSite {
domain: "gitee.com",
provider: "Gitee",
legitimate_category: SiteCategory::CodeRepository,
abuse_tags: TAG_C2 | TAG_DOWNLOAD,
blocking_risk: BlockingRisk::High,
mitre_techniques: &["T1102", "T1105", "T1583.001"],
},
AbusableSite {
domain: "transfer.sh",
provider: "transfer.sh",
legitimate_category: SiteCategory::CloudStorage,
abuse_tags: TAG_DOWNLOAD | TAG_EXFIL,
blocking_risk: BlockingRisk::High,
mitre_techniques: &["T1105", "T1567.002"],
},
AbusableSite {
domain: "file.io",
provider: "file.io",
legitimate_category: SiteCategory::CloudStorage,
abuse_tags: TAG_DOWNLOAD | TAG_EXFIL,
blocking_risk: BlockingRisk::High,
mitre_techniques: &["T1105", "T1567.002"],
},
AbusableSite {
domain: "4shared.com",
provider: "4shared",
legitimate_category: SiteCategory::CloudStorage,
abuse_tags: TAG_DOWNLOAD | TAG_PHISHING,
blocking_risk: BlockingRisk::High,
mitre_techniques: &["T1105", "T1566.002"],
},
AbusableSite {
domain: "mediafire.com",
provider: "MediaFire",
legitimate_category: SiteCategory::CloudStorage,
abuse_tags: TAG_DOWNLOAD | TAG_PHISHING,
blocking_risk: BlockingRisk::High,
mitre_techniques: &["T1105", "T1566.002"],
},
AbusableSite {
domain: "webhook.site",
provider: "webhook.site",
legitimate_category: SiteCategory::Other,
abuse_tags: TAG_C2 | TAG_EXFIL,
blocking_risk: BlockingRisk::Medium,
mitre_techniques: &["T1041", "T1071.001"],
},
AbusableSite {
domain: "*.pipedream.net",
provider: "Pipedream",
legitimate_category: SiteCategory::Other,
abuse_tags: TAG_C2 | TAG_EXFIL,
blocking_risk: BlockingRisk::Medium,
mitre_techniques: &["T1041", "T1102"],
},
AbusableSite {
domain: "ipinfo.io",
provider: "ipinfo.io",
legitimate_category: SiteCategory::Other,
abuse_tags: TAG_C2,
blocking_risk: BlockingRisk::Medium,
mitre_techniques: &["T1016", "T1590.005"],
},
AbusableSite {
domain: "api.ipify.org",
provider: "ipify",
legitimate_category: SiteCategory::Other,
abuse_tags: TAG_C2,
blocking_risk: BlockingRisk::Medium,
mitre_techniques: &["T1016"],
},
AbusableSite {
domain: "checkip.amazonaws.com",
provider: "Amazon Web Services",
legitimate_category: SiteCategory::Other,
abuse_tags: TAG_C2,
blocking_risk: BlockingRisk::Medium,
mitre_techniques: &["T1016"],
},
];
pub fn is_abusable_site(domain: &str) -> bool {
let lower = domain.to_ascii_lowercase();
ABUSABLE_SITES
.iter()
.any(|s| s.domain.to_ascii_lowercase() == lower)
}
pub fn abusable_site_info(domain: &str) -> Option<&'static AbusableSite> {
let lower = domain.to_ascii_lowercase();
ABUSABLE_SITES
.iter()
.find(|s| s.domain.to_ascii_lowercase() == lower)
}
pub fn sites_with_tag(tag: u8) -> impl Iterator<Item = &'static AbusableSite> {
ABUSABLE_SITES
.iter()
.filter(move |s| s.abuse_tags & tag != 0)
}
pub fn sites_above_risk(minimum_risk: BlockingRisk) -> impl Iterator<Item = &'static AbusableSite> {
ABUSABLE_SITES
.iter()
.filter(move |s| s.blocking_risk >= minimum_risk)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn abusable_sites_is_nonempty() {
assert!(!ABUSABLE_SITES.is_empty());
}
#[test]
fn contains_github_raw() {
assert!(ABUSABLE_SITES
.iter()
.any(|s| s.domain == "raw.githubusercontent.com"));
}
#[test]
fn contains_telegram_api() {
assert!(ABUSABLE_SITES
.iter()
.any(|s| s.domain == "api.telegram.org"));
}
#[test]
fn contains_pastebin() {
assert!(ABUSABLE_SITES.iter().any(|s| s.domain == "pastebin.com"));
}
#[test]
fn is_abusable_site_detects_github_raw() {
assert!(is_abusable_site("raw.githubusercontent.com"));
}
#[test]
fn is_abusable_site_case_insensitive() {
assert!(is_abusable_site("RAW.GITHUBUSERCONTENT.COM"));
}
#[test]
fn is_abusable_site_rejects_unknown() {
assert!(!is_abusable_site("example.com"));
}
#[test]
fn empty_string_not_abusable() {
assert!(!is_abusable_site(""));
}
#[test]
fn abusable_site_info_returns_record() {
let info = abusable_site_info("raw.githubusercontent.com").unwrap();
assert_eq!(info.provider, "GitHub");
assert_eq!(info.legitimate_category, SiteCategory::CodeRepository);
assert_eq!(info.blocking_risk, BlockingRisk::Critical);
assert!(info.is_c2());
assert!(info.is_download());
}
#[test]
fn abusable_site_info_returns_none_for_unknown() {
assert!(abusable_site_info("totally-unknown.example").is_none());
}
#[test]
fn sites_with_tag_c2_nonempty() {
let c2_sites: Vec<_> = sites_with_tag(TAG_C2).collect();
assert!(!c2_sites.is_empty());
}
#[test]
fn sites_with_tag_c2_includes_telegram() {
assert!(sites_with_tag(TAG_C2).any(|s| s.domain == "api.telegram.org"));
}
#[test]
fn sites_with_tag_download_includes_github() {
assert!(sites_with_tag(TAG_DOWNLOAD).any(|s| s.domain == "raw.githubusercontent.com"));
}
#[test]
fn sites_above_risk_critical_nonempty() {
let critical: Vec<_> = sites_above_risk(BlockingRisk::Critical).collect();
assert!(!critical.is_empty());
}
#[test]
fn sites_above_risk_critical_includes_aws() {
assert!(sites_above_risk(BlockingRisk::Critical).any(|s| s.domain == "*.amazonaws.com"));
}
#[test]
fn github_raw_has_mitre_techniques() {
let info = abusable_site_info("raw.githubusercontent.com").unwrap();
assert!(info.mitre_techniques.contains(&"T1102"));
}
#[test]
fn pastebin_is_low_blocking_risk() {
let info = abusable_site_info("pastebin.com").unwrap();
assert_eq!(info.blocking_risk, BlockingRisk::Low);
}
#[test]
fn discord_cdn_is_download() {
let info = abusable_site_info("cdn.discordapp.com").unwrap();
assert!(info.is_download());
}
#[test]
fn all_sites_have_at_least_one_mitre_technique() {
for site in ABUSABLE_SITES {
assert!(
!site.mitre_techniques.is_empty(),
"site {} has no MITRE techniques",
site.domain
);
}
}
#[test]
fn all_sites_have_nonzero_abuse_tags() {
for site in ABUSABLE_SITES {
assert!(
site.abuse_tags != 0,
"site {} has no abuse tags",
site.domain
);
}
}
}
#[cfg(all(test, feature = "serde"))]
mod serde_tests {
use super::*;
#[test]
fn site_category_serializes_to_snake_case_string() {
let json = serde_json::to_string(&SiteCategory::CodeRepository).unwrap();
assert_eq!(json, r#""code_repository""#);
}
#[test]
fn blocking_risk_serializes_to_snake_case_string() {
let json = serde_json::to_string(&BlockingRisk::Critical).unwrap();
assert_eq!(json, r#""critical""#);
}
#[test]
fn blocking_risk_all_variants_round_trip() {
for risk in [
BlockingRisk::Low,
BlockingRisk::Medium,
BlockingRisk::High,
BlockingRisk::Critical,
] {
let json = serde_json::to_string(&risk).unwrap();
let decoded: BlockingRisk = serde_json::from_str(&json).unwrap();
assert_eq!(decoded, risk);
}
}
#[test]
fn site_category_all_variants_round_trip() {
for cat in [
SiteCategory::CodeRepository,
SiteCategory::CloudStorage,
SiteCategory::Cdn,
SiteCategory::Messaging,
SiteCategory::PasteService,
SiteCategory::CloudHosting,
SiteCategory::Collaboration,
SiteCategory::UrlShortener,
SiteCategory::DnsService,
SiteCategory::Other,
] {
let json = serde_json::to_string(&cat).unwrap();
let decoded: SiteCategory = serde_json::from_str(&json).unwrap();
assert_eq!(decoded, cat);
}
}
#[test]
fn abusable_site_serializes_domain_field() {
let site = abusable_site_info("raw.githubusercontent.com").unwrap();
let json = serde_json::to_string(site).unwrap();
let v: serde_json::Value = serde_json::from_str(&json).unwrap();
assert_eq!(v["domain"], "raw.githubusercontent.com");
}
#[test]
fn abusable_site_serializes_blocking_risk_field() {
let site = abusable_site_info("raw.githubusercontent.com").unwrap();
let json = serde_json::to_string(site).unwrap();
let v: serde_json::Value = serde_json::from_str(&json).unwrap();
assert_eq!(v["blocking_risk"], "critical");
}
#[test]
fn abusable_site_serializes_mitre_techniques_as_array() {
let site = abusable_site_info("raw.githubusercontent.com").unwrap();
let json = serde_json::to_string(site).unwrap();
let v: serde_json::Value = serde_json::from_str(&json).unwrap();
assert!(v["mitre_techniques"].is_array());
assert!(v["mitre_techniques"]
.as_array()
.unwrap()
.contains(&serde_json::json!("T1102")));
}
#[test]
fn full_catalog_serializes_to_json_array() {
let json = serde_json::to_string(ABUSABLE_SITES).unwrap();
let arr: Vec<serde_json::Value> = serde_json::from_str(&json).unwrap();
assert!(arr.len() >= 30, "expected ≥30 sites, got {}", arr.len());
assert!(arr.iter().all(|v| v["domain"].is_string()));
assert!(arr.iter().all(|v| v["blocking_risk"].is_string()));
}
}
#[cfg(test)]
mod expansion_tests {
use super::*;
#[test]
fn sites_contains_graph_microsoft_com() {
assert!(abusable_site_info("graph.microsoft.com").is_some());
}
#[test]
fn sites_contains_trycloudflare() {
assert!(abusable_site_info("*.trycloudflare.com").is_some());
}
#[test]
fn sites_contains_ngrok() {
assert!(abusable_site_info("*.ngrok.io").is_some());
}
#[test]
fn sites_contains_netlify() {
assert!(abusable_site_info("*.netlify.app").is_some());
}
#[test]
fn sites_contains_onedrive() {
assert!(abusable_site_info("onedrive.live.com").is_some());
}
#[test]
fn sites_contains_azure_blob() {
assert!(abusable_site_info("*.blob.core.windows.net").is_some());
}
#[test]
fn sites_contains_transfer_sh() {
assert!(abusable_site_info("transfer.sh").is_some());
}
#[test]
fn sites_contains_file_io() {
assert!(abusable_site_info("file.io").is_some());
}
#[test]
fn sites_contains_gitee() {
assert!(abusable_site_info("gitee.com").is_some());
}
#[test]
fn sites_contains_box() {
assert!(abusable_site_info("*.box.com").is_some());
}
#[test]
fn sites_contains_4shared() {
assert!(abusable_site_info("4shared.com").is_some());
}
#[test]
fn sites_contains_mediafire() {
assert!(abusable_site_info("mediafire.com").is_some());
}
#[test]
fn sites_contains_webhook_site() {
assert!(abusable_site_info("webhook.site").is_some());
}
#[test]
fn sites_contains_pipedream() {
assert!(abusable_site_info("*.pipedream.net").is_some());
}
#[test]
fn sites_contains_discord_cdn() {
assert!(abusable_site_info("cdn.discordapp.com").is_some());
}
#[test]
fn sites_contains_ipinfo() {
assert!(abusable_site_info("ipinfo.io").is_some());
}
#[test]
fn sites_contains_ipify() {
assert!(abusable_site_info("api.ipify.org").is_some());
}
#[test]
fn abusable_sites_has_at_least_50_entries() {
assert!(
ABUSABLE_SITES.len() >= 50,
"expected ≥50 sites after LOTS expansion, got {}",
ABUSABLE_SITES.len()
);
}
}