// Package incident provides detection and cleanup of compromised packages,
// malicious .pth / lifecycle artifacts, and persistence vectors across the
// supported language ecosystems (Python and npm).
package incident

// Ecosystem identifiers for CompromisedPackage entries and IsCompromised
// lookups. The default empty value is treated as PyPI for backward
// compatibility with releases that predate the ecosystem field.
const (
	EcosystemPyPI = "pypi"
	EcosystemNPM  = "npm"
)

// CompromisedPackage describes a known-bad package+version combination.
// Ecosystem identifies the registry the package belongs to so the same
// data structure can hold PyPI and npm entries without collision (real
// names overlap across registries). IOCs is an optional list of
// indicators of compromise (file paths, hashes, network endpoints) that
// extend a detector beyond the package+version tuple.
type CompromisedPackage struct {
	Ecosystem string   `json:"ecosystem,omitempty"`
	Name      string   `json:"name"`
	Versions  []string `json:"versions"`
	Advisory  string   `json:"advisory"`
	Date      string   `json:"date"`
	Summary   string   `json:"summary"`
	IOCs      []IOC    `json:"iocs,omitempty"`
}

// IOC is a single indicator of compromise associated with a known-bad
// package. Type names the indicator class (path, hash, endpoint); Value
// is the literal string the detector looks for. Optional and additive;
// older entries that do not carry IOCs continue to work.
type IOC struct {
	Type  string `json:"type"`
	Value string `json:"value"`
}

