# Threat Intelligence

> Threat intelligence is evidence about attackers, their infrastructure, and techniques, processed into decisions to block, detect, or respond.

Also known as: CTI, Cyber Threat Intelligence, TI

Source: https://socket.dev/glossary/threat-intelligence

Last updated: 2026-11-05

Threat intelligence is evidence-based knowledge about attackers, their infrastructure, and their techniques, processed so a defender can make a decision with it. Also called cyber threat intelligence (CTI), it turns raw observations such as file hashes, domains, and malicious package versions into block, detect, and respond actions. It loses value quickly, so delivery speed matters as much as accuracy.

NIST defines threat intelligence as threat information "that has been aggregated, transformed, analyzed, interpreted, or enriched to provide the necessary context for decision-making processes" ([NIST SP 800-150](https://csrc.nist.gov/glossary/term/threat_intelligence)). The operative word is decision. A list of bad IP addresses is data. Intelligence is knowing which of them should block traffic on your network today, and being right about it.

For open source software, we think most threat intelligence is aimed at the wrong layer. Classic feeds describe attacker infrastructure: IP addresses, domains, and file hashes, pushed into a SIEM to find a compromise after it happens. [Malicious packages](https://socket.dev/glossary/malicious-package) execute during install, often talk only to legitimate services, and are pulled from the registry within hours. The indicator that works is the package name and version, derived from analyzing what is actually inside the package, and enforced before the install runs.

The most important fact in this article comes from the [keyv and cacheable compromise](https://socket.dev/supply-chain-attacks/keyv-and-cacheable-compromise) of August 4, 2026. Every network indicator in our write-up pointed at legitimate infrastructure: cloud metadata addresses, github.com, and registry.npmjs.org. An IP or domain blocklist had nothing to block.

## What is cyber threat intelligence?

Cyber threat intelligence is the same discipline as threat intelligence. The "cyber" prefix separates it from the military and law enforcement intelligence work it borrows its methods from. Practitioners split it by audience:

- **Strategic** intelligence is for leadership: which adversaries target your sector, and why. A state-backed group that steals developer credentials changes budget, hiring, and risk decisions.
- **Operational** intelligence describes campaigns and adversary behavior, usually in the vocabulary of [MITRE ATT&CK](https://socket.dev/glossary/adversarial-tactics-techniques-and-common-knowledge-att-and-ck). Malicious packages map to technique T1195.002, Compromise Software Supply Chain.
- **Tactical** intelligence is machine-readable: [indicators of compromise](https://socket.dev/glossary/indicators-of-compromise-ioc) such as hashes, IP addresses, domains, and, for software, package versions.

Threat intelligence comes from four kinds of source. The first is your own telemetry: logs, alerts, and incident findings. The second is commercial vendors. The third is government agencies and sector sharing groups. The fourth is open source intelligence (OSINT), meaning public material such as registry metadata, code repositories, paste sites, and published research. Large vendors run dedicated research teams. Microsoft's team, long branded the Microsoft Threat Intelligence Center (MSTIC), [moved to a weather-based naming taxonomy](https://www.microsoft.com/en-us/security/blog/?p=127276) for threat actors in April 2023.

A threat intelligence platform (TIP) is the system that ingests these feeds, deduplicates and scores them, and pushes the result to enforcement points: firewalls, endpoint agents, a SIEM, or a [package firewall](https://socket.dev/glossary/package-firewall). The platform is plumbing. A TIP is only as good as the analysis behind each record it carries.

## How is threat intelligence shared between organizations?

Threat intelligence is shared through three standards: STIX for the data, TAXII for transport, and TLP for handling rules. STIX 2.1 and TAXII 2.1 became OASIS Standards on June 10, 2021 ([OASIS](https://docs.oasis-open.org/cti/taxii/v2.1/taxii-v2.1.html)).

STIX (Structured Threat Information Expression) models intelligence as JSON objects: indicators, malware, threat actors, campaigns, and the relationships between them. An indicator carries a detection pattern. We generated and validated this STIX 2.1 indicator for the trojanized keyv release with the OASIS `stix2` Python library, version 3.0.2:

```json
{
  "type": "indicator",
  "spec_version": "2.1",
  "id": "indicator--c62e4521-056b-430a-b90c-eab38c51ecf8",
  "created": "2026-11-05T21:47:22.950986Z",
  "modified": "2026-11-05T21:47:22.950986Z",
  "name": "keyv@6.0.0 (npm) trojanized release",
  "indicator_types": ["malicious-activity"],
  "pattern": "[software:name = 'keyv' AND software:version = '6.0.0']",
  "pattern_type": "stix",
  "pattern_version": "2.1",
  "valid_from": "2026-08-04T09:35:00Z"
}
```

The pattern has a gap. The STIX 2.1 Software object has `name`, `cpe`, `swid`, `languages`, `vendor`, and `version`, and no field for the package ecosystem ([stix2 docs](https://stix2.readthedocs.io/en/v3.0.1/api/stix2.v21.html)). The pattern above matches anything called keyv, whether it came from npm, PyPI, or a vendor installer. STIX was designed around hosts and networks. Package identity gets bolted on through custom properties or a package URL in free text.

TAXII (Trusted Automated Exchange of Intelligence Information) is the HTTPS API that moves STIX objects. A client polls a collection and asks only for objects it has not seen:

```http
GET /api1/collections/91a7b528-80eb-42ed-a74d-c6fbd5a26116/objects/?added_after=2026-08-04T09:35:00Z HTTP/1.1
Host: taxii.example.com
Accept: application/taxii+json;version=2.1
```

The `added_after` filter keys on when the server added an object, not on any timestamp inside it. That distinction matters later in this article. TAXII 2.1 reserves keywords for publish-subscribe Channels but does not specify them, so in practice consumers poll.

TLP (Traffic Light Protocol) tells recipients how far they may pass a report along. FIRST's TLP 2.0, authoritative since August 2022, defines five labels ([FIRST](https://www.first.org/tlp/)):

| Label | Who may receive it |
| --- | --- |
| TLP:RED | Only the named individual recipients |
| TLP:AMBER+STRICT | The recipient's own organization |
| TLP:AMBER | The recipient's organization and its clients, on a need-to-know basis |
| TLP:GREEN | Peers and partners in the community, not public channels |
| TLP:CLEAR | Anyone, including the public |

TLP 2.0 renamed TLP:WHITE to TLP:CLEAR, but the predefined markings in STIX 2.1 still use the 1.0 names. The reference `stix2` library ships `TLP_WHITE` and has no `TLP_CLEAR`. FIRST is explicit that "TLP is not a formal classification scheme." Nothing enforces a TLP label except the recipient's discipline.

## Why do IP and domain indicators fail against malicious packages?

IP and domain indicators fail against malicious packages because package malware rarely needs attacker-owned infrastructure that a defender could block. David Bianco's Pyramid of Pain, published in March 2013, ranks indicator types by "how much pain it will cause them when you are able to deny those indicators to them" ([Bianco](http://detect-respond.blogspot.com/2013/03/the-pyramid-of-pain.html)). Hash values sit at the bottom, because a tiny change "results in a completely different and unrelated hash value." IP addresses, domains, host artifacts, tools, and tactics, techniques, and procedures (TTPs) sit above them, in rising order of attacker cost.

Apply the pyramid to the keyv and cacheable compromise. A compromised maintainer account published keyv@6.0.0 with a [preinstall hook](https://socket.dev/glossary/postinstall-scripts) that downloaded a standalone Bun runtime, ran an obfuscated credential stealer, and republished trojanized versions of other packages the stolen npm token could reach ([Socket](https://socket.dev/blog/popular-npm-packages-in-the-keyv-and-cacheable-namespaces-compromised-in-active-supply-chain)). The tradecraft closely matched [Shai-Hulud](https://socket.dev/blog/happy-birthday-shai-hulud), the self-propagating npm worm first seen in September 2025. These are the network indicators from our write-up:

```text
169[.]254[.]169[.]254
169[.]254[.]170[.]2
github[.]com/oven-sh/bun/releases/download/bun-v1.3.13/
registry[.]npmjs[.]org/-/whoami
registry[.]npmjs[.]org/-/npm/v1/tokens
registry[.]npmjs[.]org/-/npm/v1/oidc/token/exchange/package/
```

Every indicator on that list is legitimate infrastructure. The first two are the AWS instance metadata endpoint and the ECS credential endpoint. The rest are GitHub release downloads and the npm registry's own API. Exfiltration went to attacker-created GitHub repositories and to destinations resolved over DNS, so no fixed command-and-control host existed. A firewall rule against any of these breaks your own CI long before it inconveniences the attacker.

| Indicator | keyv campaign example | Usefulness to a defender |
| --- | --- | --- |
| Tarball hash | sha512 of keyv-6.0.0.tgz | Exact but brittle. The payload recomputes integrity fields for every package it republishes, so each tarball hash is new. |
| File hash | SHA-256 of setup.mjs and Math\_Symbol.js | Good for hunting on disk after the fact. One edit to the loader defeats it. |
| IP address | 169.254.169.254 (cloud metadata) | None. It is the victim's own cloud service. |
| Domain | github.com, registry.npmjs.org | None. Blocking them blocks development. |
| Package version | keyv@6.0.0, file-entry-cache@11.1.6 | High. Every trojanized version is a public registry event that can be analyzed before anyone installs it. |
| Behavior (TTP) | Install hook fetches a second runtime, reads cloud credentials, republishes packages | Highest. The attack cannot work without it. |

The Pyramid of Pain has no row for package versions, so we added one. For open source, the package version is the tactical indicator that maps one-to-one onto what a package manager resolves. The durable signal is behavior, found by analyzing what the package does at install time rather than trusting its metadata.

## What threat intelligence for open source packages looks like

Open source threat intelligence centers on package records, not network indicators. Malware does not get a CVE, and the National Vulnerability Database does not track malicious packages. Our CEO argued on the Risky Business podcast that this missing database is a central gap in [open source malware tracking](https://socket.dev/blog/why-open-source-software-needs-better-malware-tracking). The closest shared substitute is the OpenSSF malicious-packages repository, which publishes reports in the [OSV](https://socket.dev/glossary/osv) format under `MAL-` identifiers.

This is the record for keyv@6.0.0, trimmed to the fields a consumer acts on. The full file is [MAL-2026-11524](https://github.com/ossf/malicious-packages/blob/main/osv/malicious/npm/keyv/MAL-2026-11524.json):

```json
{
  "schema_version": "1.7.4",
  "id": "MAL-2026-11524",
  "published": "2026-08-04T11:19:14Z",
  "aliases": ["GHSA-3p9h-f68w-m6fx"],
  "summary": "Malicious code in keyv (npm)",
  "affected": [{
    "package": { "name": "keyv", "ecosystem": "npm" },
    "versions": ["6.0.0"],
    "database_specific": {
      "cwes": [{ "cweId": "CWE-506", "name": "Embedded Malicious Code" }],
      "indicators": {
        "evidence_files": [
          { "path": "setup.mjs", "sha256": "54dc7ea54a1317cca0e890a2770630cf7fa6c97813e0cb9d2caa93012b350668" },
          { "path": "Math_Symbol.js", "sha256": "9fc2570b7cef51c1b8df116d144d11ff4096357be7d2c4c6367cfc2509cf1bcc" }
        ],
        "package_integrity": [{
          "filename": "keyv-6.0.0.tgz",
          "hashes": { "sha512_sri": "sha512-N/n4R+nD5SC0fYOpAp4ZnbwwxqGVodgEZ9D7Gm/VBocorU0aQimVyleDWSY6/axdO0/temub760n3hnMppZpUg==" }
        }]
      }
    }
  }],
  "database_specific": {
    "malicious-packages-origins": [
      { "source": "amazon-inspector", "import_time": "2026-08-04T21:33:11.726128238Z" },
      { "source": "ghsa-malware", "import_time": "2026-08-05T00:10:17.860265883Z" }
    ]
  }
}
```

Three fields make this record more useful than the STIX indicator. The `ecosystem`, `name`, and `versions` triple is an exact key, the same one a package manager resolves. The `sha512_sri` value uses the same Subresource Integrity format npm writes into the `integrity` field of `package-lock.json`, so a [lockfile](https://socket.dev/glossary/lockfile) can be matched against it with a string comparison. And the evidence is a pair of files inside the tarball, not an IP address.

| Property | STIX 2.1 indicator | OSV malicious-package record |
| --- | --- | --- |
| Identity key | Software name and version, no ecosystem | Ecosystem, name, and exact versions |
| Lockfile matching | No native integrity field | sha512\_sri matches npm integrity values |
| Context | Rich: actors, campaigns, ATT&CK techniques, relationships | Free-text details and aliases only |
| Transport | TAXII 2.1 collections | A Git repository and the OSV API |
| Handling rules | TLP markings built in | None; records are public |
| Best for | Joining a package compromise to a wider incident in a SIEM or TIP | Gating installs and scanning dependency trees |

Our verdict: use OSV-format package records to gate installs and match lockfiles, because their identity key is the one your package manager uses. Use STIX when a package compromise has to join a broader investigation with actors, infrastructure, and host telemetry. Translate OSV records into STIX at that boundary, not the other way around.

## How fast does threat intelligence reach defenders?

Threat intelligence about a malicious package reaches most defenders hours after the package can already run. We reconstructed the keyv@6.0.0 timeline from the npm registry's publish timestamps, our published detection timing, and the origin metadata inside the OSV record.

> Time from keyv@6.0.0 publication to each detection and intelligence event, log scale

| Time (UTC) | Elapsed | Event | Source |
| --- | --- | --- | --- |
| Aug 4, 09:35:00 | 0 | keyv@6.0.0 published with the malicious preinstall hook | npm registry time field |
| Aug 4, ~09:41 | ~6 min | Socket flags the hook as malware | Socket write-up |
| Aug 4, 10:09 to 10:14 | ~35 min | Attacker publishes nine trojanized cacheable-family packages | Socket write-up |
| Aug 4, 11:19 | 1 h 44 min | GitHub advisory GHSA-3p9h-f68w-m6fx timestamped | OSV record origins |
| Aug 4, 21:33 | 11 h 58 min | First source report imported into OpenSSF malicious-packages | OSV record origins |
| Aug 5, 00:10 | 14 h 35 min | GitHub advisory report imported into the same repository | OSV record origins |

Across the campaign, Socket detected affected artifacts an average of 5 minutes and 18 seconds after publication ([Socket](https://socket.dev/blog/popular-npm-packages-in-the-keyv-and-cacheable-namespaces-compromised-in-active-supply-chain)). The attacker had spread to a second package family before the first public advisory existed.

The OSV record exposes a subtler problem. Its `published` field says 11:19 UTC, but its origin metadata shows the first source report reached the repository at 21:33 UTC. A consumer syncing that repository could not have seen the record for roughly ten hours after its own published timestamp. A feed timestamp records when something was true, not when you could have known it. Any retro-hunt that asks for "malware published since my last sync" will miss records that arrive backdated. TAXII's `added_after` avoids that trap by keying on server arrival time.

You can check what the registry still remembers. npm no longer serves keyv@6.0.0, but it kept the version's publish timestamp:

```console
$ curl -s https://registry.npmjs.org/keyv \
    | jq '{published: .time["6.0.0"], still_served: (.versions | has("6.0.0"))}'
{
  "published": "2026-08-04T09:35:00.763Z",
  "still_served": false
}
$ curl -s https://registry.npmjs.org/keyv/6.0.0
"version not found: 6.0.0"
```

As of November 2026, the same check on file-entry-cache returns a publish time of 10:13:02 UTC for version 11.1.6 and `still_served: false`. Once a malicious version is gone, intelligence about it can only answer a retrospective question: were we hit?

## Bad threat intelligence breaks builds

False positives in threat intelligence are outages when feeds drive enforcement. On May 26, 2026, [OSV withdrew 157 malware reports](https://socket.dev/blog/osv-withdraws-157-malware-reports) after automated detections flagged legitimate npm and PyPI packages, including FastAPI 0.136.3. The FastAPI record called a new dependency "typosquat-shaped" but identified no payload, no install-time execution, and no exfiltration. Many of the withdrawn records traced to Amazon Inspector, which OpenSSF had added as an automated source in October 2025.

Malware verdicts carry more operational weight than vulnerability advisories. A vulnerability alert can be triaged by version range and reachability. A malware alert triggers blocked builds, emergency package removal, and credential rotation. When an enforcement point trusts a feed blindly, a wrong record becomes a self-inflicted incident for every consumer at once.

We draw two rules from this. Confidence has to travel with every record, and the evidence has to be inspectable. A record that says "malicious" without naming the file and the behavior should not gate a build on its own. Socket's [Threat Feed API](https://docs.socket.dev/reference/getorgthreatfeeditems) exposes this split directly: its `is_human_reviewed` filter returns only records that no longer need human validation ([changelog](https://socket.dev/changelog/new-query-parameter-for-threat-feed-api)). Human review costs time, so blocking on unreviewed machine verdicts and blocking on reviewed ones are separate policy decisions with different failure modes. Teams should make that choice explicitly rather than inherit a vendor default.

## Where threat intelligence should be enforced

Package threat intelligence should be enforced at install, because the install is when the payload runs. The keyv@6.0.0 preinstall hook executed before any project code, and the package's library code was byte-identical by SHA-256 to the clean release candidate. Nothing downstream of the install would have looked wrong. A package firewall checks each package request against known malicious packages and blocks it before download. That only works if the verdict exists within minutes of publication, which is why we derive verdicts from analyzing package contents at publish time instead of waiting for downstream reports.

Retrospective hunting is the fallback, and it is weaker than it looks. Matching MAL records against lockfiles finds packages installed into tracked projects. It misses code fetched by `npx`, global installs, and ephemeral CI jobs, none of which leave a project lockfile behind. The [axios compromise](https://socket.dev/blog/axios-npm-package-compromised) showed the limit. As our [analysis of its blast radius](https://socket.dev/blog/hidden-blast-radius-of-the-axios-compromise) put it, "The absence of evidence after the fact is not strong evidence of absence." A clean lockfile does not prove you were safe. Socket's Threat Intel campaigns view [answers "were we hit?" from install-time evidence](https://socket.dev/blog/threat-intel-campaign-impact) instead, showing whether each campaign package was blocked by Socket Firewall or detected in scans, with links to the specific events.

[Package provenance](https://socket.dev/glossary/package-provenance) does not substitute for threat intelligence. keyv@6.0.0 shipped with a valid, signed provenance attestation, because the legitimate release workflow built source the attacker had already trojanized. Provenance correctly answered "was this built by the expected pipeline?" It could not answer "is this code malicious?"

The open problem is a source of truth. Open source has no authoritative database for malicious packages that is both fast and careful. OSV is open and structured, but May 26 showed it is only as reliable as its automated sources, and its import times can trail an attack by half a day. Vendor feeds can be faster, but they are proprietary. Until that changes, every team consuming package threat intelligence is choosing between being late and being wrong, and its install policy should say which one it prefers.
