cve-source-check
Audit CVE/vulnerability source coverage for a technology stack. Maps each component (container, library, base image, runtime) to authoritative CVE feeds, flags gaps, and produces audit-ready reports. Generic: works for any service or stack.
Install
npx skills add https://github.com/notque/vexjoy-agent/tree/main/skills/infrastructure/cve-source-check
claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install notque-vexjoy-agent@llmmart
git clone https://github.com/notque/vexjoy-agent.git
The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole notque/vexjoy-agent collection as a plugin from our marketplace. Git is the plain clone.
Skill manifest
CVE Source Check
Audit CVE/vulnerability source coverage for a technology stack. Maps components to authoritative CVE feeds via a versioned registry, flags gaps, and produces audit-ready reports (JSON + Markdown).
In scope: component-to-feed mapping, coverage/gap reporting, optional URL reachability checks. Out of scope: running scanners (Trivy/Snyk), fetching CVE content, private vuln databases.
Quick Start
# Inline, offline
python3 scripts/check-cve-sources.py \
--inline "go@1.22,alpine@3.19,postgres@16,redis@7,nginx@1.25" \
--service my-service
# Inventory + monitored feeds + link verification
python3 scripts/check-cve-sources.py \
--inventory examples/inventory.example.json \
--current-sources examples/current-sources.example.txt \
--service my-service --check-urls
Inputs
| Flag | Purpose |
|---|---|
--inventory <file> |
JSON: [{name, version?, type?}, ...] or {components: [...]}. |
--inline "name@ver,..." |
Comma-separated list. Mutually exclusive with --inventory. |
--current-sources <file> |
One URL per line. # comments and blank lines skipped. |
--service <name> |
Name for report header and filenames. |
--check-urls |
HEAD-check every source URL (5s timeout, graceful degradation). |
--registry <path> |
Override default tech-source-registry.json. |
--out-dir <path> |
Output directory (default: cwd). |
JSON only. YAML not supported (no stdlib parser).
Outputs
Files: cve-source-report-{service}-{YYYYMMDD}.{md,json} in --out-dir.
| Exit | Meaning |
|---|---|
| 0 | Full coverage. |
| 1 | Gaps (unmapped components or unmonitored sources). |
| 2 | Unreachable source URL (only with --check-urls). |
| 3 | Input error (missing/malformed registry or inventory). |
Workflow
Phase 1: LOAD
- Locate
tech-source-registry.json(next to SKILL.md by default, or--registry). - Build inventory from
--inventory(JSON list or{components: [...]}) or--inline(comma-splitname@version). - If
--current-sourcesprovided, read URLs and normalize for case-insensitive comparison.
Gate: at least one component present. Empty inventory -> exit 3.
Phase 2: MAP & VERIFY
- Look up each component
name(and aliases) in the registry.- Found ->
mapped, attach source list. Missing ->unmapped, sources[].
- Found ->
- If current sources loaded, mark each source
monitored: truewhen its normalized URL appears. - If
--check-urls: HEAD-check each unique URL. Treat 200/301/302/403/405 as reachable. 4xx (except 403/405) and 5xx ->reachable: false. Timeout/DNS/TLS failure ->reachable: null(WARN, does not affect exit code). 5s timeout per URL, cached per run.
Gate: every component has status; every source has monitored and reachable fields.
Phase 3: REPORT
- Compute summary: components, mapped/unmapped, monitored, coverage %, gaps, unreachable.
- Write JSON report with per-component status and per-source
monitored/reachablefields. - Write Markdown report: summary table, components table (markers), gaps section (when gaps exist), unmapped section (when unmapped exist).
- Print one-screen summary to stdout. Set exit code per table above.
Gate: both files written, summary printed.
Registry Schema
tech-source-registry.json shape:
{
"$schema_version": "1.0",
"kinds": ["advisory-list", "github-security", "mailing-list", "distro-tracker", "vendor-page", "mitre"],
"priorities": ["primary", "secondary"],
"technologies": [
{"name": "postgres", "aliases": ["postgresql","pg"], "type": "container",
"sources": [{"url": "https://...", "kind": "advisory-list", "priority": "primary"}]}
]
}
Each technology: name (lowercase, unique), aliases (list), type (runtime/base-image/container/library), sources (1-3, at least one primary).
To add a technology: pick canonical name, list aliases, add 1-3 sources (lead with vendor advisory page), re-run against a sample inventory.
Error Handling
| Error | Cause | Fix |
|---|---|---|
| Failed to load registry | Missing or malformed JSON | Validate with python3 -m json.tool |
| Failed to load inventory | Missing, malformed, or wrong shape | Validate JSON; must be list or {components: [...]} |
| Inventory empty | No usable components | Each entry needs name. Inline needs non-empty tokens. |
| Coverage stuck at 0% | --current-sources URLs don't match registry |
Copy URLs from registry. Scheme/host case and trailing slash are normalized; rest must match. |
Many [--] entries with --check-urls |
Network issues | Re-run without --check-urls. Network errors don't affect gap exit code. |
Files (vexjoy-agent)
-
examples
-
current-sources.example.txt 218 B
# Example: feeds my-service currently monitors. # One URL per line; blank lines and `#` comments are skipped. https://pkg.go.dev/vuln/list https://security.alpinelinux.org/ https://www.postgresql.org/support/security/ -
inventory.example.json 368 B
{ "service": "my-service", "components": [ {"name": "go", "version": "1.22.3", "type": "runtime"}, {"name": "alpine", "version": "3.19", "type": "base-image"}, {"name": "postgres", "version": "16.2", "type": "container"}, {"name": "redis", "version": "7.2", "type": "container"}, {"name": "nginx", "version": "1.25", "type": "container"} ] }
-
-
scripts
-
check-cve-sources.py 13.3 KB
#!/usr/bin/env python3 """check-cve-sources.py — audit CVE/vulnerability source coverage for a tech stack. Three-phase methodology: 1. LOAD inventory + registry + (optional) currently-monitored sources 2. MAP & VERIFY resolve each component to authoritative feeds; mark monitored; optionally HEAD-check URL reachability 3. REPORT emit JSON + Markdown audit reports stdlib only. Generic. Vendor-neutral. """ from __future__ import annotations import argparse import json import os import re import sys import urllib.error import urllib.request from datetime import datetime, timezone DEFAULT_REGISTRY = os.path.join( os.path.dirname(os.path.abspath(__file__)), "..", "tech-source-registry.json", ) HEAD_TIMEOUT = 5 REACHABLE_CODES = {200, 301, 302, 403, 405} # ----------------------------- LOAD ----------------------------------------- def load_registry(path: str) -> dict: with open(path, "r", encoding="utf-8") as f: return json.load(f) def build_lookup(registry: dict) -> dict[str, dict]: """Map name + aliases (lowercased) -> tech entry.""" lookup: dict[str, dict] = {} for entry in registry.get("technologies", []): keys = [entry["name"]] + list(entry.get("aliases", [])) for k in keys: lookup[k.lower()] = entry return lookup def parse_inventory(path: str) -> list[dict]: """JSON inventory: [{name, version?, type?}, ...] or {components: [...]}.""" with open(path, "r", encoding="utf-8") as f: data = json.load(f) if isinstance(data, dict): components = data.get("components", []) elif isinstance(data, list): components = data else: raise ValueError("Inventory JSON must be a list or {components: [...]}") out = [] for c in components: if isinstance(c, str): name, ver = _split_pin(c) out.append({"name": name, "version": ver, "type": ""}) elif isinstance(c, dict): out.append( { "name": c.get("name", "").strip(), "version": str(c.get("version", "")).strip(), "type": c.get("type", "").strip(), } ) return [c for c in out if c["name"]] def parse_inline(spec: str) -> list[dict]: """Parse 'name@ver,name,name@ver' into component list.""" out = [] for token in spec.split(","): token = token.strip() if not token: continue name, ver = _split_pin(token) out.append({"name": name, "version": ver, "type": ""}) return out def _split_pin(token: str) -> tuple[str, str]: if "@" in token: n, v = token.split("@", 1) return n.strip(), v.strip() return token.strip(), "" def load_current_sources(path: str) -> set[str]: """One URL per line; blank and # comments skipped.""" urls: set[str] = set() with open(path, "r", encoding="utf-8") as f: for line in f: line = line.strip() if not line or line.startswith("#"): continue urls.add(_normalize_url(line)) return urls def _normalize_url(url: str) -> str: # Drop trailing slash, lowercase scheme+host for comparison. m = re.match(r"^(https?://)([^/]+)(/.*)?$", url, re.IGNORECASE) if not m: return url.rstrip("/") scheme, host, path = m.group(1).lower(), m.group(2).lower(), (m.group(3) or "") return f"{scheme}{host}{path}".rstrip("/") # ----------------------------- MAP & VERIFY --------------------------------- def map_component(component: dict, lookup: dict[str, dict]) -> dict: key = component["name"].lower() entry = lookup.get(key) if entry is None: return { **component, "status": "unmapped", "type": component.get("type") or "unknown", "sources": [], } sources = [{**s, "monitored": False, "reachable": None} for s in entry.get("sources", [])] return { **component, "status": "mapped", "type": component.get("type") or entry.get("type", "unknown"), "sources": sources, } def mark_monitored(mapped: list[dict], current: set[str]) -> None: for comp in mapped: for s in comp["sources"]: if _normalize_url(s["url"]) in current: s["monitored"] = True def head_check(url: str) -> bool | None: """Return True (reachable), False (definitely unreachable), None (network error).""" try: req = urllib.request.Request(url, method="HEAD") with urllib.request.urlopen(req, timeout=HEAD_TIMEOUT) as resp: return resp.status in REACHABLE_CODES except urllib.error.HTTPError as e: return e.code in REACHABLE_CODES except (urllib.error.URLError, TimeoutError, OSError): return None except Exception: return None def verify_urls(mapped: list[dict]) -> int: """HEAD-check every URL; return count of definitively unreachable URLs.""" unreachable = 0 seen: dict[str, bool | None] = {} for comp in mapped: for s in comp["sources"]: url = s["url"] if url not in seen: seen[url] = head_check(url) s["reachable"] = seen[url] if seen[url] is False: unreachable += 1 return unreachable # ----------------------------- REPORT --------------------------------------- def summarize(mapped: list[dict]) -> dict: n = len(mapped) n_mapped = sum(1 for c in mapped if c["status"] == "mapped") n_unmapped = n - n_mapped n_monitored = sum(1 for c in mapped if c["status"] == "mapped" and any(s["monitored"] for s in c["sources"])) n_gaps = ( sum(1 for c in mapped if c["status"] == "mapped" and not any(s["monitored"] for s in c["sources"])) + n_unmapped ) n_unreachable = sum(1 for c in mapped for s in c["sources"] if s.get("reachable") is False) coverage = round(100.0 * n_monitored / n, 1) if n else 0.0 return { "components": n, "mapped": n_mapped, "unmapped": n_unmapped, "monitored": n_monitored, "coverage_pct": coverage, "gaps": n_gaps, "unreachable": n_unreachable, } def render_json(service: str, mapped: list[dict], summary: dict) -> dict: return { "service": service, "generated_at": datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ"), "summary": summary, "components": mapped, } def _marker(comp: dict) -> str: if comp["status"] == "unmapped": return "❌" if any(s["monitored"] for s in comp["sources"]): return "✅" return "⚠️" def _reach_str(reachable) -> str: if reachable is True: return "ok" if reachable is False: return "DOWN" return "—" def render_markdown(service: str, mapped: list[dict], summary: dict, checked: bool) -> str: ts = datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ") out: list[str] = [] out.append(f"# CVE Source Coverage Report: {service}") out.append("") out.append(f"_Generated: {ts}_") out.append("") out.append("## Summary") out.append("") out.append("| Metric | Value |") out.append("|--------|-------|") out.append(f"| Components | {summary['components']} |") out.append(f"| Mapped to registry | {summary['mapped']} |") out.append(f"| Unmapped | {summary['unmapped']} |") out.append(f"| Monitored (≥1 source) | {summary['monitored']} |") out.append(f"| Coverage | {summary['coverage_pct']}% |") out.append(f"| Gaps | {summary['gaps']} |") if checked: out.append(f"| Unreachable URLs | {summary['unreachable']} |") out.append("") out.append("Legend: ✅ mapped + monitored • ⚠️ mapped, not monitored • ❌ unmapped") out.append("") out.append("## Components") out.append("") header = "| Status | Component | Version | Type | Sources |" sep = "|--------|-----------|---------|------|---------|" out.append(header) out.append(sep) for c in mapped: sources_cell = _format_sources(c["sources"], checked) out.append( f"| {_marker(c)} | `{c['name']}` | {c.get('version') or '—'} | {c.get('type') or '—'} | {sources_cell} |" ) out.append("") # Gaps gap_rows = [c for c in mapped if c["status"] == "mapped" and not any(s["monitored"] for s in c["sources"])] if gap_rows: out.append("## Gaps — Sources to add") out.append("") out.append("Components mapped to authoritative sources you do not currently monitor:") out.append("") for c in gap_rows: out.append(f"### {c['name']}") for s in c["sources"]: if s["priority"] == "primary": out.append(f"- **primary** ({s['kind']}): {s['url']}") for s in c["sources"]: if s["priority"] != "primary": out.append(f"- secondary ({s['kind']}): {s['url']}") out.append("") # Unmapped unmapped = [c for c in mapped if c["status"] == "unmapped"] if unmapped: out.append("## Unmapped — Registry Extension TODO") out.append("") out.append("These components are not in the registry. Add entries (see `references/registry-schema.md`):") out.append("") for c in unmapped: out.append(f"- [ ] `{c['name']}` (version `{c.get('version') or '?'}`, type `{c.get('type') or '?'}`)") out.append("") return "\n".join(out) + "\n" def _format_sources(sources: list[dict], checked: bool) -> str: if not sources: return "—" cells = [] for s in sources: flag = "✓" if s["monitored"] else "·" reach = f" [{_reach_str(s.get('reachable'))}]" if checked else "" cells.append(f"{flag} {s['priority']}/{s['kind']}{reach}") return "<br>".join(cells) # ----------------------------- CLI ------------------------------------------ def parse_args(argv: list[str]) -> argparse.Namespace: p = argparse.ArgumentParser( description="Audit CVE/vulnerability source coverage for a technology stack.", ) src = p.add_mutually_exclusive_group(required=True) src.add_argument("--inventory", help="Path to JSON inventory file.") src.add_argument("--inline", help='Inline list: "name@ver,name,name@ver"') p.add_argument("--current-sources", help="Optional path; one URL per line.") p.add_argument("--service", default="service", help="Service name for report header.") p.add_argument("--check-urls", action="store_true", help="HEAD-check source URLs (5s timeout).") p.add_argument("--registry", default=DEFAULT_REGISTRY, help="Path to tech-source-registry.json.") p.add_argument("--out-dir", default=".", help="Output directory (default: cwd).") return p.parse_args(argv) def main(argv: list[str]) -> int: args = parse_args(argv) # PHASE 1: LOAD try: registry = load_registry(args.registry) except (OSError, json.JSONDecodeError) as e: print(f"ERROR: failed to load registry: {e}", file=sys.stderr) return 3 lookup = build_lookup(registry) if args.inventory: try: components = parse_inventory(args.inventory) except (OSError, json.JSONDecodeError, ValueError) as e: print(f"ERROR: failed to load inventory: {e}", file=sys.stderr) return 3 else: components = parse_inline(args.inline) if not components: print("ERROR: inventory is empty", file=sys.stderr) return 3 current = set() if args.current_sources: try: current = load_current_sources(args.current_sources) except OSError as e: print(f"WARN: failed to load current sources ({e}); proceeding without.", file=sys.stderr) # PHASE 2: MAP & VERIFY mapped = [map_component(c, lookup) for c in components] if current: mark_monitored(mapped, current) unreachable_count = 0 if args.check_urls: unreachable_count = verify_urls(mapped) # PHASE 3: REPORT summary = summarize(mapped) payload = render_json(args.service, mapped, summary) md = render_markdown(args.service, mapped, summary, checked=args.check_urls) os.makedirs(args.out_dir, exist_ok=True) date_tag = datetime.now(timezone.utc).strftime("%Y%m%d") safe_service = re.sub(r"[^A-Za-z0-9_.-]+", "-", args.service) json_path = os.path.join(args.out_dir, f"cve-source-report-{safe_service}-{date_tag}.json") md_path = os.path.join(args.out_dir, f"cve-source-report-{safe_service}-{date_tag}.md") with open(json_path, "w", encoding="utf-8") as f: json.dump(payload, f, indent=2, ensure_ascii=False) f.write("\n") with open(md_path, "w", encoding="utf-8") as f: f.write(md) print(f"Service: {args.service}") print(f"Components: {summary['components']}") print(f"Mapped: {summary['mapped']} (unmapped: {summary['unmapped']})") print(f"Monitored: {summary['monitored']} (coverage: {summary['coverage_pct']}%)") print(f"Gaps: {summary['gaps']}") if args.check_urls: print(f"Unreachable: {summary['unreachable']}") print(f"JSON report: {json_path}") print(f"MD report: {md_path}") if args.check_urls and unreachable_count > 0: return 2 if summary["gaps"] > 0: return 1 return 0 if __name__ == "__main__": sys.exit(main(sys.argv[1:]))
-
-
SKILL.md 5.4 KB
--- name: cve-source-check promoted_to: deploy description: "Audit CVE/vulnerability source coverage for a technology stack. Maps each component (container, library, base image, runtime) to authoritative CVE feeds, flags gaps, and produces audit-ready reports. Generic: works for any service or stack." user-invocable: false argument-hint: "[--inventory <file>] [--inline <tech-list>] [--current-sources <file>] [--service <name>] [--check-urls]" allowed-tools: - Bash - Read - Write - Edit - Glob - Grep routing: triggers: - "check cve sources" - "cve source coverage" - "audit cve feeds" - "vulnerability source audit" - "verify cve sources" - "security feed audit" category: infrastructure complexity: Simple pairs_with: - assessment --- # CVE Source Check Audit CVE/vulnerability source coverage for a technology stack. Maps components to authoritative CVE feeds via a versioned registry, flags gaps, and produces audit-ready reports (JSON + Markdown). **In scope**: component-to-feed mapping, coverage/gap reporting, optional URL reachability checks. **Out of scope**: running scanners (Trivy/Snyk), fetching CVE content, private vuln databases. ## Quick Start ```bash # Inline, offline python3 scripts/check-cve-sources.py \ --inline "go@1.22,alpine@3.19,postgres@16,redis@7,nginx@1.25" \ --service my-service # Inventory + monitored feeds + link verification python3 scripts/check-cve-sources.py \ --inventory examples/inventory.example.json \ --current-sources examples/current-sources.example.txt \ --service my-service --check-urls ``` ## Inputs | Flag | Purpose | |---|---| | `--inventory <file>` | JSON: `[{name, version?, type?}, ...]` or `{components: [...]}`. | | `--inline "name@ver,..."` | Comma-separated list. Mutually exclusive with `--inventory`. | | `--current-sources <file>` | One URL per line. `#` comments and blank lines skipped. | | `--service <name>` | Name for report header and filenames. | | `--check-urls` | HEAD-check every source URL (5s timeout, graceful degradation). | | `--registry <path>` | Override default `tech-source-registry.json`. | | `--out-dir <path>` | Output directory (default: cwd). | JSON only. YAML not supported (no stdlib parser). ## Outputs Files: `cve-source-report-{service}-{YYYYMMDD}.{md,json}` in `--out-dir`. | Exit | Meaning | |---|---| | 0 | Full coverage. | | 1 | Gaps (unmapped components or unmonitored sources). | | 2 | Unreachable source URL (only with `--check-urls`). | | 3 | Input error (missing/malformed registry or inventory). | ## Workflow ### Phase 1: LOAD 1. Locate `tech-source-registry.json` (next to SKILL.md by default, or `--registry`). 2. Build inventory from `--inventory` (JSON list or `{components: [...]}`) or `--inline` (comma-split `name@version`). 3. If `--current-sources` provided, read URLs and normalize for case-insensitive comparison. **Gate**: at least one component present. Empty inventory -> exit 3. ### Phase 2: MAP & VERIFY 1. Look up each component `name` (and aliases) in the registry. - Found -> `mapped`, attach source list. Missing -> `unmapped`, sources `[]`. 2. If current sources loaded, mark each source `monitored: true` when its normalized URL appears. 3. If `--check-urls`: HEAD-check each unique URL. Treat 200/301/302/403/405 as reachable. 4xx (except 403/405) and 5xx -> `reachable: false`. Timeout/DNS/TLS failure -> `reachable: null` (WARN, does not affect exit code). 5s timeout per URL, cached per run. **Gate**: every component has status; every source has `monitored` and `reachable` fields. ### Phase 3: REPORT 1. Compute summary: components, mapped/unmapped, monitored, coverage %, gaps, unreachable. 2. Write JSON report with per-component status and per-source `monitored`/`reachable` fields. 3. Write Markdown report: summary table, components table (markers), gaps section (when gaps exist), unmapped section (when unmapped exist). 4. Print one-screen summary to stdout. Set exit code per table above. **Gate**: both files written, summary printed. ## Registry Schema `tech-source-registry.json` shape: ```json { "$schema_version": "1.0", "kinds": ["advisory-list", "github-security", "mailing-list", "distro-tracker", "vendor-page", "mitre"], "priorities": ["primary", "secondary"], "technologies": [ {"name": "postgres", "aliases": ["postgresql","pg"], "type": "container", "sources": [{"url": "https://...", "kind": "advisory-list", "priority": "primary"}]} ] } ``` Each technology: `name` (lowercase, unique), `aliases` (list), `type` (`runtime`/`base-image`/`container`/`library`), `sources` (1-3, at least one `primary`). To add a technology: pick canonical name, list aliases, add 1-3 sources (lead with vendor advisory page), re-run against a sample inventory. ## Error Handling | Error | Cause | Fix | |---|---|---| | Failed to load registry | Missing or malformed JSON | Validate with `python3 -m json.tool` | | Failed to load inventory | Missing, malformed, or wrong shape | Validate JSON; must be list or `{components: [...]}` | | Inventory empty | No usable components | Each entry needs `name`. Inline needs non-empty tokens. | | Coverage stuck at 0% | `--current-sources` URLs don't match registry | Copy URLs from registry. Scheme/host case and trailing slash are normalized; rest must match. | | Many `[--]` entries with `--check-urls` | Network issues | Re-run without `--check-urls`. Network errors don't affect gap exit code. | -
tech-source-registry.json 8.6 KB
{ "$schema_version": "1.0", "description": "Maps technologies to authoritative CVE/security feeds. See references/registry-schema.md to extend.", "kinds": ["advisory-list", "github-security", "mailing-list", "distro-tracker", "vendor-page", "mitre"], "priorities": ["primary", "secondary"], "technologies": [ { "name": "go", "aliases": ["golang", "go-lang"], "type": "runtime", "sources": [ {"url": "https://pkg.go.dev/vuln/list", "kind": "advisory-list", "priority": "primary"}, {"url": "https://groups.google.com/g/golang-announce", "kind": "mailing-list", "priority": "primary"}, {"url": "https://github.com/golang/go/security/advisories", "kind": "github-security", "priority": "secondary"} ] }, { "name": "python", "aliases": ["python3", "cpython"], "type": "runtime", "sources": [ {"url": "https://discuss.python.org/c/announcements/security-announcements/47", "kind": "advisory-list", "priority": "primary"}, {"url": "https://github.com/python/cpython/security/advisories", "kind": "github-security", "priority": "primary"}, {"url": "https://osv.dev/list?q=&ecosystem=PyPI", "kind": "advisory-list", "priority": "secondary"} ] }, { "name": "node", "aliases": ["nodejs", "node.js"], "type": "runtime", "sources": [ {"url": "https://nodejs.org/en/blog/vulnerability/", "kind": "advisory-list", "priority": "primary"}, {"url": "https://github.com/nodejs/node/security/advisories", "kind": "github-security", "priority": "primary"}, {"url": "https://github.com/advisories?query=ecosystem%3Anpm", "kind": "github-security", "priority": "secondary"} ] }, { "name": "java", "aliases": ["openjdk", "jdk", "jre"], "type": "runtime", "sources": [ {"url": "https://www.oracle.com/security-alerts/", "kind": "advisory-list", "priority": "primary"}, {"url": "https://openjdk.org/groups/vulnerability.html", "kind": "vendor-page", "priority": "primary"}, {"url": "https://github.com/advisories?query=ecosystem%3Amaven", "kind": "github-security", "priority": "secondary"} ] }, { "name": "alpine", "aliases": ["alpine-linux"], "type": "base-image", "sources": [ {"url": "https://security.alpinelinux.org/", "kind": "distro-tracker", "priority": "primary"}, {"url": "https://lists.alpinelinux.org/~alpine/security-announce/", "kind": "mailing-list", "priority": "secondary"} ] }, { "name": "debian", "aliases": ["debian-linux"], "type": "base-image", "sources": [ {"url": "https://security-tracker.debian.org/tracker/", "kind": "distro-tracker", "priority": "primary"}, {"url": "https://lists.debian.org/debian-security-announce/", "kind": "mailing-list", "priority": "primary"} ] }, { "name": "ubuntu", "aliases": ["ubuntu-linux"], "type": "base-image", "sources": [ {"url": "https://ubuntu.com/security/notices", "kind": "advisory-list", "priority": "primary"}, {"url": "https://ubuntu.com/security/cves", "kind": "distro-tracker", "priority": "primary"}, {"url": "https://lists.ubuntu.com/archives/ubuntu-security-announce/", "kind": "mailing-list", "priority": "secondary"} ] }, { "name": "postgres", "aliases": ["postgresql", "pg"], "type": "container", "sources": [ {"url": "https://www.postgresql.org/support/security/", "kind": "advisory-list", "priority": "primary"}, {"url": "https://www.postgresql.org/list/pgsql-announce/", "kind": "mailing-list", "priority": "secondary"} ] }, { "name": "redis", "aliases": ["redis-server"], "type": "container", "sources": [ {"url": "https://github.com/redis/redis/security/advisories", "kind": "github-security", "priority": "primary"}, {"url": "https://redis.io/blog/", "kind": "vendor-page", "priority": "secondary"} ] }, { "name": "mysql", "aliases": ["mariadb"], "type": "container", "sources": [ {"url": "https://www.oracle.com/security-alerts/", "kind": "advisory-list", "priority": "primary"}, {"url": "https://mariadb.org/about/security-policy/", "kind": "vendor-page", "priority": "secondary"} ] }, { "name": "opensearch", "aliases": ["opensearch-project"], "type": "container", "sources": [ {"url": "https://github.com/opensearch-project/OpenSearch/security/advisories", "kind": "github-security", "priority": "primary"}, {"url": "https://opensearch.org/blog/", "kind": "vendor-page", "priority": "secondary"} ] }, { "name": "elasticsearch", "aliases": ["elastic", "es"], "type": "container", "sources": [ {"url": "https://www.elastic.co/community/security", "kind": "advisory-list", "priority": "primary"}, {"url": "https://discuss.elastic.co/c/announcements/security-announcements/31", "kind": "mailing-list", "priority": "secondary"} ] }, { "name": "rabbitmq", "aliases": ["rabbit", "amqp"], "type": "container", "sources": [ {"url": "https://github.com/rabbitmq/rabbitmq-server/security/advisories", "kind": "github-security", "priority": "primary"}, {"url": "https://www.rabbitmq.com/release-information.html", "kind": "vendor-page", "priority": "secondary"} ] }, { "name": "kafka", "aliases": ["apache-kafka"], "type": "container", "sources": [ {"url": "https://kafka.apache.org/cve-list", "kind": "advisory-list", "priority": "primary"}, {"url": "https://lists.apache.org/list.html?announce@apache.org", "kind": "mailing-list", "priority": "secondary"} ] }, { "name": "nginx", "aliases": ["nginx-server"], "type": "container", "sources": [ {"url": "https://nginx.org/en/security_advisories.html", "kind": "advisory-list", "priority": "primary"}, {"url": "https://mailman.nginx.org/mailman3/lists/nginx-announce.nginx.org/", "kind": "mailing-list", "priority": "secondary"} ] }, { "name": "apache", "aliases": ["httpd", "apache-httpd"], "type": "container", "sources": [ {"url": "https://httpd.apache.org/security/vulnerabilities_24.html", "kind": "advisory-list", "priority": "primary"}, {"url": "https://lists.apache.org/list.html?announce@httpd.apache.org", "kind": "mailing-list", "priority": "secondary"} ] }, { "name": "logstash", "aliases": [], "type": "container", "sources": [ {"url": "https://www.elastic.co/community/security", "kind": "advisory-list", "priority": "primary"}, {"url": "https://github.com/elastic/logstash/security/advisories", "kind": "github-security", "priority": "secondary"} ] }, { "name": "prometheus", "aliases": ["prom"], "type": "container", "sources": [ {"url": "https://github.com/prometheus/prometheus/security/advisories", "kind": "github-security", "priority": "primary"}, {"url": "https://prometheus.io/docs/operating/security/", "kind": "vendor-page", "priority": "secondary"} ] }, { "name": "grafana", "aliases": [], "type": "container", "sources": [ {"url": "https://grafana.com/security/security-advisories/", "kind": "advisory-list", "priority": "primary"}, {"url": "https://github.com/grafana/grafana/security/advisories", "kind": "github-security", "priority": "secondary"} ] }, { "name": "memcached", "aliases": [], "type": "container", "sources": [ {"url": "https://github.com/memcached/memcached/wiki/ReleaseNotes", "kind": "vendor-page", "priority": "primary"}, {"url": "https://github.com/memcached/memcached/security/advisories", "kind": "github-security", "priority": "secondary"} ] }, { "name": "haproxy", "aliases": [], "type": "container", "sources": [ {"url": "https://www.haproxy.org/#vuln", "kind": "advisory-list", "priority": "primary"}, {"url": "https://github.com/haproxy/haproxy/security/advisories", "kind": "github-security", "priority": "secondary"} ] }, { "name": "openssl", "aliases": ["libssl"], "type": "library", "sources": [ {"url": "https://www.openssl.org/news/vulnerabilities.html", "kind": "advisory-list", "priority": "primary"}, {"url": "https://mta.openssl.org/pipermail/openssl-announce/", "kind": "mailing-list", "priority": "secondary"} ] } ] }
Comments (0)
Sign in to join the conversation.
Reviews (0)
No reviews yet.
No comments yet.