惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

S
Schneier on Security
F
Fortinet All Blogs
博客园_首页
The GitHub Blog
The GitHub Blog
V
Visual Studio Blog
D
DataBreaches.Net
aimingoo的专栏
aimingoo的专栏
爱范儿
爱范儿
B
Blog
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
N
Netflix TechBlog - Medium
阮一峰的网络日志
阮一峰的网络日志
P
Proofpoint News Feed
D
Docker
Engineering at Meta
Engineering at Meta
大猫的无限游戏
大猫的无限游戏
The Cloudflare Blog
罗磊的独立博客
云风的 BLOG
云风的 BLOG
Microsoft Azure Blog
Microsoft Azure Blog
T
The Exploit Database - CXSecurity.com
博客园 - 三生石上(FineUI控件)
量子位
The Last Watchdog
The Last Watchdog
MyScale Blog
MyScale Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
T
The Blog of Author Tim Ferriss
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
小众软件
小众软件
Cloudbric
Cloudbric
博客园 - 司徒正美
H
Help Net Security
人人都是产品经理
人人都是产品经理
Application and Cybersecurity Blog
Application and Cybersecurity Blog
L
LangChain Blog
Latest news
Latest news
M
MIT News - Artificial intelligence
T
Threat Research - Cisco Blogs
博客园 - Franky
S
Security Affairs
W
WeLiveSecurity
F
Full Disclosure
Know Your Adversary
Know Your Adversary
Google DeepMind News
Google DeepMind News
The Hacker News
The Hacker News
Cyberwarzone
Cyberwarzone
美团技术团队
PCI Perspectives
PCI Perspectives
C
Check Point Blog
Spread Privacy
Spread Privacy

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant Common SOC 2 Failures (Real World) Stop Vibe-Checking Your AI App: A Practical Guide to Evals How to Use SonarQube and SonarScanner Locally to Level Up Your Code Quality Your Next To-Do App Is Dead — I Replaced Mine with an OpenClaw AI Sign a Nostr event in 60 lines of Python using coincurve — no nostr-sdk, no nbxplorer, no rust toolchain ITGC Audit Explained Like You’re in Big 4 Patch Tuesday abril 2026: Microsoft parcha 163 vulnerabilidades y un zero-day en SharePoint Stop scraping everything: a better way to track competitor price changes Listing on MCPize + the Official MCP Registry while routing payments OUTSIDE the marketplace — how I kept 100% of my x402 revenue Building an AI-Powered Risk Intelligence System Using Serverless Architecture Why We Ripped Function Overloading Out of Our AI Toolchain Testing AI-Generated Code: How to Actually Know If It Works SaaS Churn Is Killing Your Business. Here Is What to Do About It (Without a Support Team) The Speed of AI Is No Longer Linear - And Self-Improving Models Are Why How to Implement RBAC for MCP Tools: A Practical Guide for Engineering Teams From Standard Quote to Persuasive Proposal: AI Automation for Arborists I built a CLI that scaffolds complete multi-tenant SaaS apps Axios CVE-2025–62718: The Silent SSRF Bug That Could Be Hiding in Your Node.js App Right Now The dashboard that ended our friendship Data Pipelines Explained Simply (and How to Build Them with Python) The Hidden Cost of AI Systems Nobody Talks About. undefined vs undeclared, and how typeof behaves Switching from file-based jobs to NATS/Kafka in Rust without changing code io_uring Adventures: Rust Servers That Love Syscalls Why Agentic AI is Killing the Traditional Database The POUR principles of web accessibility for developers and designers Quantum Neural Network 3D — A Deep Dive into Interactive WebGL Visualization How To Install Caveman In Codex On macOS And Windows Automation Pipeline Reliability: Why Your Workflow Breaks When Nobody Is Watching I Built an 'Open World' AI Coding Agent — It Works From ANY Folder From Freelancing to Product: A Tech Service Company's SaaS Transformation China's AI Giants: Adding Tencent Hunyuan & ByteDance Doubao to AI University (74 Providers) On the Vibe Coders and Their Lies clerk: Auto-Summarize Your Claude Code Sessions AI Weekly — 2026/04/10–04/17 | The Model Lockdown Is Here, but the Toolchain Is the Real Battleground AI 週報 — 2026/04/10–2026/04/17 模型封鎖潮來了,但工具鏈才是真戰場 Maybe this is how Open-Source apps are born... 🚀 Fine-Tune LLMs with LoRA and QLoRA: 2026 Guide tRPC v11 + Next.js App Router: End-to-End Type Safety Without the Boilerplate ShadCN UI in 2026: Why I Stopped Installing Component Libraries and Started Owning My Components SaaS Billing in React Server Components: Stripe + Supabase Without a Single `useEffect` Join our DEV Weekend Challenge — $1,000 in Prizes Across TEN winners! Submissions Due April 20 at 6:59 AM UTC. Implementing FSRS Spaced Repetition in Flutter + Supabase — Adding Memory Science to an AI Learning App "I Texted My Localhost From the Train — Claude Code Fixed the Bug Before I Got Home" I Built a Sales Prep AI and It Went Deeper Than Expected Design to Code #2: One JSON, Eleven Outputs Solving the 100M-Row Problem: A Summary Table Pattern for High-Volume Push Notification Logs Flutter Web With Wasm: What Actually Changes For Developers I Built 50 Royalty-Free Soundtracks for My Side Project in a Weekend Using AI Music Generation The Vibe Coding Security Checklist: 7 Things to Check Before You Ship Stop Letting Googlebot Guess Fix Your React App's SEO Right Desconstruindo o Streaming do LinkedIn: Como Criar um Engine de Extração de Vídeo de Alta Performance com HLS e FFmpeg (EDA Part-1) EDA (Exploratory Data Analysis) Explained With Real Life — Why Looking at Your Data Is the Most Important Step in Machine Learning Brand Relationship Management at Scale: Our 4-Touch Outreach System for 200+ Brands Why String.fromEnvironment() Might Return an Empty String in Dart JGuardrails 1.0.0 — Hardening Java LLM Apps Against Jailbreaks, Toxicity, and Prompt Injection Plan and Schedule a Full Week of Threads Content From One Claude Conversation Coding Cat Oran Ep3, Five Tables Changed Everything Updated: BFF Pattern I'm done watching freelancers get buried by 200 proposals. So I'm building the alternative. This is my first post BFS Algorithm in Java Step by Step Tutorial with Examples Tracking LLM Pricing Monthly: An Open Dataset for 22 AI Models How We Measure Content ROI on a Comparison Site: Revenue Attribution Without Perfect Data Introducing Nova AI Ops: The AI-Native Operating System for SRE Teams I built a free desktop video downloader for Windows — Grabbit How Talkie OCR Helps Vision-Impaired & Dyslexic Users Read the World Around Them VRCFaceTracking安装和iPhone面捕配置教程,有bug Even CrowdStrike Can't See Your Agents The Automation Gold Rush: What n8n Workflows and Claude Are Opening Up for Developers Right Now
Sector-aware threat intel API: stop triaging hundreds of CVEs manually
Setounkpe7 · 2026-05-18 · via DEV Community