// KnownCompromised is the embedded list of known compromised packages.
// Updated with each Aguara release.
//
// Entries are matched by (Ecosystem, Name, Version). An entry with an
// empty Ecosystem is treated as PyPI so IsCompromised stays
// backward-compatible with prior callers that did not supply an
// ecosystem argument.
var KnownCompromised = []CompromisedPackage{
	{
		Ecosystem: EcosystemPyPI,
		Name:      "litellm",
		Versions:  []string{"1.82.7", "1.82.8"},
		Advisory:  "PYSEC-2026-litellm",
		Date:      "2026-03-24",
		Summary:   "Malicious .pth file exfiltrates credentials (SSH, cloud, K8s) and installs backdoor with systemd persistence",
	},

	// --- npm ---
	//
	// Historical npm compromises with publicly-published advisories.
	// Maintainers should extend this list as new incidents are
	// confirmed via npm advisories or vendor disclosures. Each entry
	// must cite the source advisory in the Advisory field; speculative
	// or unverified package/version tuples do not belong here.
	{
		Ecosystem: EcosystemNPM,
		Name:      "event-stream",
		Versions:  []string{"3.3.6"},
		Advisory:  "GHSA-mh6f-8j2x-4483",
		Date:      "2018-11-26",
		Summary:   "event-stream 3.3.6 shipped a malicious flatmap-stream dependency that targeted bitcoin wallets in copay-dash; the version was unpublished and remediated by maintainers.",
	},
	{
		Ecosystem: EcosystemNPM,
		Name:      "flatmap-stream",
		Versions:  []string{"0.1.1"},
		Advisory:  "GHSA-mh6f-8j2x-4483",
		Date:      "2018-11-26",
		Summary:   "Malicious dependency injected through event-stream 3.3.6; exfiltrated wallet data from copay-dash.",
	},
	{
		Ecosystem: EcosystemNPM,
		Name:      "ua-parser-js",
		Versions:  []string{"0.7.29", "0.8.0", "1.0.0"},
		Advisory:  "GHSA-pjwm-rvh2-c87w",
		Date:      "2021-10-22",
		Summary:   "Compromised ua-parser-js versions installed cryptominer and credential-stealing payloads on Linux and Windows.",
	},
	{
		Ecosystem: EcosystemNPM,
		Name:      "coa",
		Versions:  []string{"2.0.3", "2.0.4", "2.1.1", "2.1.3", "3.0.1", "3.1.3"},
		Advisory:  "GHSA-73qr-pfmq-6rp8",
		Date:      "2021-11-04",
		Summary:   "Compromised coa releases delivered credential-stealing payload; package was unpublished and remediated.",
	},
	{
		Ecosystem: EcosystemNPM,
		Name:      "rc",
		Versions:  []string{"1.2.9", "1.3.9", "2.3.9"},
		Advisory:  "GHSA-g2q5-5433-rhrf",
		Date:      "2021-11-12",
		Summary:   "Compromised rc releases delivered the same credential-stealing payload as the coa incident from the same week.",
	},
	{
		Ecosystem: EcosystemNPM,
		Name:      "node-ipc",
		Versions:  []string{"9.1.6", "9.2.3", "12.0.1"},
		Advisory:  "SOCKET-2026-05-14-node-ipc",
		Date:      "2026-05-14",
		Summary:   "Compromised node-ipc releases shipped an obfuscated CommonJS credential-stealing payload in node-ipc.cjs; CommonJS consumers trigger it via require(\"node-ipc\"). Exfiltrates secrets via DNS TXT queries against bt.node.js and an HTTPS endpoint at sh.azurestaticprovider.net.",
		IOCs: []IOC{
			{Type: "hash", Value: "96097e0612d9575cb133021017fb1a5c68a03b60f9f3d24ebdc0e628d9034144"},
			{Type: "endpoint", Value: "sh.azurestaticprovider.net"},
			{Type: "endpoint", Value: "37.16.75.69"},
			{Type: "dns-zone", Value: "bt.node.js"},
			{Type: "runtime", Value: "__ntw"},
			{Type: "runtime", Value: "__ntRun"},
		},
	},
	{
		Ecosystem: EcosystemNPM,
		Name:      "node-ipc",
		Versions:  []string{"10.1.1", "10.1.2", "11.0.0", "11.1.0"},
		Advisory:  "SOCKET-node-ipc-historical-malicious",
		Date:      "2022-03-07",
		Summary:   "Historical malicious node-ipc releases (originally surfaced as the \"peacenotwar\" / RIAEvangelist incident) tied to destructive or unauthorized file-writing behavior on installs from specific geographies. Listed separately from the 2026 compromise because the payload and motivation differ.",
	},

	// --- Mini Shai-Hulud 2026 supply-chain wave (@antv) ---
	//
	// May 2026 campaign documented by Socket targeting AntV and a
	// small set of related visualization packages. The malicious
	// versions ship install-time / import-time credential-stealing
	// payloads. Every entry below is verified against the npm
	// registry: the registry's `deprecated` field on the version
	// carries an explicit security, "risk", "published in error",
	// or malicious-version notice. Versions without that registry
	// signal are intentionally omitted even when third-party
	// trackers list the package.
	//
	// The TanStack / Mistral / UiPath wave from the same campaign
	// is already covered by the embedded OSV snapshot
	// (MAL-2026-3432 and adjacent MAL-2026-* records) and is not
	// duplicated here.
	//
	// Sources:
	//   - https://socket.dev/blog/antv-packages-compromised
	//   - npm registry metadata (registry.npmjs.org)
	{
		Ecosystem: EcosystemNPM,
		Name:      "@antv/g2",
		Versions:  []string{"5.5.8", "5.6.8"},
		Advisory:  "SOCKET-2026-05-19-mini-shai-hulud-antv",
		Date:      "2026-05-19",
		Summary:   "Mini Shai-Hulud-linked npm compromise; affected @antv/g2 versions were flagged by the maintainers via npm's deprecated field (reason: \"risk\"). Aligned with the @antv wave Socket reported in May 2026.",
		IOCs: []IOC{
			{Type: "runtime", Value: "bun"},
			{Type: "path", Value: "setup.mjs"},
			{Type: "endpoint", Value: "filev2.getsession.org"},
			{Type: "endpoint", Value: "t.m-kosche.com"},
			{Type: "path", Value: "/api/public/otel/v1/traces"},
		},
	},
	{
		Ecosystem: EcosystemNPM,
		Name:      "@antv/g6",
		Versions:  []string{"5.2.1", "5.3.1"},
		Advisory:  "SOCKET-2026-05-19-mini-shai-hulud-antv",
		Date:      "2026-05-19",
		Summary:   "Mini Shai-Hulud-linked npm compromise; npm deprecated message flags these versions as published with a compromised key.",
	},
	{
		Ecosystem: EcosystemNPM,
		Name:      "@antv/x6",
		Versions:  []string{"3.2.7", "3.3.7"},
		Advisory:  "SOCKET-2026-05-19-mini-shai-hulud-antv",
		Date:      "2026-05-19",
		Summary:   "Mini Shai-Hulud-linked npm compromise; versions flagged via npm's deprecated field (reason: \"published in error\") and removed from latest dist-tag.",
	},
	{
		Ecosystem: EcosystemNPM,
		Name:      "@antv/l7",
		Versions:  []string{"2.26.10", "2.27.10"},
		Advisory:  "SOCKET-2026-05-19-mini-shai-hulud-antv",
		Date:      "2026-05-19",
		Summary:   "Mini Shai-Hulud-linked npm compromise; npm deprecated message labels these versions as malicious.",
	},
	{
		Ecosystem: EcosystemNPM,
		Name:      "@antv/f2",
		Versions:  []string{"5.16.0"},
		Advisory:  "SOCKET-2026-05-19-mini-shai-hulud-antv",
		Date:      "2026-05-19",
		Summary:   "Mini Shai-Hulud-linked npm compromise; npm deprecated message flags this version (reason: \"risk\").",
	},
	{
		Ecosystem: EcosystemNPM,
		Name:      "@antv/data-set",
		Versions:  []string{"0.12.8", "0.13.8"},
		Advisory:  "SOCKET-2026-05-19-mini-shai-hulud-antv",
		Date:      "2026-05-19",
		Summary:   "Mini Shai-Hulud-linked npm compromise; npm deprecated message flags these versions as published in error.",
	},
	{
		Ecosystem: EcosystemNPM,
		Name:      "echarts-for-react",
		Versions:  []string{"3.0.7", "3.1.7", "3.2.7"},
		Advisory:  "SOCKET-2026-05-19-mini-shai-hulud-antv",
		Date:      "2026-05-19",
		Summary:   "Mini Shai-Hulud-linked npm compromise affecting echarts-for-react alongside the @antv wave; npm deprecated message flags these versions as published in error.",
	},
	{
		Ecosystem: EcosystemNPM,
		Name:      "timeago.js",
		Versions:  []string{"4.1.2"},
		Advisory:  "SOCKET-2026-05-19-mini-shai-hulud-antv",
		Date:      "2026-05-19",
		Summary:   "Mini Shai-Hulud-linked npm compromise; npm deprecated message flags this version as published in error.",
	},
	{
		Ecosystem: EcosystemNPM,
		Name:      "size-sensor",
		Versions:  []string{"1.0.4", "1.1.4", "1.2.4"},
		Advisory:  "SOCKET-2026-05-19-mini-shai-hulud-antv",
		Date:      "2026-05-19",
		Summary:   "Mini Shai-Hulud-linked npm compromise; npm deprecated message flags these versions as published in error.",
	},
	{
		Ecosystem: EcosystemNPM,
		Name:      "canvas-nest.js",
		Versions:  []string{"2.2.4"},
		Advisory:  "SOCKET-2026-05-19-mini-shai-hulud-antv",
		Date:      "2026-05-19",
		Summary:   "Mini Shai-Hulud-linked npm compromise; npm deprecated message flags this version as published in error.",
	},
	{
		Ecosystem: EcosystemNPM,
		Name:      "@antv/g-image-exporter",
		Versions:  []string{"1.2.42"},
		Advisory:  "SOCKET-2026-05-19-mini-shai-hulud-antv",
		Date:      "2026-05-19",
		Summary:   "Mini Shai-Hulud-linked npm compromise; npm deprecated message flags this version as published in error. The version is also anomalous relative to the package's latest stable lineage (1.0.x), consistent with the @antv wave pattern of attacker-bumped majors/minors above the legitimate latest.",
	},
	{
		Ecosystem: EcosystemNPM,
		Name:      "@antv/infographic",
		Versions:  []string{"0.3.19", "0.4.19"},
		Advisory:  "SOCKET-2026-05-19-mini-shai-hulud-antv",
		Date:      "2026-05-19",
		Summary:   "Mini Shai-Hulud-linked npm compromise; npm deprecated message flags these versions as published with a compromised key.",
	},
}

