# PS Banshee > A Recorded Future CLI for terminal-based threat intelligence investigations. Full single-file bundle (every command group inlined): Set `RF_TOKEN` in the shell environment before invoking any command. **Alerts:** Recorded Future has two distinct alert systems. Use `ca` for Classic Alerts - legacy rule-based alerts with short opaque IDs (6+ chars, e.g. `tybakN`). Use `pba` for Playbook Alerts - automation-driven alerts with 36-char UUID IDs (the `task:` prefix is optional; `pba search` returns them with the prefix). Categories exclusive to PBA: `domain_abuse`, `cyber_vulnerability`, `third_party_risk`, `code_repo_leakage`, `identity_novel_exposures`, `geopolitics_facility`, `malware_report`. If the user gives you an alert ID, pick the group by ID length; if they describe the category, the categories above route to `pba`. # Commands ## Banshee CLI Knowledge Base # Banshee CLI Knowledge Base > A Recorded Future CLI for terminal-based threat intelligence investigations. > Built by the Cyber Security Engineers at Recorded Future. > Validated against `ps-banshee` / `banshee` version 1.3.0. This knowledge base is designed for LLM consumption (Claude Code, Opus, and other agentic CLIs). Three artifacts are published for agents: - **Index** — concise table of contents: - **Full bundle** — every command group inlined in one document: - **Per-group pages** — for selective fetches, served as raw markdown at `https://.../latest/knowledge-base//index.md` (e.g. `ca`, `ioc`, `list`). Linked from the index above. To make `banshee` discoverable to your agent in a project, add an action-phrased line to your `CLAUDE.md`, `AGENTS.md`, or equivalent rules file: > When working with Recorded Future, fetch for the full `banshee` CLI reference, then use the `banshee` CLI. If that URL is unreachable, run `banshee --help` instead. Set `RF_TOKEN` in the shell environment before invoking — see [Authentication](#authentication-global-options) below. --- ## Authentication & Global Options ``` banshee [OPTIONS] COMMAND [ARGS]... ``` | Flag | Short | Description | |------|-------|-------------| | `--api-key TEXT` | `-k` | Recorded Future API key. Preferred: set `RF_TOKEN` env var instead. | | `--no-ssl-verify` | `-s` | Disable SSL verification (use with proxies via `HTTP_PROXY` / `HTTPS_PROXY`). | | `--debug` | | Enable debug mode. | | `--version` | | Show version. | | `--install-completion` | | Install shell tab completion. | | `--show-completion` | | Print completion config for manual install. | **Best practice:** Export `RF_TOKEN=` so you never pass `-k` on every call. --- ## Readiness Checks Before running workflows, verify the local toolchain and authentication path. ```bash # CLI is installed and reachable banshee --version banshee --help # Recorded Future API token is present test -n "$RF_TOKEN" && echo "RF_TOKEN set" # jq is required for most pipeline examples jq --version # Read-only API smoke tests banshee entity search wannacry -l 1 banshee ioc bulk-lookup ip 8.8.8.8 | jq '.[0] | {ioc: .entity.name, score: .risk.score}' # Required only for pcap workflows; without tshark, even `banshee pcap enrich --help` can fail command -v tshark ``` If `banshee` is missing, install the Python package `ps-banshee` through your approved Python package workflow, then re-run the checks above. --- ## Live Validation Snapshot Last live validation: **2026-06-12** (release 1.3.0 refresh) against `ps-banshee` / `banshee` **1.3.0** with `RF_TOKEN` authentication. Validated successfully: ```bash # Local toolchain and auth presence banshee --version banshee --help test -n "$RF_TOKEN" && echo "RF_TOKEN set" # Read-only API access banshee ca rules banshee ca rules leaked banshee ca search -t 7d banshee ca search -t 12h | banshee ca export banshee ca search -t 12h | banshee ca export --csv banshee pba search -C 60d -l 3 banshee pba search -o uhash:69sKLfTGsS -C 60d -l 3 banshee pba search -C 60d -l 3 | banshee pba export banshee pba search -C 60d -l 3 | banshee pba export --csv banshee ioc bulk-lookup ip 8.8.8.8 ``` Observed caveats: - `ca export` and `pba export` read **only** from stdin and take no positional arguments. Pipe `banshee ca search` / `banshee pba search` into them. - `pba export` consumes the full `pba search` JSON object (it reads `.data[]`), whereas `ca export` consumes the `ca search` JSON array. - In `ca export --csv` the `Updated` column is currently always empty (reserved for future API support) - confirmed in this run. - The new `pba search --org-id` (`-o`) filter accepts a 10-character ID or the 16-character `uhash:` form and is repeatable. - `pcap enrich` was not live-tested because `tshark` was not installed. This is expected: `banshee pcap enrich --help` raises `RuntimeError: tshark is not installed or not in PATH`. --- ## Output Conventions - All commands default to **JSON output** to stdout — pipe-friendly by design. - Add `--pretty` / `-p` to any command for human-readable formatted output. - Most commands support piping via stdin (newline- or whitespace-separated IDs/IOCs). - Combine with `jq` for advanced filtering (examples throughout). - Response shapes differ by endpoint. Notable patterns: - `ioc lookup` returns a JSON array and uses `.risk.evidenceDetails[]` for detailed risk evidence. - `ioc bulk-lookup` returns a JSON array and uses `.risk.rule.evidence[]` for bulk risk evidence. - `ioc search` returns an object with results under `.data.results[]`. - `pba search` returns an object with alert records under `.data[]`. - `pcap enrich` and `email enrich` return flat records such as `.ioc`, `.risk_score`, and `.rule_evidence[]`. --- ## Command Groups | Group | Page | Description | |-------|------|-------------| | `ca` | [ca.md](ca.md) | Classic Alerts — search, lookup, update, export | | `email` | [email.md](email.md) | Enrich EML files with RF intelligence | | `entity` | [entity.md](entity.md) | Entity search and lookup | | `ioc` | [ioc.md](ioc.md) | IOC enrichment, bulk enrichment, search, rules | | `list` | [list.md](list.md) | Manage RF Lists & Watch Lists (create, add/remove entities, entries) | | `pcap` | [pcap.md](pcap.md) | Enrich packet captures with RF intelligence | | `pba` | [pba.md](pba.md) | Playbook Alerts — search, lookup, update, export | | `risklist` | [risklist.md](risklist.md) | Fetch, create, and inspect risk lists | | `rules` | [rules.md](rules.md) | Search and download detection rules (Sigma, YARA, Snort) | --- ## Notes for LLMs - **All IDs are opaque short strings** (e.g. `tybakN`, `1b0s1q`) — never guess them; always retrieve via search first. - **PBA alert IDs** use UUID format and are returned with the `task:` prefix already included by `pba search` (`.data[].playbook_alert_id`). Pass them as-is to `pba lookup` and `pba update` — do not add an extra `task:`. - **`ca update` and `pba update` return plain text**, not JSON — `SUCCESS:\n` per updated alert. Do not pipe to `jq`. - **stdin piping** is consistent across all bulk/update commands: pipe newline-separated IDs or IOCs directly. - **`--pretty` is not JSON** — it's human-readable and unsuitable for further parsing with `jq`. Omit it in pipelines. - **Risk rules** (used in `ioc rules`, `risklist fetch`, `risklist create`) are named strings like `recentValidatedCnc`, `analystNote`, `recentPhishing`. Discover available rule names with `banshee ioc rules `. - **Entity IDs vs. name,type pairs**: `list bulk-add` / `list bulk-remove` accept both — use `SoA6SP` (RF ID) or `wannacry,Malware` (name + type) or `ip:8.8.8.8` (type-prefixed value). - **`risklist create --fusion`** uploads the result directly to RF Fusion; `--output-path` is then interpreted as a Fusion destination path, not a local path. - **`ioc lookup` vs `ioc bulk-lookup` evidence paths differ**: `ioc lookup` uses `.risk.evidenceDetails[]`; `ioc bulk-lookup` uses `.risk.rule.evidence[]`. They are not interchangeable. ## ca # ca > **Classic Alerts** - legacy rule-based alerts. IDs are short opaque strings of 6+ chars (e.g. `tybakN`). For automation/playbook-driven alerts (36-char UUID IDs with optional `task:` prefix, categories like `domain_abuse` / `third_party_risk` / etc.), use [`pba`](pba.md) instead. > > See [index.md](index.md) for authentication, readiness checks, output conventions, and shared LLM notes. ### `banshee ca lookup ALERT_ID` Retrieve a single Classic Alert by ID. | Argument/Option | Description | |-----------------|-------------| | `ALERT_ID` (required) | Alert ID, e.g. `tybakN` | | `--pretty` / `-p` | Pretty print | ```bash banshee ca lookup tybakN banshee ca lookup tybakN -p ``` **Response shape:** Returns a single JSON object. | Field | Description | |-------|-------------| | `.id` | Alert ID | | `.title` | Alert title | | `.type` | Alert type string (e.g. `"EVENT"`) | | `.log.triggered` | Trigger timestamp (ISO 8601) | | `.review.status_in_portal` | Human-readable status: `New`, `Pending`, `Dismissed`, `Resolved` | | `.review.assignee` | Assigned analyst email | | `.rule.id` | Alert rule ID | | `.rule.name` | Alert rule name | | `.url.portal` | Direct link to alert in RF portal | | `.ai_insights.text` | RF AI-generated summary string | | `.hits[]` | Documents that triggered the alert | | `.hits[].id` | Hit document ID | | `.hits[].fragment` | Text snippet that matched | | `.hits[].language` | Language code (e.g. `"eng"`) | | `.hits[].entities[]` | Entities found in the hit: `{id, name, type}` | | `.hits[].document.title` | Source document title | | `.hits[].document.url` | Source document URL | | `.hits[].document.source` | Source name string | | `.hits[].document.authors` | Array of author strings (may be empty) | | `.triggered_by[]` | Entities/rules that triggered the alert (may be empty) | | `.triggered_by[].reference_id` | Reference document ID | | `.triggered_by[].triggered_by_strings[]` | Human-readable trigger descriptions | | `.enriched_entities[]` | Pre-enriched entity objects with RF context (may be empty) | ```bash # Extract all entities from alert hits for enrichment banshee ca lookup tybakN | jq '[.hits[].entities[] | {id, name, type}] | unique_by(.id)' # Get the AI summary banshee ca lookup tybakN | jq -r '.ai_insights.text' # Get portal link banshee ca lookup tybakN | jq -r '.url.portal' ``` --- ### `banshee ca search` Search Classic Alerts with optional filters. | Option | Short | Default | Description | |--------|-------|---------|-------------| | `--triggered TEXT` | `-t` | `1d` | Time range. Relative (`1d`, `12h`) or absolute interval (`[2024-08-01, 2024-08-14]`). | | `--rule TEXT` | `-r` | | Filter by alert rule name (freetext, repeatable). | | `--status` | `-s` | | One of: `New`, `Pending`, `Dismissed`, `Resolved` | | `--pretty` | `-p` | | Pretty print | ```bash banshee ca search -t 1d banshee ca search -t "[2025-05-01, 2025-05-05]" -s Pending banshee ca search -t 12h -p banshee ca search -r "Leaked Credential Monitoring" -r "Brand Mentions with Cyber entities" -t 1d banshee ca search -r leaked -t 12h -p ``` **Response shape:** Returns a JSON array. Each alert object has the following top-level fields: | Field | Description | |-------|-------------| | `.id` | Alert ID (e.g. `tybakN`) | | `.title` | Alert title | | `.log.triggered` | Trigger timestamp (ISO 8601) | | `.review.status_in_portal` | Human-readable status: `New`, `Pending`, `Dismissed`, `Resolved` | | `.review.status` | Internal status string (`no-action`, etc.) — not useful for jq filtering | | `.rule.name` | Name of the alert rule that fired | | `.rule.id` | Alert rule ID | **Note:** There is no top-level `priority` field on `ca search` alert records. Use `.review.status_in_portal` (not `.review.status`) when filtering by status in jq pipelines. ```bash # Extract IDs of New alerts (use status_in_portal for jq filtering) banshee ca search -t 1d | jq -r '.[] | select(.review.status_in_portal == "New") | .id' # When using the -s flag, status filtering happens server-side — no jq select needed banshee ca search -t 1d -s New | jq -r '.[].id' ``` --- ### `banshee ca rules [FREETEXT]` List all Classic Alert rules, optionally filtered by freetext. | Argument/Option | Description | |-----------------|-------------| | `FREETEXT` (optional) | Search term to filter rule names | | `--pretty` / `-p` | Pretty print | ```bash banshee ca rules banshee ca rules -p ``` **Response shape:** Returns a flat JSON array. Each item has the following fields: | Field | Description | |-------|-------------| | `.id` | Rule ID (e.g. `k_TnPe`) | | `.title` | Rule name | | `.enabled` | `true`/`false` — whether the rule is active | | `.priority` | `true` = alerts from this rule are severity **High**; `false` = severity **Informational**. To triage by priority, fetch rules first and join to alerts via `.rule.id` (see Priority triage workflow below). | | `.tags` | Array of tag strings | | `.created` | Creation timestamp (ISO 8601) | | `.owner` | Object with `id` and `name` — rule owner | | `.intelligence_goals` | Array of `{id, name}` objects — associated intelligence goals | | `.notification_settings` | Object with `email_subscribers` array | Use `.title` and `.id` when constructing pipelines. `.priority` maps directly to alert severity: `true` is High, `false` is Informational. --- ### Priority triage workflow `ca search` and `ca lookup` do not return a per-alert severity field. To triage alerts by severity, fetch the rules list first, filter to rules where `.priority == true`, and intersect against alert `.rule.id` values: ```bash # High-priority alert IDs in the last day PRIORITY_RULES=$(banshee ca rules | jq -r '.[] | select(.priority == true) | .id' | paste -sd'|' -) banshee ca search -t 1d | jq --arg rules "$PRIORITY_RULES" -r '.[] | select(.rule.id | test("^(" + $rules + ")$")) | .id' ``` Pipe the resulting IDs straight into `banshee ca update` to status-change only the high-priority alerts. --- ### `banshee ca update [ALERT_IDS]...` Update one or more Classic Alerts. IDs can be passed as arguments, space-separated, or piped via stdin. | Option | Short | Description | |--------|-------|-------------| | `--status` | `-s` | New status: `New`, `Pending`, `Dismissed`, `Resolved` | | `--note TEXT` | `-n` | Add a text note | | `--append` | `-A` | Append to existing note instead of overwriting | | `--assignee TEXT` | `-a` | Reassign alert. Accepts `uhash:3aXZxdkM12` or `analyst@acme.com` | **Input methods:** ```bash # Single ID banshee ca update 8cORlQ -s Resolved # Multiple IDs (space-separated) banshee ca update 8cORlQ 8biCIG -s Pending # Pipe IDs from file cat alerts.txt | banshee ca update -s Dismissed # Pipe from search via jq banshee ca search | jq -r '.[].id' | banshee ca update -n "Investigation started" # stdin redirect banshee ca update -s Dismissed < alerts.txt ``` **Response:** Returns plain text, not JSON — one line per updated alert: `SUCCESS:\n`. Do not pipe to `jq`. --- ### `banshee ca export` Fetch full alert details for the alerts produced by `ca search` and emit them as JSON or CSV. Input is **stdin only** — pipe the JSON array from `banshee ca search`; there are no positional arguments. | Option | Short | Default | Description | |--------|-------|---------|-------------| | `--csv` | | JSON | Output as CSV (fixed column set) instead of JSON (full alert details). | ```bash banshee ca search -t 1d | banshee ca export banshee ca search -t 1d -r "Leaked Credential Monitoring" | banshee ca export > credential_alerts.json banshee ca search -t 12h -s Pending | banshee ca export --csv > alerts.csv ``` **Input:** Expects the JSON array emitted by `banshee ca search` on stdin; every element must have an `id`. Running with no piped input (a TTY) raises a `BadParameter` error. **Response shape (default):** A JSON array of full alert objects — the same per-alert structure returned by `banshee ca lookup` (`.id`, `.title`, `.log.triggered`, `.review`, `.rule`, `.hits[]`, etc.). **Response shape (`--csv`):** CSV with a header row and these fixed columns: `ID`, `Priority`, `Alert Rule`, `Status`, `Created`, `Updated`, `Title`, `Assignee`, `URL`, `Entities`, `Recorded Future AI Insights`. `Priority` is derived from the alert rule (`High` when the rule is a priority rule, otherwise `Informational`); commas inside field values are replaced with spaces. ## email # email > See [index.md](index.md) for authentication, readiness checks, output conventions, and shared LLM notes. ### `banshee email enrich FILE_PATH` Parse an EML file, extract IPs from headers, URLs/domains from the body, and attachment hashes, then enrich the indicators with RF threat intelligence. By default, only shows indicators above the risk score threshold (65). | Option | Short | Default | Description | |--------|-------|---------|-------------| | `--risk-score INTEGER` | `-r` | `65` | Show only indicators above this score (0–99) | | `--threat-hunt` | `-t` | `false` | Also include indicators linked to threat actors even if below the score threshold | | `--pretty` | `-p` | | Pretty print | Default JSON output is a flat array of records with fields such as `ioc`, `type`, `location`, `risk_score`, `first_seen`, `last_seen`, `rule_evidence`, `analyst_notes`, `malwares`, `count_of_analyst_notes`, and `ta_names`. ```bash banshee email enrich phishing_email.eml banshee email enrich phishing_submission.eml -r 1 -p # Extract the highest-risk indicators from an enriched EML banshee email enrich phishing_email.eml -r 1 | jq '[.[] | {ioc, type, location, score: .risk_score, top_rule: (.rule_evidence[0].rule // "")}] | sort_by(-.score)' ``` ## entity # entity > See [index.md](index.md) for authentication, readiness checks, output conventions, and shared LLM notes. ### `banshee entity lookup ENTITY_ID` Look up a Recorded Future entity by its ID. | Argument/Option | Description | |-----------------|-------------| | `ENTITY_ID` (required) | RF entity ID, e.g. `qf0H03` | | `--pretty` / `-p` | Pretty print | ```bash banshee entity lookup qf0H03 banshee entity lookup qf0H03 -p ``` **Response shape:** Returns a single JSON object with top-level keys `id`, `type`, and `attributes`. The entity name is nested under `.attributes.name`, not at the top level. ```bash # Correct jq to extract id, type, and name: banshee entity lookup qf0H03 | jq '{id, type, name: .attributes.name}' ``` --- ### `banshee entity search NAME` Search entities by name, optionally filtered by type. | Argument/Option | Short | Default | Description | |-----------------|-------|---------|-------------| | `NAME` (required) | | | Entity name to search | | `--type` | `-t` | | One or more entity types (repeatable). See full type list below. | | `--limit INTEGER` | `-l` | `100` | Max results (1–100) | | `--pretty` | `-p` | | Pretty print | **Common entity types (partial list):** `Malware`, `IpAddress`, `InternetDomainName`, `URL`, `Hash`, `CyberVulnerability`, `CyberThreatActorCategory`, `Organization`, `Person`, `Country`, `MitreAttackIdentifier`, `YaraDetectionRule`, `SnortDetectionRule`, `SigmaDetectionRule` (plus 100+ more). ```bash banshee entity search wannacry banshee entity search "Cobalt Strike" -p banshee entity search "Cobalt Strike" -t Malware -t Username -p -l 20 ``` **Response shape:** Returns a flat JSON array. Each item has exactly three fields: | Field | Description | |-------|-------------| | `.id` | RF entity ID (e.g. `SoA6SP`) | | `.name` | Entity display name | | `.type` | Entity type string (e.g. `Malware`, `InternetDomainName`) | ```bash # Extract all IDs matching a name banshee entity search "Cobalt Strike" -t Malware | jq -r '.[].id' # Build a lookup table of id → name banshee entity search wannacry | jq '[.[] | {(.id): .name}] | add' ``` ## ioc # ioc > See [index.md](index.md) for authentication, readiness checks, output conventions, and shared LLM notes. ### `banshee ioc lookup ENTITY_TYPE [IOC]...` Rich, per-IOC enrichment. One API call per indicator. Use for deep context. **Entity types:** `ip`, `domain`, `url`, `hash`, `vulnerability` | Option | Short | Default | Description | |--------|-------|---------|-------------| | `--verbosity INTEGER` | `-v` | `1` | Detail level 1–5 (see verbosity table below) | | `--ai-insights` | `-a` | | Include AI-generated summaries of risk rules | | `--pretty` | `-p` | | Pretty print | **Verbosity levels by entity type:** | Level | ip | domain | hash | url | vulnerability | |-------|----|--------|------|-----|---------------| | 1 | entity, risk, timestamps | entity, risk, timestamps | entity, hashAlgorithm, risk, timestamps | entity, risk, timestamps | entity, lifecycleStage, risk, timestamps | | 2 | + intelCard, location | + intelCard | + fileHashes, intelCard | + intelCard | + intelCard | | 3 | + analystNotes, links | + analystNotes, links | + analystNotes, links | + analystNotes, links | + analystNotes, links | | 4 | + enterpriseLists, riskMapping, sightings, threatLists | + enterpriseLists, riskMapping, sightings, threatLists | + enterpriseLists, riskMapping, sightings, threatLists | + enterpriseLists, riskMapping, sightings | + cvss, cvssv3, cvssv4, enterpriseLists, riskMapping, sightings, threatLists | | 5 | + dnsPortCert, scanner | same as 4 | same as 4 | same as 4 | + cpe, cpe22uri, nvdDescription, nvdReferences | ```bash banshee ioc lookup ip 139.224.189.177 banshee ioc lookup domain overafazg.org banshee ioc lookup ip 8.140.135.23 -v 3 banshee ioc lookup ip 8.140.135.23 139.224.189.177 -p # Pipe from CSV file cat test_ips.csv | banshee ioc lookup ip -p ``` **Response shape (verbosity 1):** Returns a JSON array. Each item has `entity`, `risk`, `timestamps`. Higher verbosity levels add: v2 `+intelCard, location`; v3 `+analystNotes, links`; v4 `+enterpriseLists, riskMapping, sightings, threatLists`; v5 `+dnsPortCert, scanner` (ip only). `.risk.evidenceDetails[]` item fields: | Field | Description | |-------|-------------| | `.rule` | Rule name string | | `.criticality` | Integer 0–4 (0–5 for vulnerabilities) | | `.criticalityLabel` | Human-readable label (e.g. `"Unusual"`, `"Malicious"`) | | `.evidenceString` | Human-readable evidence description | | `.mitigationString` | Mitigation guidance (may be empty string) | | `.timestamp` | Most recent evidence timestamp (ISO 8601) | **Advanced jq recipes:** ```bash # Most critical rule banshee ioc lookup ip 1.2.3.4 | jq '[ .[].risk.evidenceDetails[] ] | group_by(.criticality) | max_by(.[0].criticality) | .[].rule' # All triggered rules banshee ioc lookup ip 1.2.3.4 | jq '.[].risk.evidenceDetails[].rule' # Risk score + most critical rule banshee ioc lookup ip 1.2.3.4 | jq '[ .[] | ( [ .risk.evidenceDetails[].criticality ] | max ) as $max_crit | { score: .risk.score, rules: [ .risk.evidenceDetails[] | select(.criticality == $max_crit) | .rule ] } ]' # Risk score + all rules with criticality labels banshee ioc lookup ip 1.2.3.4 | jq '[ .[] | { score: .risk.score, rules: [.risk.evidenceDetails[] | {rule, label: .criticalityLabel}] } ]' ``` --- ### `banshee ioc bulk-lookup ENTITY_TYPE [IOC]...` Fast bulk enrichment — batches up to 1000 IOCs per API call. Returns risk score and triggered risk rules only. Use for high-volume triage. | Option | Description | |--------|-------------| | `--pretty` / `-p` | Pretty print | **Response shape:** Returns a JSON array. Each item has `entity` (`id`, `name`, `type`) and `risk`. Note: no `timestamps` key (unlike `ioc lookup`). `.risk` fields: | Field | Description | |-------|-------------| | `.risk.score` | Integer risk score 0–99 | | `.risk.level` | Integer criticality level | | `.risk.context` | Context object grouped by risk domain (`phishing`, `public`, `c2`, `malware`) | | `.risk.rule.count` | Number of triggered rules | | `.risk.rule.maxCount` | Max possible rules | | `.risk.rule.mostCritical` | Most critical rule name | | `.risk.rule.summary` | Array of summary strings | | `.risk.rule.evidence[]` | Array of triggered rule objects | `.risk.rule.evidence[]` item fields: | Field | Description | |-------|-------------| | `.rule` | Rule name string | | `.level` | Integer criticality 0–4 | | `.description` | HTML-tagged evidence string (entity refs use `` markup) | | `.count` | Hit count | | `.sightings` | Sighting count | | `.timestamp` | Most recent evidence timestamp (ISO 8601) | | `.mitigation` | Mitigation guidance (may be empty string) | | `.type` | Rule type string (e.g. `linkedIntrusion`) | Bulk risk rule evidence is under `.risk.rule.evidence[]`; this differs from `ioc lookup`, which uses `.risk.evidenceDetails[]`. ```bash banshee ioc bulk-lookup ip 92.38.178.133 203.0.113.17 banshee ioc bulk-lookup domain overafazg.org coolbeans.org -p banshee ioc bulk-lookup hash e3f236e4aeb73f8f8f0caebe46f53abbb2f71fa4b266a34ab50e01933709e877 # From file (one IOC per line) banshee ioc bulk-lookup vulnerability < cves.txt cat cves.txt | banshee ioc bulk-lookup vulnerability # Extract names and scores banshee ioc bulk-lookup vulnerability CVE-2021-22204 CVE-2016-4557 | jq '[.[] | {ioc: .entity.name, risk_score: .risk.score}]' # Extract names, scores, and triggered rule names banshee ioc bulk-lookup ip 92.38.178.133 | jq '[.[] | {ioc: .entity.name, score: .risk.score, rules: [(.risk.rule.evidence // [])[].rule]}]' ``` --- ### `banshee ioc search ENTITY_TYPE` Search the RF IOC corpus with filters. | Option | Short | Default | Description | |--------|-------|---------|-------------| | `--limit INTEGER` | `-l` | `5` | Max results (1–1000) | | `--risk-score TEXT` | `-r` | | Risk score range (interval notation) | | `--risk-rule TEXT` | `-R` | | Filter by risk rule name | | `--verbosity INTEGER` | `-v` | `1` | Detail level 1–5 (same table as `ioc lookup`) | | `--pretty` | `-p` | | Pretty print | **Risk score interval notation:** | Syntax | Meaning | |--------|---------| | `'[20,90]'` | 20 ≤ score ≤ 90 | | `'(20,90)'` | 20 < score < 90 | | `'[20,90)'` | 20 ≤ score < 90 | | `'[20,)'` | score ≥ 20 | | `'[,90)'` | score < 90 | Default JSON output is an object. Search results are under `.data.results[]`, and total/returned counts are under `.counts`. ```bash banshee ioc search ip -l 10 -r '(,80]' banshee ioc search domain -r '[90,)' banshee ioc search hash -r '[80,81]' -p banshee ioc search vulnerability --limit 1 -v 3 # Extract IOC names from search results banshee ioc search ip -r '[90,)' -l 100 | jq -r '.data.results[].entity.name' ``` --- ### `banshee ioc rules ENTITY_TYPE` List risk rules for an entity type, with optional filters. | Option | Short | Description | |--------|-------|-------------| | `--freetext TEXT` | `-F` | Filter rules by name/description | | `--mitre-code TEXT` | `-M` | Filter by MITRE ATT&CK code (e.g. `T1587.004`) | | `--criticality INTEGER` | `-C` | Filter by criticality 0–5 | | `--pretty` | `-p` | Pretty print | **Criticality reference (IP, Domain, URL, Hash):** | Level | Label | Risk Score Band | |-------|-------|----------------| | 4 | Very Malicious | 90–99 | | 3 | Malicious | 65–89 | | 2 | Suspicious | 25–64 | | 1 | Unusual | 5–24 | | 0 | No evidence of risk | 0 | **Criticality reference (Vulnerability):** | Level | Label | Risk Score Band | |-------|-------|----------------| | 5 | Very Critical | 90–99 | | 4 | Critical | 80–89 | | 3 | High | 65–79 | | 2 | Medium | 25–64 | | 1 | Low | 5–24 | | 0 | No evidence of risk | 0 | ```bash banshee ioc rules ip banshee ioc rules domain -p banshee ioc rules hash -C 3 banshee ioc rules vulnerability -M T1587.004 -C 2 -F concept ``` **Response shape:** Returns a flat JSON array. Each item represents one risk rule: | Field | Description | |-------|-------------| | `.name` | Rule name string — use this value with `--risk-rule` in `ioc search` and `risklist` commands (e.g. `"recentActiveCnc"`) | | `.criticalityLabel` | Human-readable label (e.g. `"Very Malicious"`) | | `.criticality` | Integer criticality level | | `.description` | Rule description string | | `.categories[]` | Array of `{name, framework}` objects — MITRE ATT&CK categories (e.g. `{name: "TA0011", framework: "MITRE"}`) | | `.relatedEntities[]` | Array of RF entity ID strings referenced by this rule | | `.count` | Number of IOCs currently matching this rule | ```bash # List all rule names for an entity type banshee ioc rules ip | jq -r '.[].name' # Find rules above criticality 3 with their descriptions banshee ioc rules ip | jq '[.[] | select(.criticality >= 3) | {name, criticalityLabel, description}]' ``` ## list # list > See [index.md](index.md) for authentication, readiness checks, output conventions, and shared LLM notes. ### `banshee list create NAME [LIST_TYPE]` Create a new list. | Argument/Option | Default | Description | |-----------------|---------|-------------| | `NAME` (required) | | Name of the list | | `LIST_TYPE` | `entity` | One of: `entity`, `source`, `text` | | `--pretty` / `-p` | | Pretty print | ```bash banshee list create coolbeans banshee list create coolsources source -p ``` --- ### `banshee list search [NAME]` Search for lists by name and/or type. | Option | Short | Default | Description | |--------|-------|---------|-------------| | `NAME` (optional) | | | Filter by list name | | `--list-type` | `-t` | | One of: `entity`, `source`, `text`, `custom`, `ip`, `domain`, `tech_stack`, `industry`, `brand`, `partner`, `industry_peer`, `location`, `supplier`, `vulnerability`, `company`, `hash`, `operation`, `attacker`, `target`, `method`, `executive` | | `--limit INTEGER` | `-l` | `1000` | Max results (1–3000) | | `--pretty` | `-p` | | Pretty print | ```bash banshee list search -l 1500 -p banshee list search -t vulnerability banshee list search Attacker banshee list search ernest -t entity -p -l 3 ``` **Response shape:** Returns a flat JSON array. Each item has: | Field | Description | |-------|-------------| | `.id` | List ID (e.g. `report:-19oM7`) | | `.name` | List name | | `.type` | List type: `entity`, `source`, `text`, etc. | | `.created` | Creation timestamp (ISO 8601) | | `.updated` | Last updated timestamp (ISO 8601) | | `.owner_id` | Owner uhash ID | | `.owner_name` | Owner display name | | `.owner_organisation_details` | Organisation ownership info | --- ### `banshee list info LIST_ID` Get metadata about a list. ```bash banshee list info 1b0tFN banshee list info 1b0tFN -p ``` **Response shape:** Returns a single JSON object — same field set as items in `list search`: `id`, `name`, `type`, `created`, `updated`, `owner_id`, `owner_name`, `organisation_id`, `organisation_name`, `owner_organisation_details`. --- ### `banshee list status LIST_ID` Get processing/sync status of a list. ```bash banshee list status 1b0tFN ``` **Response shape:** Returns a single JSON object with two fields: | Field | Description | |-------|-------------| | `.status` | Processing status string (e.g. `"ready"`) | | `.size` | Number of entities currently on the list | --- ### `banshee list entities LIST_ID` Retrieve all entities currently on a list. ```bash banshee list entities 1b0s1q ``` **Response shape:** Returns a flat JSON array. Each item has: | Field | Description | |-------|-------------| | `.entity.id` | RF entity ID | | `.entity.name` | Entity display name | | `.entity.type` | Entity type string | | `.status` | Entity status on the list (e.g. `"ready"`) | | `.added` | Timestamp when entity was added (ISO 8601) | ```bash # Extract all entity IDs on a list banshee list entities report:6P8708 | jq -r '.[].entity.id' # Get entity names and types banshee list entities report:6P8708 | jq '[.[] | {name: .entity.name, type: .entity.type}]' ``` --- ### `banshee list entries LIST_ID` Retrieve text match entries on a list (for `text`-type lists). ```bash banshee list entries 1b0s1q ``` --- ### `banshee list add LIST_ID ENTITY_ID [PROPERTIES]` Add a single entity to a list. | Argument | Description | |----------|-------------| | `LIST_ID` (required) | List ID | | `ENTITY_ID` (required) | RF entity ID (e.g. `SoA6SP`) OR `name,type` pair (e.g. `wannacry,Malware`) | | `PROPERTIES` (optional) | Use `annotation=` to attach a note that appears on the Recorded Future platform for this entity. Quote the value if it contains spaces. | ```bash banshee list add 1b0s1q lYNvCK banshee list add 1b0s1q lYNvCK 'annotation=C2 server seen during incident X-1234' ``` --- ### `banshee list bulk-add LIST_ID [ENTITY_INPUT]...` Add multiple entities to a list. Accepts entity IDs, `name,type` pairs, or `type:value` pairs. | Option | Short | Default | Description | |--------|-------|---------|-------------| | `--overwrite` | `-o` | off | Overwrite mode: keep entities present in the supplied input, add new ones, and remove any entities currently on the list that are **not** in the input. Without it, the command only appends new entities and never removes existing ones. | **Input formats:** - RF entity ID: `SoA6SP` - Name + type: `wannacry,Malware` or `www.duckdns.org,InternetDomainName` - Type-prefixed value: `ip:8.8.8.8` ```bash banshee list bulk-add report:21YKUC SoA6SP lYNvCK banshee list bulk-add 21YKUC ip:8.8.8.8 www.duckdns.org,InternetDomainName # Overwrite mode: make the list match exactly the entities supplied (adds missing, removes stale) banshee list bulk-add 21YKUC SoA6SP lYNvCK --overwrite # From file (one entity per line) banshee list bulk-add 21YKUC < entities.txt cat entities.txt | banshee list bulk-add 21YKUC ``` **Response:** Plain text grouped by outcome — `ADDED:`, `REMOVED:` (overwrite only), and `UNCHANGED:` blocks listing the affected entities. Not JSON; do not pipe to `jq`. --- ### `banshee list remove LIST_ID ENTITY_ID` Remove a single entity from a list. ```bash banshee list remove 1b0s1q lYNvCK ``` --- ### `banshee list bulk-remove LIST_ID [ENTITY_INPUT]...` Remove multiple entities from a list. Same input formats as `bulk-add`. ```bash banshee list bulk-remove 21YKUC JLHNoH lYNvCK banshee list bulk-remove 21YKUC ip:8.8.8.8 www.duckdns.org,InternetDomainName # From file banshee list bulk-remove 21YKUC < entities.txt cat entities.txt | banshee list bulk-remove 21YKUC ``` --- ### `banshee list copy SOURCE_LIST_ID DESTINATION_LIST_ID` Copy the entities from one list to another. The source list's entities are read and added to the destination. | Option | Short | Default | Description | |--------|-------|---------|-------------| | `--overwrite` | `-o` | off | Overwrite mode: keep entities present in both lists, add new ones, and remove any entities on the destination that are **not** in the source. Without it, entities are only appended to the destination and nothing is removed. | If the source list is empty the command exits without modifying the destination, even with `--overwrite`. ```bash banshee list copy 1b0s1q 21YKUC # Make the destination mirror the source exactly (adds missing, removes stale) banshee list copy 1b0s1q 21YKUC --overwrite ``` **Response:** Plain text grouped by outcome — `ADDED:`, `REMOVED:` (overwrite only), and `UNCHANGED:` blocks listing the affected entities. Not JSON; do not pipe to `jq`. --- ### `banshee list clear LIST_ID` Remove **all** entities from a list (destructive — use with care). Text-match entries cannot be removed via the API. The list itself is not deleted; only its entities are removed. ```bash banshee list clear 1b0s1q ``` **Response:** Plain text. Prints `No entities to remove` when the list is already empty, `Successfully removed entities` on success, or — if any removals fail — ` entities were not removed from the list:` followed by the still-present entities. Not JSON. ## pba # pba > **Playbook Alerts** - automation-driven alerts. IDs are 36-char UUIDs and the `task:` prefix is optional (e.g. `d144a9ec-90e6-40fe-89b0-d85ed65d3e9c` or `task:d144a9ec-90e6-40fe-89b0-d85ed65d3e9c`). PBA-exclusive categories: `domain_abuse`, `cyber_vulnerability`, `third_party_risk`, `code_repo_leakage`, `identity_novel_exposures`, `geopolitics_facility`, `malware_report`. For legacy rule-based alerts (short opaque IDs), use [`ca`](ca.md) instead. > > See [index.md](index.md) for authentication, readiness checks, output conventions, and shared LLM notes. ### `banshee pba search` Search Playbook Alerts with rich filter options. | Option | Short | Default | Description | |--------|-------|---------|-------------| | `--created TEXT` | `-C` | | Filter by created date (e.g. `1d`, `7d`) | | `--updated TEXT` | `-u` | | Filter by updated date | | `--category` | `-c` | all | One or more categories (repeatable): `domain_abuse`, `cyber_vulnerability`, `third_party_risk`, `code_repo_leakage`, `identity_novel_exposures`, `geopolitics_facility`, `malware_report` | | `--entity TEXT` | `-e` | | Filter by associated entity (repeatable) | | `--priority` | `-P` | all | `Informational`, `Moderate`, `High` (repeatable) | | `--status` | `-s` | all | `New`, `InProgress`, `Dismissed`, `Resolved` (repeatable) | | `--org-id TEXT` | `-o` | all | Filter by owning organisation ID (repeatable). Accepts a 10-char ID or a 16-char `uhash:` form | | `--limit INTEGER` | `-l` | `100` | Max results (1–10000) | | `--pretty` | `-p` | | Pretty print | **Response shape:** Returns a JSON object with three top-level keys: `.data` (array of alert records), `.counts` (`{returned, total}`), and `.status` (request status object: `{status_code, status_message}`). Alert records are under `.data[]` with fields: `playbook_alert_id`, `alert_rule` (`{id, label, name}`), `category`, `priority`, `status`, `title`, `created`, `updated`, `actions_taken`, `owner_organisation_details`. ```bash banshee pba search --created 1d banshee pba search -C 1d -u 1d -p banshee pba search --limit 1000 --category identity_novel_exposures --category domain_abuse banshee pba search --updated 7d --category domain_abuse --pretty banshee pba search -c identity_novel_exposures -c third_party_risk -P High -P Moderate -s New banshee pba search -e idn:recordedfuture.com -e idn:example.com -c domain_abuse -u 7d banshee pba search -o 69sKLfTGsS -o uhash:5zQaSyRpA1 -C 7d -P High ``` --- ### `banshee pba lookup ALERT_ID` Retrieve a single Playbook Alert by ID. Accepts a 36-char UUID with or without the `task:` prefix — the CLI auto-prepends `task:` to bare UUIDs. ```bash banshee pba lookup task:d144a9ec-90e6-40fe-89b0-d85ed65d3e9c banshee pba lookup d144a9ec-90e6-40fe-89b0-d85ed65d3e9c banshee pba lookup task:d144a9ec-90e6-40fe-89b0-d85ed65d3e9c -p ``` **Response shape:** Returns a single JSON object with four top-level keys: `playbook_alert_id`, `panel_status`, `panel_evidence_summary`, `panel_log_v2`. **`.panel_status`** — alert metadata and current disposition: | Field | Description | |-------|-------------| | `.panel_status.status` | Current status: `New`, `InProgress`, `Dismissed`, `Resolved` | | `.panel_status.priority` | Priority: `Informational`, `Moderate`, `High` | | `.panel_status.case_rule_label` | Human-readable rule name (e.g. `"Data Leakage on Code Repository"`) | | `.panel_status.entity_id` | RF entity ID of the primary subject (e.g. `"url:https://..."`) | | `.panel_status.entity_name` | Primary entity name | | `.panel_status.risk_score` | RF risk score integer | | `.panel_status.targets[]` | Array of `{name}` objects — entities targeted or affected | | `.panel_status.actions_taken[]` | Actions already recorded on the alert | | `.panel_status.created` | Creation timestamp (ISO 8601) | | `.panel_status.updated` | Last updated timestamp (ISO 8601) | **`.panel_evidence_summary`** — evidence detail; structure varies by alert category. For `code_repo_leakage`: | Field | Description | |-------|-------------| | `.panel_evidence_summary.repository.name` | Repository URL | | `.panel_evidence_summary.repository.owner.name` | Repository owner login | | `.panel_evidence_summary.evidence[]` | Array of evidence items | | `.panel_evidence_summary.evidence[].url` | Source URL of the exposed content | | `.panel_evidence_summary.evidence[].content` | Snippet of the exposed content | | `.panel_evidence_summary.evidence[].assessments[]` | Assessment objects: `{id, title, value}` | | `.panel_evidence_summary.evidence[].targets[]` | Target entities: `{name}` | | `.panel_evidence_summary.evidence[].published` | Publication timestamp | ```bash # Summary: entity, rule, status banshee pba lookup task: | jq '{entity: .panel_status.entity_name, rule: .panel_status.case_rule_label, status: .panel_status.status, priority: .panel_status.priority}' # Extract evidence URLs (code_repo_leakage) banshee pba lookup task: | jq '[.panel_evidence_summary.evidence[].url]' ``` --- ### `banshee pba update [ALERT_IDS]...` Update one or more Playbook Alerts. IDs accept `task:` prefix or bare UUID. Can be piped. | Option | Short | Description | |--------|-------|-------------| | `--status` | `-s` | New status: `New`, `InProgress`, `Dismissed`, `Resolved` | | `--reopen` | `-r` | Reopen strategy (for Dismissed/Resolved only): `Never`, `SignificantUpdates` | | `--priority` | `-p` | New priority: `Informational`, `Moderate`, `High` | | `--comment TEXT` | `-t` | Add a comment | | `--assignee TEXT` | `-a` | Reassign (accepts `uhash:3aXZxdkM12`) | **Valid status/reopen combinations:** `Dismissed → Never`, `Resolved → Never`, `Resolved → SignificantUpdates` ```bash # Single update banshee pba update task:c5dd878b-e5e2-4a19-ad28-a5b770a0aa64 -s Resolved # Multiple IDs banshee pba update c5dd878b-e5e2-4a19-ad28-a5b770a0aa64 a0ce3533-7438-4a6a-9cfd-9eb150fc540c -s Resolved # Pipe from search banshee pba search -c domain_abuse -P Informational | jq -r '.data[].playbook_alert_id' | banshee pba update -s Resolved # From file banshee pba update -s Dismissed < alerts.txt cat alerts.txt | banshee pba update -s Dismissed # Full example banshee pba update 26ca663b-a1d8-4dbd-85ef-4bd3cecaa935 c5dd878b-e5e2-4a19-ad28-a5b770a0aa64 -s InProgress -p Informational -t "Bumping priority down due to recent findings." ``` **Response:** Returns plain text, not JSON — one line per updated alert: `SUCCESS:\n`. Do not pipe to `jq`. --- ### `banshee pba export` Fetch full alert details for the alerts produced by `pba search` and emit them as JSON or CSV. Input is **stdin only** — pipe the JSON object from `banshee pba search`; there are no positional arguments. | Option | Short | Default | Description | |--------|-------|---------|-------------| | `--csv` | | JSON | Output as CSV (fixed column set) instead of JSON (full alert details). | ```bash banshee pba search --created 1d -l 10 | banshee pba export > alerts.json banshee pba search --updated 7d --category identity_novel_exposures | banshee pba export --csv > identity_alerts.csv ``` **Input:** Expects the JSON object emitted by `banshee pba search` on stdin — the export reads `.data[]` and requires `playbook_alert_id` and `category` on each record (these drive the category-specific fetch). Running with no piped input (a TTY) raises a `BadParameter` error. **Response shape (default):** A JSON array of full Playbook Alert objects — the same per-alert structure returned by `banshee pba lookup` (`playbook_alert_id`, `panel_status`, `panel_evidence_summary`, `panel_log_v2`). **Response shape (`--csv`):** CSV with a header row and these fixed columns: `ID`, `Priority`, `Alert Rule`, `Status`, `Created`, `Updated`, `Subject`, `Assignee`, `Assessments`, `Entities`, `Reopen Strategy`, `Onwards Actions`. `Assessments` and `Entities` are `; `-joined; commas inside field values are replaced with spaces. ## pcap # pcap > See [index.md](index.md) for authentication, readiness checks, output conventions, and shared LLM notes. > **Prerequisite:** `tshark` must be installed and in `PATH`. In Banshee 1.2.0, `banshee pcap enrich --help` also fails if `tshark` is missing, so verify with `command -v tshark` first. ### `banshee pcap enrich FILE_PATH` Parse a pcap file, extract IPs and domains, enrich with RF threat intelligence. By default, only shows indicators above the risk score threshold (65). | Option | Short | Default | Description | |--------|-------|---------|-------------| | `--risk-score INTEGER` | `-r` | `65` | Show only indicators above this score (1–99) | | `--threat-hunt` | `-t` | `false` | Also include indicators linked to threat actors even if below the score threshold (retrospective threat hunting) | | `--pretty` | `-p` | | Pretty print | Default JSON output is a flat array of records with fields such as `ioc`, `risk_score`, `most_malicious_rule`, `rule_evidence`, `ta_names`, `malwares`, and `wireshark_query`. ```bash banshee pcap enrich sandbox.pcap banshee pcap enrich honeypot-traffic.pcap -r 25 -t -p # Summarize hits from JSON output banshee pcap enrich sandbox.pcap -r 25 -t | jq '[.[] | {indicator: .ioc, score: .risk_score, top_rule: .most_malicious_rule, evidence_rules: [(.rule_evidence // [])[].rule]}] | sort_by(-.score)' ``` ## risklist # risklist > See [index.md](index.md) for authentication, readiness checks, output conventions, and shared LLM notes. ### `banshee risklist fetch` Download a risk list from RF or load a local custom file. | Option | Short | Description | |--------|-------|-------------| | `--entity-type` | `-e` | Entity type: `ip`, `domain`, `url`, `hash`, `vulnerability` | | `--list-name TEXT` | `-l` | `default`, `large`, or any rule name from `banshee ioc rules` | | `--custom-list-path TEXT` | `-c` | Path to a local risk list file | | `--output-path TEXT` | `-o` | Output path (defaults to CWD with auto-generated name) | | `--as-json` | `-j` | Convert downloaded list to JSON (only with `--list-name` + `--entity-type`) | ```bash banshee risklist fetch -e domain -l default banshee risklist fetch -c /custom/path/to/list.csv banshee risklist fetch -e ip -l recentValidatedCnc -o ./custom_name.csv ``` --- ### `banshee risklist create` Build a custom merged risk list from one or more risk rules, with optional score filtering. Can write locally or upload to RF Fusion. | Option | Short | Default | Description | |--------|-------|---------|-------------| | `--entity-type` | `-e` | | Entity type: `ip`, `domain`, `url`, `hash`, `vulnerability` | | `--risk-rule TEXT` | `-R` | | Risk rule to include (repeatable): `default`, `large`, or any rule name from `banshee ioc rules` | | `--risk-score INTEGER` | `-r` | | Minimum risk score threshold (5–99) | | `--format` | `-f` | `csv` | Output format: `csv`, `edl`, `json` | | `--output-path TEXT` | `-o` | CWD | Output file path | | `--fusion` | `-F` | | Upload to RF Fusion (use with `--output-path` as Fusion destination path) | **Output formats:** - `csv` — Comma-separated with headers: `Name, Risk, RiskString, EvidenceDetails` - `edl` — Plain list of IOC values, one per line (for firewall/EDL feeds) - `json` — Full JSON array of risk list entries ```bash banshee risklist create -e ip -R default -r 70 -o ip_risklist_70.csv banshee risklist create -e domain -R analystNote -R recentPhishing -r 80 banshee risklist create -e ip -R recentActiveCnc -R recentValidatedCnc -f edl banshee risklist create -e hash -R default -f json -o /tmp/hash_risklist.json banshee risklist create -e ip -R recentValidatedCnc -F -o /home/risklists/ip_cnc_risklist.csv ``` --- ### `banshee risklist stat` Show metadata for a risk list — whether it exists in Fusion and its current etag. | Option | Short | Description | |--------|-------|-------------| | `--entity-type` | `-e` | Entity type | | `--list-name TEXT` | `-l` | List name | | `--custom-list-path TEXT` | `-c` | Path to local risk list file | | `--pretty` | `-p` | Pretty print | | `--count` | `-C` | Show IOC counts and risk score distribution across the risk list | ```bash banshee risklist stat -e ip -l recentValidatedCnc banshee risklist stat -e domain -l domain_risklist banshee risklist stat -e ip -l default --count ``` **Response shape:** Returns a single JSON object: | Field | Description | |-------|-------------| | `.name` | Risk list name as stored in Fusion (e.g. `"recentValidatedCnc_ip_risklist"`) | | `.exists` | `true`/`false` — whether the list exists in RF Fusion | | `.etag` | Etag hash string for cache validation | | `.counts` | *(only with `--count`)* Object mapping each risk score to its IOC count, e.g. `{"28": 261110, "65": 6531}` | **Live-test note:** During 2026-05-01 testing, `--custom-list-path /tmp/banshee_smoke_risklist.json` attempted a Fusion API lookup and returned `400 Bad Request`; prefer `-e`/`-l` unless validating a known Fusion-backed custom path. ## rules # rules > See [index.md](index.md) for authentication, readiness checks, output conventions, and shared LLM notes. ### `banshee rules search` Search and download Sigma, YARA, and Snort detection rules from Recorded Future. | Option | Short | Default | Description | |--------|-------|---------|-------------| | `--type` | `-t` | | Rule type (repeatable, OR logic): `sigma`, `yara`, `snort` | | `--threat-actor-map` | `-T` | | Filter by actors in your Threat Actor Map | | `--threat-actor-category` | `-C` | | Filter by threat actor category (repeatable, OR logic). Categories include nation-state groups, ransomware groups, hacktivists, financially motivated actors, and more. | | `--threat-malware-map` | `-M` | | Filter by malware in your Malware Threat Map | | `--org-id TEXT` | `-O` | | Organization ID for MSSP/multi-org accounts (for use with threat maps) | | `--entity TEXT` | `-e` | | Filter by RF entity ID (repeatable, OR logic). Use `banshee entity search` to find IDs. MITRE codes accepted (e.g. `mitre:T1486`). | | `--created-after TEXT` | `-a` | | Relative (`1d`, `7d`) or absolute (`2024-01-01`) | | `--created-before TEXT` | `-b` | | Relative or absolute date | | `--updated-after TEXT` | `-u` | | Relative or absolute date | | `--updated-before TEXT` | `-U` | | Relative or absolute date | | `--id TEXT` | `-i` | | Filter by Insikt Note document ID (e.g. `doc:lmRPGB`) | | `--title TEXT` | `-n` | | Freetext search on associated Insikt Note titles | | `--limit INTEGER` | `-l` | `10` | Max results (1–1000) | | `--output-path TEXT` | `-o` | | Save rules to directory (omit to print to console) | | `--pretty` | `-p` | | Pretty print | ```bash banshee rules search -t yara -t snort -l 20 -a 3d banshee rules search -t sigma --entity mitre:T1486 --entity kK5UbE banshee rules search --id doc:0uTafk banshee rules search --title Ransomware -p banshee rules search -t yara --output-path . banshee rules search --threat-actor-map -o fetched_rules ``` **Response shape:** Returns a flat JSON array (when not using `--output-path`). Each item represents an Insikt Note with associated detection rules: | Field | Description | |-------|-------------| | `.id` | Insikt Note document ID (e.g. `doc:o6_lui`) | | `.type` | Rule type: `sigma`, `yara`, or `snort` | | `.title` | Insikt Note title | | `.description` | Full Insikt Note description text | | `.created` | Note creation timestamp (ISO 8601) | | `.updated` | Note last updated timestamp (ISO 8601) | | `.rules[]` | Array of rule objects — one note may have multiple rules | `.rules[]` item fields: | Field | Description | |-------|-------------| | `.content` | Raw rule text (YAML for Sigma, plain text for YARA/Snort) | | `.file_name` | Suggested filename for saving the rule | | `.entities[]` | Entities referenced by the rule: `{id, name, type}` (may include `display_name`) | ```bash # List all sigma rule titles and filenames from the last 7 days banshee rules search -t sigma -l 50 -a 7d | jq '[.[] | {title, file: .rules[0].file_name}]' # Extract all MITRE ATT&CK IDs referenced by rules banshee rules search -t sigma -l 20 | jq '[.[].rules[].entities[] | select(.type == "MitreAttackIdentifier") | .name] | unique' # Print raw Sigma rule content banshee rules search --id doc:0uTafk | jq -r '.[0].rules[0].content' ``` # Optional ## Installation # Installing PS Banshee ## Installation methods Install [ps-banshee](https://pypi.org/project/ps-banshee/) with `pipx` or `pip`. ## Installation !!! tip "PS Banshee requires Python 3.10 or later (up to 3.13)." ### Recommended: pipx (isolated environment) To install globally, run: ```bash pipx install ps-banshee ``` !!! info "Installing pipx" If you don't have pipx installed, see the [installation guide](https://github.com/pypa/pipx?tab=readme-ov-file#install-pipx). ### Alternative: pip (current environment) To install in the current environment, run: ```bash pip install ps-banshee ``` ### Dependencies All required Python dependencies are resolved automatically by `pip`. To use the `pcap` command, ensure you have: - tshark 3.0.0 or later ## Authorization PS Banshee reads your Recorded Future API key from the `RF_TOKEN` environment variable (recommended) or from the `-k` / `--api-key` flag on each command. ### Option 1: Set `RF_TOKEN` (recommended) === "macOS / Linux" Current shell only: ```bash export RF_TOKEN= ``` Persist for future shells (zsh — adjust to `~/.bashrc` for bash). Open a new shell after running this (or run `source ~/.zshrc` to apply in the current shell): ```bash echo 'export RF_TOKEN=' >> ~/.zshrc ``` === "Windows (PowerShell)" Current session only: ```powershell $env:RF_TOKEN = '' ``` Persist for future sessions (open a new PowerShell after running this): ```powershell setx RF_TOKEN ``` === "Windows (Command Prompt)" Current session only: ```cmd set RF_TOKEN= ``` Persist for future sessions (open a new Command Prompt after running this): ```cmd setx RF_TOKEN ``` ### Option 2: Pass with `-k` per command ```bash banshee -k ``` This works on any platform, but is more verbose and the key may land in shell history. ## Upgrading PS Banshee To upgrade PS Banshee to a newer version, reinstall using the updated wheel file. !!! warning "Upgrading from v1.0.0 or earlier" If you are upgrading from v1.0.0 or an earlier version, you must uninstall the existing package first before installing the new version. **If installed with pipx:** ```bash pipx uninstall banshee pipx install ps-banshee ``` **If installed with pip:** ```bash pip uninstall banshee pip install ps-banshee ``` **If installed with pipx:** ```bash pipx install --force ps-banshee ``` **If installed with pip:** ```bash pip install --upgrade ps-banshee ``` ## Shell autocompletion After installing PS Banshee, enable command auto completion with: ```bash banshee --install-completion ``` Restart your shell to complete the installation. You can now use TAB to auto-complete commands. ## Uninstallation To remove PS Banshee from your system, use the appropriate command based on your installation method. **If installed with pipx:** ```bash pipx uninstall ps-banshee ``` **If installed with pip:** ```bash pip uninstall ps-banshee ``` ## Next steps See the [first steps](./first-steps.md) to start using PS Banshee. ## Using with AI agents # Using with AI agents Banshee is designed to be driven from the terminal — including by AI coding agents such as Claude Code, Codex, and any other LLM that can run shell commands. Two artifacts are published to help an agent learn the CLI: - **Index** — concise table of contents for selective fetches: [llms.txt](../../llms.txt) - **Full bundle** — every command group inlined in a single document: [llms-full.txt](../../llms-full.txt) Both follow the [llms.txt](https://llmstxt.org/) convention. ## Make `banshee` discoverable to your agent Copy the snippet below and paste it into whichever rules/instructions file your agent reads — `CLAUDE.md`, `AGENTS.md`, or the equivalent for your tool: ```markdown ## Recorded Future (banshee CLI) When a request involves Recorded Future or threat intelligence, use the `banshee` CLI. This covers, for example: - checking or enriching the risk of an IOC (IP, domain, URL, file hash, or CVE) - looking up or searching for entities - triaging Classic or Playbook alerts - managing RF lists and watchlists - fetching or building risk lists - finding or downloading detection rules (Sigma, YARA, Snort) - enriching an email (`.eml`) or packet capture (`.pcap`) First fetch the full command reference, then run `banshee`: If that URL is unreachable, or a command from the reference isn't present in your installed version, run `banshee --help` (and `banshee --help`) to confirm the commands your binary actually supports. ``` ## Authorization Set the `RF_TOKEN` environment variable in the agent's shell before invoking banshee. The env-var path is strongly preferred for agent workflows — the agent doesn't have to remember to pass `-k` on every call. See [Installation → Authorization](installation.md#authorization) for full setup instructions (macOS, Linux, Windows). ## PS Banshee use cases overview # PS Banshee use cases overview Below are some of the core use cases to get started: - [Alerts Management](alerts/index.md) - [Detection Rules](detection-rules/index.md) - [Email Enrichment](email/index.md) - [Entity Match](entity/index.md) - [IOC Enrichment](enrichment/index.md) - [Packet Capture Analysis](pcap/index.md) - [Risk Lists](risklists/index.md) - [Watchlist Management](watchlist/index.md)