$npx -y skills add transilienceai/communitytools --skill ti-ingestThreat-intel signal ingest — converts a CVE + affected-asset + claim payload into a queued engagement-scope row for the validation pipeline.
| 1 | # Threat-Intel Signal Ingest |
| 2 | |
| 3 | Convert a threat-intel signal into a queued engagement-scope row that the Exploitability Validation Run (cloud-agent task #3) consumes. |
| 4 | |
| 5 | ## Trigger |
| 6 | |
| 7 | Two modes: |
| 8 | - **Prompt-invoked**: an analyst runs the skill against a `signal.json` they have on hand. |
| 9 | - **Scheduled poll**: the cloud-agent runtime polls `{OUTPUT_DIR}/inbox/` on a cron (default every 15 minutes) and processes any new signal files it finds. |
| 10 | |
| 11 | ## Workflow |
| 12 | |
| 13 | 1. **Read the payload** — `tools/ti-ingest.py --in <path-or-stdin>`. |
| 14 | 2. **Validate schema** — required keys: `signal_id`, `cve` (one or more), `assets` (one or more), `claim`. Optional: `confidence`, `source`, `references`. |
| 15 | 3. **Enrich with NVD** — for every CVE in the payload, run `tools/nvd-lookup.py <CVE>` and attach `{score, severity, cwe}` to the row. |
| 16 | 4. **De-dup** — skip rows whose `(asset, cve)` pair already exists in `queue/scope-*.json`. Re-queue only if the prior row's status is `REJECTED` AND the TI signal carries a higher `confidence` than the last attempt. |
| 17 | 5. **Write queue row** — one JSON file per `(asset, cve)` pair at `queue/scope-{ts}-{asset_id}-{cve}.json`. The Validation Run task picks these up. |
| 18 | |
| 19 | ## Output |
| 20 | |
| 21 | ``` |
| 22 | {OUTPUT_DIR}/ |
| 23 | inbox/ |
| 24 | signal-{ts}.json # raw payload, kept for audit |
| 25 | queue/ |
| 26 | scope-{ts}-{asset}-{cve}.json |
| 27 | ``` |
| 28 | |
| 29 | Per scope row: |
| 30 | |
| 31 | ```json |
| 32 | { |
| 33 | "scope_id": "scope-20260513-asset42-CVE-2024-12345", |
| 34 | "signal_id": "ti-2026-0042", |
| 35 | "asset": {"id": "asset42", "url": "https://app.example.com", "tier": "revenue"}, |
| 36 | "cve": "CVE-2024-12345", |
| 37 | "nvd": {"score": 9.8, "severity": "CRITICAL", "cwe": "CWE-79"}, |
| 38 | "claim": "Reflected XSS via search parameter", |
| 39 | "confidence": "high", |
| 40 | "source": "vendor-advisory", |
| 41 | "references": ["https://..."], |
| 42 | "queued_at": "2026-05-13T10:00:00Z", |
| 43 | "status": "queued" |
| 44 | } |
| 45 | ``` |
| 46 | |
| 47 | ## Rules |
| 48 | |
| 49 | 1. **Idempotent.** Re-running on the same payload must not produce duplicate queue rows. |
| 50 | 2. **No execution.** Ingest never runs PoCs. It only queues scope for downstream tasks. |
| 51 | 3. **Audit trail.** Raw payload is always copied to `inbox/` before any transformation. |
| 52 | 4. **NVD failures are non-blocking.** If `nvd-lookup` errors, write the row with `nvd: null` and `nvd_error: "..."`; do not drop the signal. |
| 53 | 5. **Asset must be in inventory.** Cross-check `asset.id` against `artifacts/org-surface.json` (from Org Recon Refresh task). Unknown assets get a row but flagged `unknown_asset: true` so the validator skips them. |
| 54 | |
| 55 | ## References |
| 56 | |
| 57 | - `reference/ingest-schema.md` — full input/output JSON schemas. |