A Monday morning in a SOC

A SOC (Security Operations Center) is the team that watches for cyberattacks against a company. They sit between the firewall and the incident report, and one of their daily jobs is to read the day's new software vulnerabilities and decide which ones the company has to patch first.

A vulnerability is published as a CVE (Common Vulnerabilities and Exposures), a kind of barcode the industry uses to refer to a single bug. "CVE-2025-12345" means one specific flaw, in one specific piece of software, at one specific moment in time.

Now picture a typical morning. Three public feeds land in the analyst's inbox:

  • NVD (National Vulnerability Database, run by the US government). The official catalogue. Around 150 new CVEs a day. Every flaw eventually shows up here, dangerous or not.
  • CISA KEV (Known Exploited Vulnerabilities). A shortlist of CVEs that attackers are already using in real attacks. Maintained by CISA, the US cybersecurity agency. Smaller, scarier.
  • GHSA (GitHub Security Advisories). Same idea, but for open-source code. A vulnerability in a Python library or a Node package shows up here.

None of these feeds is wrong. None is targeted either. A bank's SOC and a hospital's IT team subscribe to the same firehose, and a junior analyst spends the first two hours of every shift reading titles and asking the only question that really matters: "is this us?".

Is the bug in software we run? Does it touch a system we care about? Could an attacker use it against our customers? Most of the 150 daily CVEs are noise for any given company. A Minecraft mod RCE is irrelevant to a bank. A SCADA bug in a German PLC is irrelevant to a SaaS startup. But to find the five that matter, the analyst has to skim the headlines of the hundred-plus that don't.

