VulnFeed 2.0:构建 Zero-Server 漏洞仪表盘(Level 2 发布)

发布: (2025年12月7日 GMT+8 04:02)
6 min read
原文: Dev.to

Source: Dev.to

问题

大多数漏洞仪表盘要么:

  • 费用过高 – 企业级 SaaS 工具价格高昂
  • 功能受限 – 只专注于单一生态系统或发行版
  • 隐私噩梦 – 追踪你的数据、查询和团队
  • 过于复杂 – 需要后端基础设施来维护

我们想要一种根本不同的方案。

介绍 Onyx Intelligence

Onyx 是一个完全静态、零服务器的漏洞仪表盘,聚合来自 25+ 个来源(CISA、Red Hat、所有主流 Linux 发行版、npm、PyPI、Maven、RubyGems、Cargo、Composer 等)的数据,呈现在一个美观、交互式的界面中。

可以把它看作 VulnFeed 的 Level 2 进化版 —— 你喜欢的一切功能,且更强大。

关键统计

  • 📊 25+ 个漏洞数据来源
  • 🔄 通过 GitHub Actions 每 6 小时自动更新
  • 🏗️ 零后端需求(GitHub Pages 部署)
  • 🔒 零追踪,零数据收集
  • 🎨 美观的玻璃拟态 UI,支持明暗主题
  • 📱 完全响应式(移动端、平板、桌面)
  • 🧠 资产暴露扫描(可选)

工作原理(技术实现)

数据收集管道

一切从一个每 6 小时运行一次的 GitHub Actions 工作流开始:

# .github/workflows/osv-feed-update.yml
schedule:
  - cron: '0 */6 * * *'  # Every 6 hours

以下是幕后发生的事情:

# scripts/fetch_osv_data.py
import requests
import json
from datetime import datetime

# Fetch from OSV.dev for all ecosystems
ecosystems = ['npm', 'PyPI', 'Maven', 'Cargo', 'Go', 'NuGet', 'Composer', 'RubyGems']

for ecosystem in ecosystems:
    response = requests.get(
        'https://api.osv.dev/v1/query',
        json={'package': {'ecosystem': ecosystem}}
    )
    # Validate and deduplicate
    vulnerabilities = response.json()

    # Store as clean JSON
    with open(f'data/{ecosystem.lower()}.json', 'w') as f:
        json.dump(vulnerabilities, f)

# Also fetch CISA KEV, Red Hat, Linux distros
# Everything gets merged, validated, and deployed

输出为干净、结构化的 JSON 文件,供前端使用。

前端渲染

在客户端,它是纯原生 JavaScript,没有任何框架或臃肿代码:

// Load vulnerability data from static JSON files
async function loadVulnerabilities() {
    const response = await fetch('/data/vulnerabilities.json');
    return response.json();
}

// Build interactive visualizations with Chart.js
function renderSeverityChart(vulnerabilities) {
    const severityData = {
        labels: ['Critical', 'High', 'Medium', 'Low'],
        datasets: [{
            data: [
                vulnerabilities.filter(v => v.severity === 'CRITICAL').length,
                vulnerabilities.filter(v => v.severity === 'HIGH').length,
                vulnerabilities.filter(v => v.severity === 'MEDIUM').length,
                vulnerabilities.filter(v => v.severity === 'LOW').length
            ]
        }]
    };

    new Chart(ctx, { type: 'doughnut', data: severityData });
}

// Real‑time filtering and search (no backend calls!)
function searchVulnerabilities(query, severity, days) {
    return vulnerabilities.filter(v => 
        (v.description.toLowerCase().includes(query.toLowerCase()) ||
         v.id.includes(query)) &&
        (severity === 'ALL' || v.severity === severity) &&
        (isWithinDays(v.published, days))
    );
}

没有 API 调用。没有服务器请求。仅靠静态资源和客户端逻辑完成繁重工作。

部署魔法