// IsCompromised checks if a package name+version is in the PyPI
// section of the known-bad list. The legacy two-argument signature
// pre-dates the Ecosystem field; it stays scoped to PyPI so a Python
// package that happens to share a name with an npm advisory (e.g.
// `rc`, `event-stream`) is not falsely flagged by the Python
// checker. Callers that want a cross-ecosystem or npm-only lookup
// should use IsCompromisedIn explicitly.
func IsCompromised(name, version string) *CompromisedPackage {
	return findCompromised(EcosystemPyPI, name, version)
}

// IsCompromisedIn restricts the lookup to a specific ecosystem. Use
// this from the npm checker so a PyPI package that happens to share a
// name with an npm package is not falsely flagged.
func IsCompromisedIn(ecosystem, name, version string) *CompromisedPackage {
	return findCompromised(ecosystem, name, version)
}

func findCompromised(ecosystem, name, version string) *CompromisedPackage {
	for i := range KnownCompromised {
		entry := &KnownCompromised[i]
		if entry.Name != name {
			continue
		}
		if ecosystem != "" {
			entryEco := entry.Ecosystem
			if entryEco == "" {
				entryEco = EcosystemPyPI
			}
			if entryEco != ecosystem {
				continue
			}
		}
		for _, v := range entry.Versions {
			if v == version {
				return entry
			}
		}
	}
	return nil
}