That re-triage happens in every SOC, every morning, against the same feeds, with the rules living in someone's head instead of being written down anywhere. Different person on call, different answers. Different week, different priorities. No memory.

That triage step is the one I wanted to push down into an API.

The solution

threat-intel-api is an open-source (MIT) vulnerability intelligence service. It pulls in NVD, CISA KEV and GHSA, removes the duplicates between them, and scores every CVE against a YAML file you write that describes what your sector and your stack actually care about.

Six starter profiles ship in the box: finance, healthcare, ICS (industrial control systems, the software that runs factories and power grids), government, SaaS and e-commerce. Each profile is a list of keywords, technologies, CWE categories (a CWE is a type of bug, like SQL injection or hardcoded credentials) and weights you can tune.

Every score ships with the per-criterion breakdown that produced it. Paste it into a ticket and the analyst sees exactly why CVE-X scored 78 and CVE-Y scored 35. No hidden model, no opaque weight, no "trust the vendor".

The rest of this post is how to plug it into your stack.

What it does in 30 seconds

The live API runs at threat-intel-api-production.up.railway.app. No auth on the public endpoints, no key required. Three calls cover the demo:

Top 5 finance-relevant threats, last 24h

curl -s 'https://threat-intel-api-production.up.railway.app/api/v1/sectors/finance/dashboard' \
  | jq '.top_24h[:5] | .[] | {cve: .external_id, score, cvss: .cvss_score, title: .title[0:80]}'

Enter fullscreen mode Exit fullscreen mode

{
  "cve": "CVE-2026-7579",
  "score": 35.0,
  "cvss": 7.3,
  "title": "Hard-coded credentials in AstrBot dashboard auth (CWE-798)"
}

Enter fullscreen mode Exit fullscreen mode

Subscribe a SIEM to the finance RSS feed

curl 'https://threat-intel-api-production.up.railway.app/api/v1/sectors/finance/feed.rss?min_score=70'

Enter fullscreen mode Exit fullscreen mode

Inspect the score breakdown of a single CVE

curl -s 'https://threat-intel-api-production.up.railway.app/api/v1/sectors/finance/dashboard' \
  | jq '.top_24h[0].score_breakdown'

Enter fullscreen mode Exit fullscreen mode

{
  "cwe_match":        { "hit": true,  "matched": ["CWE-798"], "points": 20 },
  "cvss_threshold":   { "hit": true,  "threshold": 7.0,       "points": 15 },
  "kev":              { "hit": false, "points": 0 },
  "technology_match": { "hit": false, "matched": [], "points": 0 }
}

Enter fullscreen mode Exit fullscreen mode

That CVE scored 35 for finance: +20 for the CWE-798 match (hardcoded credentials matter in banking), +15 because CVSS 7.3 clears the 7.0 threshold. Not a wake-up call, but it lands in the 7-day digest with a reason attached.

