Build with the API / Weekly executive brief
Weekly executive brief
The week's top 10 threat clusters as a Markdown brief.
What you get
Pulls the ten highest-scoring threat clusters of the last 7 days and renders a Markdown brief: rank, title, score and urgency, a one-sentence summary, entity chips (actors, malware, CVEs, platforms...) and a link to each cluster. Saved to brief.md and printed.
- Endpoints
/threats- Credits per run
- 1
- Key
- Works on the free key
The code
weekly-exec-brief.py, 135 lines. Python 3, needs requests.
#!/usr/bin/env python3
"""weekly-exec-brief: the week's top 10 threat clusters as a Markdown brief.
What it does
Pulls the ten highest-scoring threat clusters of the last 7 days and renders a Markdown
brief: rank, title, score and urgency, a one-sentence summary, entity chips (actors,
malware, CVEs, platforms...) and a link to each cluster. Saved to brief.md and printed.
Endpoints
GET /threats?time_filter=7d&sort_by=threat_score&limit=10 (1 credit)
Cost: 1 credit per run. Works on the free tier.
Usage
python3 weekly-exec-brief.py # writes ./brief.md
python3 weekly-exec-brief.py --out /tmp/brief.md
"""
import argparse
from datetime import datetime, timezone
import json
import os
import sys
import time
import requests
API_BASE = os.environ.get("THREATCLUSTER_API_BASE", "https://threatcluster.io/api/public/v1").rstrip("/")
API_KEY = os.environ.get("THREATCLUSTER_API_KEY", "")
SITE = os.environ.get("THREATCLUSTER_SITE", "https://threatcluster.io") # where the linked pages live
PACE_SECONDS = 2.1 # free keys get 30 requests/min; ~28/min keeps loops clear of 429s
_credits = {"used": 0, "remaining": None}
def _auth_headers():
# A tc_... key is sent as X-API-Key; anything else is a short-lived bearer (e.g. from `tc login`).
if not API_KEY:
sys.exit("THREATCLUSTER_API_KEY is not set. Free keys: https://threatcluster.io/about/api")
if API_KEY.startswith("tc_"):
return {"X-API-Key": API_KEY}
return {"Authorization": "Bearer " + API_KEY}
def api_get(path, _allow=(), **params):
"""GET one endpoint. Exits non-zero with the API's own error body, unless the
status is listed in _allow (per-item lookups where a 404 is itself an answer)."""
r = requests.get(API_BASE + path, headers=_auth_headers(), params=params, timeout=60)
if "X-Request-Cost" in r.headers:
_credits["used"] += int(r.headers["X-Request-Cost"])
if "X-RateLimit-Remaining" in r.headers:
_credits["remaining"] = r.headers["X-RateLimit-Remaining"]
if r.status_code >= 400 and r.status_code not in _allow:
try:
body = json.dumps(r.json())
except ValueError:
body = r.text[:500]
sys.exit("HTTP %d from %s: %s" % (r.status_code, path, body))
return r
def cluster_url(cluster):
# The free payload carries `slug` (canonical page) and `cluster_id`; the last 8 hex
# chars of the id also resolve, via a 301 to the slug, when slug is missing.
ident = cluster.get("slug") or cluster.get("short_id") or cluster.get("cluster_id", "").replace("-", "")[-8:]
return "%s/cluster/%s" % (SITE, ident)
def report_credits():
# Stderr, so it never pollutes piped output (brief.md, blocklists, JSON).
remaining = _credits["remaining"] if _credits["remaining"] is not None else "n/a"
sys.stderr.write("[threatcluster] credits used this run: %d, remaining today: %s\n" % (_credits["used"], remaining))
CHIP_TYPES = ("apt_group", "ransomware_group", "malware", "campaign", "cve", "platform", "company", "country")
def first_sentence(text):
text = (text or "").strip().replace("\n", " ")
for stop in (". ", "! ", "? "):
if stop in text:
return text.split(stop, 1)[0] + stop.strip()
return text
def chips(entities, max_chips=6):
# One chip per type first (breadth), then fill the remaining slots.
out = []
ents = entities if isinstance(entities, dict) else {}
for t in CHIP_TYPES:
if ents.get(t):
out.append("`%s: %s`" % (t, ents[t][0]))
for t in CHIP_TYPES:
for v in (ents.get(t) or [])[1:]:
if len(out) >= max_chips:
break
out.append("`%s: %s`" % (t, v))
return " ".join(out[:max_chips])
def main():
ap = argparse.ArgumentParser(description="Top-10 weekly brief in Markdown")
ap.add_argument("--out", default="brief.md", help="where to write the brief")
args = ap.parse_args()
data = api_get("/threats", time_filter="7d", sort_by="threat_score", limit=10).json()
threats = data.get("threats", [])
today = datetime.now(timezone.utc).strftime("%Y-%m-%d")
md = ["# ThreatCluster weekly executive brief: week ending %s" % today, "",
"Top %d threat clusters of the last 7 days, ranked by ThreatCluster threat score." % len(threats), ""]
for i, t in enumerate(threats, 1):
title = t.get("ai_title") or t.get("title") or "(untitled)"
md.append("## %d. %s" % (i, title))
md.append("**Score %.0f** · %s urgency · %s article(s) · latest activity %s"
% (t.get("threat_score") or 0, t.get("urgency_level") or "unknown",
t.get("article_count") or 0, (t.get("date_range_latest") or "")[:10]))
md.append("")
md.append(first_sentence(t.get("ai_summary")))
md.append("")
chip_line = chips(t.get("entities"))
if chip_line:
md.append(chip_line)
md.append("[Read the cluster](%s)" % cluster_url(t))
md.append("")
md.append("---")
md.append("Generated with the ThreatCluster public API (free tier, 7-day window).")
text = "\n".join(md) + "\n"
with open(args.out, "w", encoding="utf-8") as fh:
fh.write(text)
print(text, end="")
sys.stderr.write("[weekly-exec-brief] wrote %s\n" % args.out)
report_credits()
if __name__ == "__main__":
main()
Output
From a run on 3 September 2026. Yours will differ as the corpus moves.
[weekly-exec-brief] wrote /home/james/Desktop/threatcluster/tc-testing/threatcluster-api/examples/recipes/_validation/brief.md [threatcluster] credits used this run: 1, remaining today: 67 # ThreatCluster weekly executive brief: week ending 2026-09-03 Top 10 threat clusters of the last 7 days, ranked by ThreatCluster threat score. ## 1. China-Linked QTFY Group Targets Critical Infrastructure with Advanced Exploits **Score 81** · medium urgency · 5 article(s) · latest activity 2026-09-02 The Joint Cybersecurity Advisory JCSA-20260826-01, released on August 26, 2026, details ongoing activities by the China-linked hacking group QTFY, attributed to Nanjing Xinjiuwei Network Technology Co. `apt_group: Apt41` `ransomware_group: Bl00dy` `malware: PlugX` `campaign: Salt Typhoon` `cve: CVE-2018-13379` `platform: Alibaba Cloud` [Read the cluster](https://threatcluster.io/cluster/china-linked-qtfy-group-targets-critical-infrastructure-with-545ca28d) ## 2. SonicWall SMA1000 Faces Third Zero-Day Exploitation in 2026 **Score 81** · medium urgency · 23 article(s) · latest activity 2026-09-02 SonicWall's SMA1000 VPN appliances are under active exploitation due to two newly discovered zero-day vulnerabilities, CVE-2026-83548 and CVE-2026-83549, which were confirmed on September 1, 2026. `ransomware_group: INC` `malware: Knuckleball` `cve: CVE-2024-1708` `platform: CouchDB` `company: Sonicwall` `country: Australia` [Read the cluster](https://threatcluster.io/cluster/sonicwall-sma1000-zero-day-vulnerabilities-under-active-expl-72cbcfdd) ## 3. Chinese Operator Breaches Philippine Nuclear and Naval Entities **Score 81** · medium urgency · 5 article(s) · latest activity 2026-08-31 A suspected Chinese-speaking operator has compromised a Philippine nuclear research body and a marine engineering company supporting the Philippine Navy by exploiting known vulnerabilities. `malware: Mettle` `campaign: Operation CameraSwarm` `cve: CVE-2023-49105` `platform: LiteSpeed Cache` `company: CGI Global Limited` `country: Philippines` [Read the cluster](https://threatcluster.io/cluster/chinese-speaking-actor-breaches-philippine-nuclear-and-naval-93fb80f8) ## 4. Critical Exploitation of Sangoma Switchvox Vulnerabilities Underway **Score 79** · medium urgency · 7 article(s) · latest activity 2026-09-02 Sangoma Switchvox SMB Edition 8.3 is facing active exploitation of multiple vulnerabilities, particularly CVE-2026-9586, which allows unauthenticated SQL injection leading to remote code execution. `cve: CVE-2026-9585` `platform: Apache` `company: Sangoma` `country: United States` `cve: CVE-2026-9586` `cve: CVE-2026-9587` [Read the cluster](https://threatcluster.io/cluster/critical-vulnerabilities-in-sangoma-switchvox-exploited-for--884616e9) ## 5. Mirage Kitten Targets Aviation and FinTech with New Cross-Platform Malware …
Run it
- Get a free key at /api. Every account has one; it covers the endpoints above.
export THREATCLUSTER_API_KEY=… your key.python3 weekly-exec-brief.py
The file on GitHub: weekly-exec-brief.py.
Goes well with
- Trending threat actors: Which threat actors, ransomware crews and malware families are rising this week?
- A lookup tool for LLM agents: A tool-calling function `threatcluster_lookup(query)` for LLM agents.
- Brand and domain dark-web monitor: Are my brands or domains showing up on the dark web?
- Bash integration: curl and jq in shell scripts and cron
All recipes: /build. Endpoint reference: /api/public/v1/docs.