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

  1. Get a free key at /api. Every account has one; it covers the endpoints above.
  2. export THREATCLUSTER_API_KEY=… your key.
  3. python3 weekly-exec-brief.py

The file on GitHub: weekly-exec-brief.py.

Goes well with

All recipes: /build. Endpoint reference: /api/public/v1/docs.