diff --git a/support/redhat-support/SKILL.md b/support/redhat-support/SKILL.md new file mode 100644 index 0000000..6c4a3bf --- /dev/null +++ b/support/redhat-support/SKILL.md @@ -0,0 +1,209 @@ +--- +name: redhat-support +description: Query Red Hat security data — look up CVEs, check which Red Hat products are affected by a vulnerability, and find the advisory (RHSA) that fixes a given CVE. Use when validating a CVE ID, assessing whether a CVE affects a specific Red Hat product or package, or correlating a CVE with the Red Hat advisory that resolves it. +--- + +# Red Hat Security Data + +Query the Red Hat Security Data API to retrieve CVE details, affected-product state, and the advisories (RHSAs) that address each CVE. This is the source of record for validating that a CVE ID exists and for understanding how Red Hat has classified and addressed it. + +## API Overview + +- **Base URL**: `https://access.redhat.com/hydra/rest/securitydata` +- **Authentication**: None required — the endpoints used here are public. +- **Two shapes**: + - **Single CVE detail**: `GET /cve/.json` + - **CVE search**: `GET /cve.json` with filter parameters (`package`, `advisory`, `severity`, `after`, `before`, `cwe`, `per_page`) + +The single-CVE endpoint returns the full vulnerability record (severity, CVSS, affected products, fix state, references). The search endpoint returns a compact list — use it to enumerate, then drill into individual CVEs with the single-detail endpoint when needed. + +## Quick Start + +```bash +# Single CVE lookup +curl -s "https://access.redhat.com/hydra/rest/securitydata/cve/CVE-2024-3094.json" | jq . + +# Find CVEs affecting a package +curl -s "https://access.redhat.com/hydra/rest/securitydata/cve.json?package=openssh&per_page=10" | jq . + +# Find CVEs included in a specific advisory +curl -s "https://access.redhat.com/hydra/rest/securitydata/cve.json?advisory=RHSA-2024:1614&per_page=20" | jq '.[].CVE' +``` + +## Response Structure + +### Single CVE detail (`/cve/.json`) + +```json +{ + "threat_severity": "Critical", + "public_date": "2024-03-29T00:00:00Z", + "bugzilla": { "id": "2272210", "url": "...", "description": "..." }, + "cvss3": { + "cvss3_base_score": "10.0", + "cvss3_scoring_vector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H", + "status": "draft" + }, + "cwe": "CWE-506", + "details": ["..."], + "statement": "...", + "package_state": [ + { + "product_name": "Red Hat Enterprise Linux 9", + "package_name": "xz", + "fix_state": "Not affected", + "cpe": "cpe:/o:redhat:enterprise_linux:9" + } + ], + "affected_release": [ + { + "product_name": "Red Hat Enterprise Linux 8", + "release_date": "2024-04-02T00:00:00Z", + "advisory": "RHSA-2024:1718", + "cpe": "cpe:/o:redhat:enterprise_linux:8", + "package": "openssh-0:8.0p1-19.el8_9" + } + ], + "references": ["..."] +} +``` + +The key fields for agent reasoning: + +- `threat_severity` — Red Hat's classification (`Critical`, `Important`, `Moderate`, `Low`) +- `package_state[]` — per-product status when there is **no released fix yet** (`Affected`, `Not affected`, `Will not fix`, `Under investigation`, `Out of support scope`) +- `affected_release[]` — per-product fix metadata when an advisory **has shipped** (includes the `advisory` ID and the fixed `package` NVR) +- `references[]` — links to NVD, CVE.org, blog posts, and KB articles + +A given product appears in either `package_state` *or* `affected_release` for a given CVE — not both. If a product is in `affected_release`, the CVE is fixed there. + +### CVE search list (`/cve.json`) + +Each entry is a compact summary: + +```json +{ + "CVE": "CVE-2026-35414", + "severity": "moderate", + "public_date": "2026-04-02T17:08:15Z", + "advisories": ["RHSA-2026:16059", "RHSA-2026:13383"], + "bugzilla": "2454490", + "bugzilla_description": "...", + "cvss3_score": "4.8", + "cvss3_scoring_vector": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:N", + "CWE": "CWE-168", + "affected_packages": ["openssh-0:9.9p1-14.el10_1", "..."], + "resource_url": "https://access.redhat.com/hydra/rest/securitydata/cve/CVE-2026-35414.json" +} +``` + +`resource_url` is the single-CVE-detail endpoint for that entry — follow it for full data. + +For full field descriptions, supported filter parameters, and pagination rules, see `references/security-data-api.md`. + +## Common Queries + +### Validate that a CVE ID exists and is real + +```bash +CVE="CVE-2024-3094" +curl -fsS "https://access.redhat.com/hydra/rest/securitydata/cve/$CVE.json" \ + > /dev/null && echo "valid" || echo "not found" +``` + +A 404 here means Red Hat has no record of the CVE — treat it as not a real Red Hat-tracked CVE. (NVD may still have it; this endpoint reflects Red Hat's view only.) + +### Get severity, CVSS, and one-line description for a CVE + +```bash +CVE="CVE-2024-3094" +curl -s "https://access.redhat.com/hydra/rest/securitydata/cve/$CVE.json" \ + | jq -r ' + "Severity: \(.threat_severity)", + "CVSS3: \(.cvss3.cvss3_base_score) (\(.cvss3.cvss3_scoring_vector))", + "Bugzilla: \(.bugzilla.description)"' +``` + +### Check whether a CVE affects a specific Red Hat product + +```bash +CVE="CVE-2024-3094" +PRODUCT="Red Hat Enterprise Linux 9" + +curl -s "https://access.redhat.com/hydra/rest/securitydata/cve/$CVE.json" \ + | jq -r --arg p "$PRODUCT" ' + (.package_state // []) as $ps | + (.affected_release // []) as $ar | + ([$ps[] | select(.product_name == $p)] + [$ar[] | select(.product_name == $p)]) as $hits | + if ($hits | length) == 0 then "\($p): not listed for this CVE" + else $hits[] | + if .advisory then "\($p): fixed in \(.advisory) (\(.package))" + else "\($p): \(.fix_state) (package: \(.package_name))" + end + end' +``` + +### Find the Red Hat advisory (RHSA) that fixes a CVE for a given product + +```bash +CVE="CVE-2024-1086" +PRODUCT="Red Hat Enterprise Linux 9" + +# Exact match — RHEL 9 proper only, excludes EUS / E4S / AUS variants +curl -s "https://access.redhat.com/hydra/rest/securitydata/cve/$CVE.json" \ + | jq -r --arg p "$PRODUCT" ' + [(.affected_release // [])[] | select(.product_name == $p)] | unique_by(.advisory)[] | + "\(.product_name): \(.advisory) (\(.release_date[:10]))"' +``` + +A single `(product_name, advisory)` pair can appear multiple times in `affected_release` (typically one per architecture or sub-package); `unique_by(.advisory)` collapses these. + +To include EUS / Extended Update Support / Advanced Update Support variants too, broaden the filter: + +```bash +# Family match — includes RHEL 9 proper AND its EUS/AUS/E4S variants +curl -s "https://access.redhat.com/hydra/rest/securitydata/cve/$CVE.json" \ + | jq -r --arg p "$PRODUCT" ' + [(.affected_release // [])[] | select(.product_name | startswith($p))] | unique_by([.product_name, .advisory])[] | + "\(.product_name): \(.advisory) (\(.release_date[:10]))"' +``` + +Be explicit about which one the user wants — `startswith` will match `"Red Hat Enterprise Linux 9.0 Extended Update Support"`, `"...9.2 Extended Update Support"`, etc., not just RHEL 9 proper. + +### List recent CVEs affecting a package + +```bash +PACKAGE="openssh" +curl -s "https://access.redhat.com/hydra/rest/securitydata/cve.json?package=$PACKAGE&per_page=20" \ + | jq -r '.[] | "\(.CVE) \(.severity) \(.public_date[:10]) — \(.bugzilla_description)"' +``` + +### List all CVEs included in an advisory + +```bash +ADVISORY="RHSA-2024:1614" +curl -s "https://access.redhat.com/hydra/rest/securitydata/cve.json?advisory=$ADVISORY&per_page=100" \ + | jq -r '.[].CVE' +``` + +### Filter by severity and date + +```bash +# Critical CVEs disclosed since the start of 2026, affecting OpenShift +curl -s "https://access.redhat.com/hydra/rest/securitydata/cve.json?severity=critical&after=2026-01-01&package=openshift&per_page=50" \ + | jq -r '.[] | "\(.CVE) \(.public_date[:10]) — \(.bugzilla_description)"' +``` + +## Cross-reference with other skills + +- **`update-advisor`** — Use this skill to validate any CVE IDs `update-advisor` cites in its risk report. Never repeat a CVE ID the agent hasn't checked against `/cve/.json`. +- **`product-lifecycle`** — When a CVE's `affected_release` lists a product, use `product-lifecycle` to confirm the product is still in a support phase that receives the advisory. + +## Important + +- **The `/cve/.json` endpoint is the source of truth for whether a CVE is recognized by Red Hat.** If it returns 404, do not assume the CVE applies to any Red Hat product — even if NVD or cve.org has an entry. +- **`package_state` and `affected_release` are mutually exclusive per product per CVE.** A product is in `package_state` when no fix has shipped (whatever the reason), and in `affected_release` once an advisory has shipped a fixed package. +- **`fix_state: "Will not fix"`, `"Out of support scope"`, and `"Affected"` are not all the same.** "Will not fix" is a deliberate decision; "Out of support scope" means the product version is past its support window; "Affected" means a fix is planned but not yet shipped. +- **Use `?per_page=` on search endpoints.** Default page size is small and the result set can be large; cap to what's needed. +- **`/cvrf/`, `/csaf/`, and direct advisory-detail endpoints are not available on this public API.** To get advisory contents, follow the public web URL at `https://access.redhat.com/errata/` — but those pages are HTML, not JSON, and not appropriate to scrape from this skill. If full advisory contents are needed, surface the URL to the user. +- **Do not fabricate CVE IDs, RHSA IDs, or CVSS scores.** Only report values returned by these endpoints. diff --git a/support/redhat-support/references/security-data-api.md b/support/redhat-support/references/security-data-api.md new file mode 100644 index 0000000..ddf4dd8 --- /dev/null +++ b/support/redhat-support/references/security-data-api.md @@ -0,0 +1,145 @@ +# Red Hat Security Data API Reference + +## Endpoints + +| Endpoint | Method | Purpose | +|---|---|---| +| `GET /hydra/rest/securitydata/cve/.json` | GET | Full detail for a single CVE | +| `GET /hydra/rest/securitydata/cve.json` | GET | Search/list CVEs with filters | + +Base host: `https://access.redhat.com` + +No authentication required. + +## Search Filter Parameters (`/cve.json`) + +| Parameter | Type | Description | +|---|---|---| +| `package` | string | Affects-package filter — substring match against `affected_packages` | +| `advisory` | string | Return CVEs included in the given advisory (e.g. `RHSA-2024:1614`) | +| `severity` | string | One of `low`, `moderate`, `important`, `critical` | +| `after` | date | ISO 8601 — only CVEs with `public_date` on/after | +| `before` | date | ISO 8601 — only CVEs with `public_date` on/before | +| `cwe` | string | CWE ID (e.g. `CWE-168`) | +| `bug` | string | Bugzilla ID | +| `per_page` | int | Page size (default is small; cap to what's actually needed) | +| `page` | int | 1-indexed page number | + +Filters combine with AND. The endpoint returns a JSON array — empty `[]` when nothing matches. + +## Single-CVE Detail Schema (`/cve/.json`) + +| Field | Type | Description | +|---|---|---| +| `name` | string | CVE ID (echoes the path component) | +| `threat_severity` | string | `Critical` \| `Important` \| `Moderate` \| `Low` | +| `public_date` | string | ISO 8601 | +| `bugzilla` | object | `{ id, url, description }` | +| `cvss` | object | CVSS v2 (legacy; may be absent). When present: `{ cvss_base_score, cvss_scoring_vector, status }` | +| `cvss3` | object | CVSS v3. When present: `{ cvss3_base_score, cvss3_scoring_vector, status }` | + +### `cvss3` sub-fields + +| Field | Type | Description | +|---|---|---| +| `cvss3_base_score` | string | CVSS v3 base score as a decimal string (e.g. `"10.0"`) | +| `cvss3_scoring_vector` | string | CVSS v3 vector (e.g. `"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H"`) | +| `status` | string | `draft` \| `verified` | + +| `cwe` | string | CWE ID, dash-prefixed | +| `details` | string[] | Multi-paragraph narrative description | +| `statement` | string | Red Hat's contextual statement (may be empty) | +| `acknowledgement` | string | Reporter credit | +| `mitigation` | object | `{ value, lang }` when present | +| `package_state` | object[] | Products with no released fix — see below | +| `affected_release` | object[] | Products where a fix has shipped — see below | +| `references` | string[] | External URLs (NVD, CVE.org, blog posts, KBs) | +| `upstream_fix` | string | Upstream version where the issue is fixed | + +### `package_state[]` — pre-fix state + +Per-product entries that describe how a CVE applies to a product **before** an advisory has shipped a fix. + +| Field | Type | Description | +|---|---|---| +| `product_name` | string | Red Hat product name | +| `package_name` | string | Package within the product | +| `cpe` | string | CPE identifier | +| `fix_state` | string | See enumeration below | + +`fix_state` values: + +| Value | Meaning | +|---|---| +| `Affected` | Product is vulnerable; a fix is planned | +| `Not affected` | Product does not ship the vulnerable code path | +| `Will not fix` | Deliberate decision not to ship a fix (typically older releases) | +| `Out of support scope` | Product version is past its support window | +| `Under investigation` | Red Hat has not finished triage | +| `Fix deferred` | Acknowledged but de-prioritized | + +### `affected_release[]` — post-fix state + +Per-product entries for releases that **have** shipped a fix. + +| Field | Type | Description | +|---|---|---| +| `product_name` | string | Red Hat product name | +| `release_date` | string | ISO 8601 advisory release date | +| `advisory` | string | RHSA / RHBA / RHEA ID (e.g. `RHSA-2024:1718`) | +| `cpe` | string | CPE identifier | +| `package` | string | Fixed package NVR (name-version-release) | + +A product appears in **either** `package_state` or `affected_release` for a given CVE, not both. + +The same `(product_name, advisory)` pair can appear multiple times in `affected_release` — typically once per architecture or sub-package. Use `unique_by(.advisory)` or `unique_by([.product_name, .advisory])` when listing or counting. + +Product names also share base prefixes across support tiers. `"Red Hat Enterprise Linux 9"` (the base product), `"Red Hat Enterprise Linux 9.0 Extended Update Support"`, `"Red Hat Enterprise Linux 9.2 Extended Update Support"`, etc., are distinct entries. Use exact `==` match when targeting the base product only; use `startswith` only when the caller wants the whole family including EUS / AUS / E4S. + +## Search List Schema (`/cve.json`) + +Compact summary per CVE. Drill into `resource_url` for full data. + +| Field | Type | Description | +|---|---|---| +| `CVE` | string | CVE ID | +| `severity` | string | Lowercase — `low` \| `moderate` \| `important` \| `critical` | +| `public_date` | string | ISO 8601 | +| `advisories` | string[] | All RHSAs that include this CVE (may be empty) | +| `bugzilla` | string | Bugzilla ID | +| `bugzilla_description` | string | Short summary | +| `CWE` | string | CWE ID | +| `cvss_score` | string\|null | CVSS v2 base score | +| `cvss_scoring_vector` | string\|null | CVSS v2 vector | +| `cvss3_score` | string\|null | CVSS v3 base score | +| `cvss3_scoring_vector` | string\|null | CVSS v3 vector | +| `affected_packages` | string[] | Fixed-package NVRs across all advisories | +| `package_state` | object[]\|null | Same shape as the single-detail endpoint when present | +| `resource_url` | string | Single-detail endpoint for this CVE | + +Note: `severity` is lowercase in search results and capitalized in single-detail responses. The values are the same; the casing differs. + +## What this API does **not** expose + +These shapes are referenced elsewhere on access.redhat.com but are not available on this public endpoint: + +| Wanted | Status | Workaround | +|---|---|---| +| Advisory (RHSA) body / errata text | Not on this API | Construct the public URL `https://access.redhat.com/errata/` and surface it to the user — HTML, not JSON | +| CVRF / CSAF documents | Not on this API at the paths probed | None — surface the advisory URL | +| KB solutions (`/solutions/`) | Authenticated, not part of the security data API | Out of scope for this skill | +| Bugzilla bug detail beyond the ID and summary | Separate Bugzilla API (`bugzilla.redhat.com`) | Outside the scope of this skill | + +If a use case requires advisory contents, surface the public URL to the user rather than trying to fetch it via this API. + +## Pagination and rate limits + +- The endpoint does not return total counts in headers. To know if there are more results, request `per_page + 1` and check whether the extra entry came back. +- No documented public rate limit, but batch where possible — prefer one search call with `per_page=N` over `N` single-detail calls when only summary data is needed. + +## Search Tips + +1. **Validate first, then fetch.** A 404 from `/cve/.json` is the definitive "Red Hat does not track this CVE." Use it before doing any other work with a CVE ID. +2. **Use `?advisory=` to enumerate.** Given an RHSA, listing its CVEs via search is the fastest correlation. +3. **`?package=` is a substring match.** `openssh` matches both `openssh` and `openssh-clients`. Combine with `?severity=` and `?after=` to narrow. +4. **Search returns the lighter shape.** If you need `affected_release` or `package_state` detail, the `resource_url` on each search hit points to the single-detail endpoint.