Swap finance for healthcare, ics, gov, saas, or ecommerce and you get a sector-weighted view of the same underlying CVE corpus.

Why a SOC team should care

This isn't a replacement for Recorded Future or Mandiant. It's the free, self-hosted thing you put next to them.

  • Sector-relevant by default. The Minecraft-mod RCEs that NVD publishes ten times a week don't surface in your finance feed. The excluded_keywords rule kills them at score time.
  • Auditable scoring. No tuned ML model, no opaque weights. Eleven additive rules, a flat function, the breakdown stored in Postgres next to the score. When the SOC lead asks why CVE-X is a 78 and CVE-Y is a 62, you can answer.
  • SIEM-ready out of the box. Every sector exposes a JSON dashboard and an RSS feed with a min_score filter. Splunk, Sentinel and Elastic all consume RSS natively.
  • Hot-reloadable profiles. Your team adds the keywords that match your stack without touching code or restarting the service.
  • No vendor lock-in. MIT, Docker, Postgres, one docker compose up.

Plug it into your stack in 5 minutes

SIEM via RSS

In Splunk, Sentinel, or Elastic: add an RSS input pointing at the feed. Done.

# Splunk-style: poll finance threats scoring >= 70
curl 'https://threat-intel-api-production.up.railway.app/api/v1/sectors/finance/feed.rss?min_score=70'

Enter fullscreen mode Exit fullscreen mode

Tune min_score per sector. KEV-flagged threats get +25 automatically, so 70+ is usually the "actively-exploited or stack-relevant" band.

SOAR via JSON polling

A ~10-line Python poller for any SOAR runbook (Cortex XSOAR, Tines, Shuffle, n8n):

import httpx, time

SEEN = set()
URL = "https://threat-intel-api-production.up.railway.app/api/v1/sectors/finance/dashboard"

while True:
    data = httpx.get(URL, timeout=10).json()
    for t in data["top_24h"]:
        if t["score"] >= 75 and t["external_id"] not in SEEN:
            SEEN.add(t["external_id"])
            # hand off to your SOAR: create incident, enrich, notify
            print(f"NEW {t['external_id']} score={t['score']} cvss={t['cvss_score']}")
            print("  reasons:", [k for k, v in t["score_breakdown"].items() if v.get("hit")])
    time.sleep(900)  # 15 minutes — collectors run hourly

Enter fullscreen mode Exit fullscreen mode

The breakdown gives the SOAR playbook a structured "why" field to include in the auto-created ticket.

Slack / Teams alert

Same poll, different sink:

import httpx
THREATS = httpx.get(".../sectors/ics/dashboard").json()["top_24h"]
for t in THREATS:
    if t["score"] >= 80:
        httpx.post(SLACK_WEBHOOK, json={
            "text": f":rotating_light: *{t['external_id']}* (score {t['score']}) — {t['title']}"
        })

Enter fullscreen mode Exit fullscreen mode

Webhook alerting from the API itself is on the roadmap as M4, so you won't need the poller forever.

Add your sector profile

This is the part that earns the project its keep. Sector knowledge belongs to the people in the sector — not to me. A payments analyst can ship a better finance profile than I ever will.

Profiles are YAML. Here's the real profiles/public/finance.yaml:

id: finance
name: Finance & Banking
keywords: [banking, payment, swift, sepa, ach, card, pos, atm]
technologies: [Java, Spring, Tomcat, WebSphere, Oracle Database, Apache Struts]
cwe_priorities: [CWE-89, CWE-79, CWE-352, CWE-287, CWE-798, CWE-22]
cvss_threshold: 7.0
priority_boost_keywords: [wire transfer, swift network, card skimming]
excluded_keywords: [minecraft, game, mod]

Enter fullscreen mode Exit fullscreen mode

Want iso20022 weighted as a priority boost? Want mitre-att&ck-t1486 in the keyword set? Edit one file, then:

