Skip to main content
Glama
README.md
# threatkb

threatkb answers questions about the MITRE ATT&CK knowledge base
from a dataset file you keep on your own machine: look a technique
up by its ATT&CK id or by an approximate name, pull the full record
for a technique (platforms, kill-chain phases, references,
sub-techniques, mitigations, detections), list the mitigations or
detections tied to a technique, and list the tactics the dataset
knows about. One binary serves a command-line interface and a
stdio MCP server.

There is no bundled dataset and no network service behind this
tool. You point it at a STIX bundle in the
`enterprise-attack.json` shape (the layout MITRE publishes for the
enterprise matrix) with the `THREATKB_DATA_FILE` environment
variable. When the variable is unset or the file cannot be read,
the query commands fail with an error naming the missing dataset
instead of guessing — threatkb never invents ATT&CK data.
`threatkb info` still answers in that state and reports
`dataset_loaded: false` with the reason.

## Install

```bash
THREATKB_DATA_FILE=/path/to/enterprise-attack.json npx @reneturcios/threatkb tactics
```

Or run the container image:

```bash
docker run -i -e THREATKB_DATA_FILE=/data/enterprise-attack.json \
  -v /path/to/data:/data ghcr.io/cloudcorprecords/threatkb
```

The container defaults to the MCP server (see below). Pass CLI
arguments to use it as a CLI instead.

## CLI

```bash
export THREATKB_DATA_FILE=/path/to/enterprise-attack.json

threatkb query --id T1059
threatkb query --name "command and scripting"
threatkb full --id T1059
threatkb full --name PowerShell
threatkb mitigations T1059
threatkb detections T1059
threatkb tactics
threatkb info

threatkb --version
```

Results print as JSON. Technique searches return
`{results: [...], count: N}`; mitigation and detection queries
return `{technique_id, results: [...], count: N}` for the one
technique asked about, and an unknown technique id is an error.
Exit codes: `0` on success, `1` when a query fails (including a
missing dataset), `2` for usage errors.

Lookup rules: an id lookup is exact and case-insensitive
(`t1059` finds `T1059`). A name lookup is fuzzy — exact name
first, then names starting with the query, then names containing
it, then names containing every word of the query.

## MCP server

One bin serves both faces. The `mcp` subcommand starts a stdio MCP
server:

```bash
npx -y @reneturcios/threatkb mcp
```

MCP client configuration:

```json
{
  "mcpServers": {
    "threatkb": {
      "command": "npx",
      "args": ["-y", "@reneturcios/threatkb", "mcp"],
      "env": {
        "THREATKB_DATA_FILE": "/path/to/enterprise-attack.json"
      }
    }
  }
}
```

### Tools

| Tool | Input | What it returns |
| --- | --- | --- |
| `query_technique` | `technique_id` or `tech_name` (one required in practice) | Matching technique summaries as `{results, count}`. |
| `search_technique_full` | `technique_id` or `tech_name` | The same matches with full detail: platforms, kill-chain phases, references, sub-techniques, mitigations, detections. |
| `query_mitigations` | `technique_id` (required) | Mitigations linked to that technique. |
| `query_detections` | `technique_id` (required) | Detections linked to that technique. |
| `list_tactics` | (none) | Every tactic in the dataset as `{results, count}`. |
| `server_info` | (none) | Server name, version, dataset path, whether the dataset loaded, and object counts when it did. |

### How the STIX dataset is read

threatkb indexes a deliberately simplified slice of the STIX
model, documented here so the limits are clear:

- Techniques are `attack-pattern` objects; the ATT&CK id comes
  from the `external_references` entry with source name
  `mitre-attack`. Tactics come from a technique's
  `kill_chain_phases` phase names.
- Tactics are `x-mitre-tactic` objects (with `x_mitre_shortname`).
- Mitigations are `course-of-action` objects linked to a
  technique by a `mitigates` relationship.
- Detections are `detects` relationships pointing at the
  technique; the relationship's source (usually an
  `x-mitre-data-component`) is resolved, including its data
  source name when linked. A technique's `x_mitre_detection`
  guidance text is also returned as a detection entry.
- Sub-techniques are recognised by `x_mitre_is_subtechnique` or a
  dotted id; the parent comes from a `subtechnique-of`
  relationship when present, otherwise from the id prefix.

Revocation/deprecation flags, analytics, data-source coverage
scoring, and group/software attribution are out of scope.

## Development

```bash
npm install
npm run build   # tsc -> dist/
npm test        # node test runner over test/*.test.ts, on a hand-written STIX fixture, no real dataset needed
npm run dev     # run the CLI from source via tsx
```

## License

MIT — see `LICENSE`.