
Rss Analyzer
- 1 installs
- 1 repo stars
- Updated July 19, 2026
- dapperdivers/roundtable-arsenal
Analyze RSS feeds and extract structured insights from feed data.
About
RSS-analyzer provides tools for parsing and analyzing RSS feeds. Developers use it to extract topics, trends, and metadata from multiple feed sources.
- RSS feed parsing and analysis
- Content extraction and metadata
Rss Analyzer by the numbers
- 1 all-time installs (skills.sh)
- Ranked #1,803 of 2,064 Data Science & ML skills by installs in the Skillselion catalog
- Data as of Jul 20, 2026 (Skillselion catalog sync)
npx skills add https://github.com/dapperdivers/roundtable-arsenal --skill rss-analyzerAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 1 |
|---|---|
| repo stars | ★ 1 |
| Last updated | July 19, 2026 |
| Repository | dapperdivers/roundtable-arsenal ↗ |
What it does
Analyze RSS feeds and extract structured insights from feed data.
Files
RSS Analyzer
Fetches cybersecurity RSS feeds and analyzes entries for threats, categorization, and severity scoring.
When to Use
- Building daily/weekly security briefings
- Monitoring specific feeds for breaking threats
- Supplementing OpenCTI data with narrative context from security blogs
- Tracking disclosure timelines for vulnerabilities
Configuration
| Variable | Default | Description |
|---|---|---|
RSS_CACHE_DIR | /tmp/rss-cache | Directory for cached feed data |
RSS_MAX_AGE_HOURS | 24 | Maximum age of entries to process |
Configured Feeds
See references/feeds.md for the full feed list with categories.
Workflow
1. Fetch — Download configured RSS/Atom feeds via HTTP/HTTPS 2. Parse — Extract entries (title, link, published date, description/summary) 3. Categorize — Assign category: vulnerability, malware, threat-actor, policy, tool, research 4. Score — Assign severity (critical, high, medium, low) based on keywords and context 5. Deduplicate — Remove duplicate entries across feeds (by URL or title similarity) 6. Output — Return structured JSON or render markdown
Scripts
Fetch all feeds
python3 scripts/fetch-feeds.py [--cache-dir /path] [--verbose]Fetches all feeds configured in references/feeds.md. Outputs JSON array of entries.
Example output:
[
{
"feed": "BleepingComputer",
"title": "Critical RCE in Log4j allows remote code execution",
"link": "https://example.com/article",
"published": "2026-03-17T14:30:00Z",
"category": "vulnerability",
"severity": "critical"
}
]Analyze fetched entries
python3 scripts/analyze-feed.py [--since 24h] [--min-severity medium] [--category vulnerability]Analyzes cached feed data. Filters by time window, severity, and category.
Example:
# Get all critical/high vulns from last 48 hours
python3 scripts/analyze-feed.py --since 48h --min-severity high --category vulnerability
# Output format
{
"entries": [...],
"summary": {
"total": 42,
"by_severity": {"critical": 3, "high": 12, "medium": 27},
"by_category": {"vulnerability": 28, "malware": 14}
}
}Error Handling
Scripts exit with:
0— Success1— Network error (feed unreachable)2— Parse error (invalid XML/JSON)3— Configuration error (missing feed list)
Check stderr for error details.
Examples
Use Case 1: Daily Briefing
# Fetch latest, analyze high-severity items
python3 scripts/fetch-feeds.py
python3 scripts/analyze-feed.py --since 24h --min-severity highUse Case 2: Malware Tracking
# Get malware-specific entries from last week
python3 scripts/analyze-feed.py --since 168h --category malwareUse Case 3: Custom Time Window
# Historical analysis for specific date range
python3 scripts/fetch-feeds.py
python3 scripts/analyze-feed.py --since 2026-03-15T00:00:00Z --until 2026-03-16T23:59:59ZNote on OpenCTI RSS
18 security feeds are also ingested into OpenCTI as STIX reports. For structured data, prefer querying OpenCTI via opencti-intel. Use this skill for:
- Feeds NOT in OpenCTI
- When you need the raw narrative/article text
- When OpenCTI RSS ingestion is behind or inactive
- Custom feed analysis not available in OpenCTI
Dependencies
- Python 3.9+
feedparser— RSS/Atom parsingbeautifulsoup4— HTML cleanuprequests— HTTP client
Install via: pip3 install feedparser beautifulsoup4 requests
Security RSS Feeds
Threat Intelligence
| Feed | URL | Category |
|---|---|---|
| Krebs on Security | https://krebsonsecurity.com/feed/ | General |
| BleepingComputer | https://www.bleepingcomputer.com/feed/ | General |
| The Record | https://therecord.media/feed | General |
| Dark Reading | https://www.darkreading.com/rss.xml | General |
| The Hacker News | https://feeds.feedburner.com/TheHackersNews | General |
Vendor Research
| Feed | URL | Category |
|---|---|---|
| Unit 42 (Palo Alto) | https://unit42.paloaltonetworks.com/feed/ | Research |
| Securelist (Kaspersky) | https://securelist.com/feed/ | Research |
| Mandiant Blog | https://www.mandiant.com/resources/blog/rss.xml | Research |
| SentinelOne Labs | https://www.sentinelone.com/labs/feed/ | Research |
| Talos Intelligence | https://blog.talosintelligence.com/feeds/posts/default | Research |
Vulnerability Focus
| Feed | URL | Category |
|---|---|---|
| CISA Alerts | https://www.cisa.gov/cybersecurity-advisories/all.xml | Advisories |
| NIST NVD | https://nvd.nist.gov/feeds/xml/cve/misc/nvd-rss.xml | CVE |
| Exploit Database | https://www.exploit-db.com/rss.xml | Exploits |
Cloud / Infrastructure
| Feed | URL | Category |
|---|---|---|
| Kubernetes Blog | https://kubernetes.io/feed.xml | Infra |
| Aqua Security | https://blog.aquasec.com/rss.xml | Cloud |
| Wiz Blog | https://www.wiz.io/blog/rss.xml | Cloud |
#!/usr/bin/env python3
"""analyze-feed.py — Analyze feed entries for threats and severity scoring."""
import argparse
import json
import re
import sys
SEVERITY_KEYWORDS = {
"critical": ["critical", "zero-day", "0-day", "rce", "remote code execution", "actively exploited"],
"high": ["high", "ransomware", "breach", "exploit", "vulnerability", "cve-"],
"medium": ["medium", "phishing", "malware", "update", "patch"],
"low": ["low", "advisory", "disclosure", "research"],
}
SEVERITY_ORDER = {"critical": 4, "high": 3, "medium": 2, "low": 1}
CATEGORIES = {
"vulnerability": ["cve", "vulnerability", "exploit", "zero-day", "0-day", "rce", "buffer overflow"],
"ransomware": ["ransomware", "ransom", "lockbit", "blackcat", "clop"],
"breach": ["breach", "leak", "data exposure", "compromised"],
"malware": ["malware", "trojan", "botnet", "rat", "backdoor"],
"phishing": ["phishing", "social engineering", "spear-phishing"],
"patch": ["patch", "update", "fix", "security update"],
"policy": ["regulation", "compliance", "policy", "gdpr", "nist"],
}
def classify_entry(entry: dict) -> dict:
"""Add severity and category to a feed entry."""
text = f"{entry.get('title', '')} {entry.get('summary', '')}".lower()
# Determine severity
severity = "low"
for level in ["critical", "high", "medium", "low"]:
if any(kw in text for kw in SEVERITY_KEYWORDS[level]):
severity = level
break
# Determine categories
cats = []
for cat, keywords in CATEGORIES.items():
if any(kw in text for kw in keywords):
cats.append(cat)
entry["severity"] = severity
entry["severity_score"] = SEVERITY_ORDER[severity]
entry["categories"] = cats or ["general"]
return entry
def main():
parser = argparse.ArgumentParser(description="Analyze feed entries for threats.")
parser.add_argument("--input", help="JSON file of entries (default: stdin)")
parser.add_argument("--min-severity", choices=["low", "medium", "high", "critical"], default="low")
parser.add_argument("--categories", help="Filter by categories (comma-separated)")
args = parser.parse_args()
if args.input:
entries = json.loads(open(args.input).read())
else:
entries = json.load(sys.stdin)
min_score = SEVERITY_ORDER[args.min_severity]
filter_cats = set(args.categories.split(",")) if args.categories else None
analyzed = []
for entry in entries:
entry = classify_entry(entry)
if entry["severity_score"] < min_score:
continue
if filter_cats and not set(entry["categories"]) & filter_cats:
continue
analyzed.append(entry)
analyzed.sort(key=lambda x: x["severity_score"], reverse=True)
json.dump(analyzed, sys.stdout, indent=2)
if __name__ == "__main__":
main()
#!/usr/bin/env python3
"""fetch-feeds.py — Fetch RSS feeds and return structured JSON."""
import argparse
import json
import sys
from datetime import datetime, timedelta, timezone
try:
import feedparser
except ImportError:
print("Error: feedparser not installed. Run: pip install feedparser", file=sys.stderr)
sys.exit(1)
DEFAULT_FEEDS = [
"https://feeds.feedburner.com/TheHackersNews",
"https://www.cisa.gov/cybersecurity-advisories/all.xml",
"https://krebsonsecurity.com/feed/",
"https://www.bleepingcomputer.com/feed/",
]
def parse_since(since_str: str) -> datetime:
"""Parse a relative time string like '24h' or '7d' into a datetime."""
now = datetime.now(timezone.utc)
if since_str.endswith("h"):
return now - timedelta(hours=int(since_str[:-1]))
elif since_str.endswith("d"):
return now - timedelta(days=int(since_str[:-1]))
raise ValueError(f"Invalid --since format: {since_str}")
def fetch_feed(url: str, since: datetime = None) -> list:
"""Fetch a single feed and return entries."""
feed = feedparser.parse(url)
entries = []
for entry in feed.entries:
published = entry.get("published_parsed")
if published:
pub_dt = datetime(*published[:6], tzinfo=timezone.utc)
if since and pub_dt < since:
continue
pub_str = pub_dt.isoformat()
else:
pub_str = None
entries.append({
"title": entry.get("title", ""),
"link": entry.get("link", ""),
"published": pub_str,
"summary": entry.get("summary", "")[:500],
"source": feed.feed.get("title", url),
})
return entries
def main():
parser = argparse.ArgumentParser(description="Fetch cybersecurity RSS feeds.")
parser.add_argument("--url", action="append", help="Feed URL (repeatable)")
parser.add_argument("--feeds", help="JSON file with list of feed URLs")
parser.add_argument("--since", help="Only entries from last Nh or Nd (e.g., 24h, 7d)")
parser.add_argument("--format", choices=["json", "summary"], default="json")
args = parser.parse_args()
urls = []
if args.url:
urls.extend(args.url)
if args.feeds:
urls.extend(json.loads(open(args.feeds).read()))
if not urls:
urls = DEFAULT_FEEDS
since = parse_since(args.since) if args.since else None
all_entries = []
for url in urls:
try:
all_entries.extend(fetch_feed(url, since))
except Exception as e:
print(f"Warning: Failed to fetch {url}: {e}", file=sys.stderr)
all_entries.sort(key=lambda x: x.get("published") or "", reverse=True)
if args.format == "summary":
for e in all_entries:
print(f"[{e['published'] or '?'}] {e['title']}")
print(f" {e['link']}\n")
else:
json.dump(all_entries, sys.stdout, indent=2)
if __name__ == "__main__":
main()