部署几乎是如此简单,宛如魔法:

  1. Commit changes to your fork.
  2. GitHub Actions workflow triggers automatically.
  3. Python scripts fetch fresh data.
  4. Static HTML/CSS/JS gets generated.
  5. Deployed to GitHub Pages automatically.

你的仪表盘已上线:yourusername.github.io/Onyx-Intelligence/

我们构建的关键特性

✅ 多源聚合

不再需要为不同漏洞来源打开 25 个浏览器标签页,所有内容集中在一个地方:

// Single search across CISA, Red Hat, npm, PyPI, Maven, etc.
const allVulnerabilities = [
    ...cisaKEV,
    ...redHatAdvisories,
    ...npmVulnerabilities,
    ...pypiVulnerabilities,
    ...mavenVulnerabilities,
    // ... 20+ more sources
];

// Now search once and get results from everywhere
const results = allVulnerabilities.filter(v =>
    v.id.includes('CVE-2024-') ||
    v.packages.includes('lodash') ||
    v.source === 'CISA'
);
✅ 智能过滤

高级过滤,无需后端复杂性:

// Critical vulnerabilities from the last 30 days
const criticalRecent = vulnerabilities.filter(v =>
    v.cvss >= 7.0 &&
    daysOld(v.published)  v.ecosystem === 'npm');

// Combine filters
const targetedResults = vulnerabilities.filter(v =>
    (v.severity === 'CRITICAL' || v.severity === 'HIGH') &&
    v.ecosystem.includes('Linux') &&
    daysOld(v.published) <= 7
);
✅ 资产暴露扫描器

可选功能,扫描 IP 和域名,使用多个情报源:

// Scan an IP against Censys, Shodan, AbuseIPDB, VirusTotal
async function scanAsset(ipOrDomain) {
    const results = await Promise.all([
        fetch(`/api/scan?ip=${ipOrDomain}&provider=censys`),
        fetch(`/api/scan?ip=${ipOrDomain}&provider=shodan`),
        fetch(`/api/scan?ip=${ipOrDomain}&provider=abuseipdb`),
        fetch(`/api/scan?ip=${ipOrDomain}&provider=virustotal`)
    ]);

    return {
        censys: await results[0].json(),
        shodan: await results[1].json(),
        abuseipdb: await results[2].json(),
        virustotal: await results[3].json()
    };
}

API 密钥安全存储在 GitHub Secrets 中——永不在前端代码中泄露。

✅ 隐私至上设计

零追踪。零数据收集。仅是纯粹、诚实的软件:

// Only localStorage for theme preference
localStorage.setItem('theme', 'dark');
localStorage.setItem('lastViewed', 'npm');

// Everything else is session‑only, in‑memory
const sessionData = {
    currentFilters: { severity: 'HIGH', days: 30 },
    selectedVulnerability: null
};

// No Google Analytics, Mixpanel, Segment, etc.
✅ 美观 UI

我们不仅仅是构建了一个工具——我们打造了一个高端外观的产品:

/* Glassmorphism cards */
.vulnerability-card {
    background: rgba(255, 255, 255, 0.1);
    backdrop-filter: blur(10px);
    border: 1px solid rgba(255, 255, 255, 0.2);
    border-radius: 12px;
    padding: 1.5rem;
    transition: all 0.3s ease;
}
.vulnerability-card:hover {
    background: rgba(255, 255, 255, 0.15);
    transform: translateY(-2px);
    box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
}

/* Dark mode support */
@media (prefers-color-scheme: dark) {
    .vulnerability-card {
        background: rgba(30, 27, 75, 0.2);
        border-color: rgba(255, 255, 255, 0.1);
    }
}

/* Responsive grid */
@media (max-width: 768px) {
    .grid {
        grid-template-columns: 1fr;
    }
}

流畅的动画,明暗主题,完全响应式。

入门指南(真的,只需 5 分钟)

步骤 1:Fork 仓库

(后续步骤请参见原文。)

Back to Blog

相关文章

阅读更多 »