/** * Threat intelligence integration (v4.5). * * Loads external IOC feeds (JSON), merges with local blocklist, * and provides confidence-scored IOC matching with decay. */ import type { Finding } from "./types.js"; export interface FeedIOC { type: "domain" | "ip" | "url" | "hash" | "package"; value: string; severity: "critical" | "high" | "medium"; confidence: number; family?: string; campaign?: string; source?: string; firstSeen?: string; lastSeen?: string; } export declare const CACHE_DIR = ".scg-cache"; export declare const FEED_CACHE_FILE = "threat-feed.json"; /** * Copy of the bundled (compiled-in) IOC feed, without any cached remote * entries merged. Used by "feed stats" to distinguish bundled vs effective * entry counts; scripts/generate-feed.mjs derives the publishable feed.json * from the same array (parsed out of this source file, single source of truth). */ export declare function getBundledFeed(): FeedIOC[]; /** * Load and merge IOC feeds. Starts with bundled feed, merges remote if available. */ export declare function loadThreatIntel(cacheDir?: string, remoteFeedUrl?: string): FeedIOC[]; /** * Update remote threat feed and cache locally. */ export declare function updateThreatFeed(feedUrl: string, cacheDir?: string): Promise<{ added: number; total: number; }>; /** * Structural check: is this file supply-chain-guard's own threat-feed data * (the published feed.json or the .scg-cache/threat-feed.json cache)? * * The feed intentionally contains RAW IOC values (domains, IPs, package * names) as machine-readable detection data - the same reason the scanner's * own source files are IOC-excluded. Without this check, any repo that * commits the published feed (or the refresh cache) drowns in phantom * criticals from its own protection data (v5.4.0 dogfooding find: 169 * findings on this repo's feed.json). * * Strictness is the security property: valid JSON, top-level keys and every * entry key from a fixed allowlist, entries hold only inert scalars. Any * deviation -> file is scanned like everything else. */ export declare function isInertThreatFeedFile(filename: string, content: string): boolean; /** * Validity gate for a single feed entry. Remote/cached entries are * JSON.parse results cast to FeedIOC without any runtime check, so every * consumer-facing load path filters through this. Invalid entries are * quarantined (dropped) deterministically instead of crashing a scan or * flooding it with garbage-literal matches. */ export declare function isValidFeedIOC(entry: unknown): entry is FeedIOC; export declare function checkThreatIntel(content: string, relativePath: string, feed: FeedIOC[]): Finding[]; /** * Match a package name (and optional exact version) against type:"package" * feed entries carrying an ecosystem prefix ("ruby:", "composer:", "nuget:", * "go:"). checkThreatIntel() deliberately skips package entries (they would * false-positive on file content); ecosystem scanners resolve them here * against parsed manifest/lockfile package lists instead. * * IOC values come in two shapes: * - bare name ("ruby:knot-date-utils-rb") - matches every version * - name@version ("nuget:Sicoob.Sdk@2.0.0") - matches only that version * * NuGet package ids are case-insensitive, so the "nuget" ecosystem compares * names ignoring case. Other registries treat names as case-sensitive * (RubyGems/Packagist names are lowercase by convention). */ export declare function matchPackageIOC(ecosystem: string, name: string, version?: string, feed?: FeedIOC[]): FeedIOC | null; //# sourceMappingURL=threat-intel.d.ts.map