curl -X POST http://localhost:8000/api/v1/admin/reload-profiles \
     -H "X-Admin-Key: $ADMIN_API_KEY"

Enter fullscreen mode Exit fullscreen mode

No restart. No migration. The reload response lists profiles added, updated, removed, and any parse errors with file paths. Private profiles live in profiles/private/ and require the admin header to read — useful if your internal product list is sensitive.

Full schema reference: profiles/README.md.

The scoring algorithm in one table

Eleven rules. Additive. Clamped to [0, 100]. Whole-word, case-insensitive matching, so java doesn't match javascript.

Rule Condition Points
Technology match profile technology appears in corpus +30
Keyword match profile keyword appears in corpus +25
CWE match threat CWE listed in cwe_priorities +20
CVSS threshold cvss_score >= cvss_threshold +15
Priority boost profile priority_boost_keyword appears +20
Excluded profile excluded_keyword appears -30
KEV tag threat tagged kev +25
Actively exploited threat tagged actively-exploited +15
Ransomware threat tagged ransomware +15
Multi-source documented by 3+ sources (or +5 for 2) +10
Package match package indicator matches a technology +20

Every score the API returns ships with the per-criterion breakdown that produced it. Drop it straight into a ticket and the analyst can defend the priority to the SOC lead without re-running anything.

Architecture, briefly

Three collectors → one dedup'd Threat table → a flat scoring function → JSON + RSS.

threat-intel-api architecture: NVD, CISA KEV and GHSA collectors feed a deduplicated PostgreSQL store; the SectorScoringService combines that store with YAML profiles to produce per-sector scores, exposed through the FastAPI v1 layer to SIEM, SOAR and analyst consumers.

One Threat row per CVE ID, one ThreatSource row per (CVE, source) pair. NVD wins on CVSS at read time, KEV wins on the actively-exploited and ransomware tags, GHSA wins on package indicators. Provenance stays attached. You can always check what NVD said vs what KEV said about the same CVE.

Stack: FastAPI, SQLAlchemy 2.0, PostgreSQL, Pydantic v2, httpx + tenacity, structlog, Sentry. Runs in a 195 MB Alpine container, non-root, no pip in the runtime image, signed with cosign. CI gate is 9 blocking jobs: Bandit, Semgrep, Ruff (security ruleset), mypy strict, pip-audit, Hadolint, Trivy (fails on CRITICAL+HIGH > 0), SBOM publish, full pytest with 86% coverage threshold.

What it won't do (yet)

Honesty section:

  • Not a TIP replacement. No actor or campaign attribution, no malware-family clustering, no IOC enrichment beyond what the source feeds publish.
  • No STIX 2.1 / TAXII export yet. That's M5 on the roadmap — needed for enterprise TIP ingestion.
  • GHSA collector is in soft-fail mode in production. It runs, but GraphQL rate-limiting still bites occasionally and I haven't fully stabilised the cursor pagination. NVD and KEV are the reliable spine right now.
  • No webhook alerting yet. Poll the dashboard endpoint, or subscribe to the RSS feed. M4 will fix this.

If any of those are blockers for your team, the issues board is the right place to say so — priority follows usage.

Try it / contribute

Where help would actually matter:

  • Sector profiles. A payments analyst can ship a better finance.yaml than I can. Same for a clinical-systems engineer on healthcare, or an OT engineer on ICS. Open a PR with a YAML and a one-paragraph rationale.
  • GHSA stabilisation. GraphQL pagination and rate-limit handling in collectors/ghsa.py.
  • M4 webhook alerting. The shape is sketched in the roadmap. Looking for someone who's done webhook delivery at scale (retries, signing, dead-letter handling).

Run it locally:

git clone https://github.com/Setounkpe7/threat-intel-api.git
cd threat-intel-api
docker compose up
# API on :8000, Swagger at /docs

Enter fullscreen mode Exit fullscreen mode