# GitHub Security Advisories Scraper - GHSA CVE Data (`ninhothedev/github-advisories-scraper`) Actor

$1/1K 🔥 Scrape the GitHub Advisory Database (GHSA): vulnerabilities with affected packages, ecosystem-specific vulnerable version ranges, first patched version, CVSS, EPSS and CWE. One row per affected package. No API key required.

- **URL**: https://apify.com/ninhothedev/github-advisories-scraper.md
- **Developed by:** [ninhothedev](https://apify.com/ninhothedev) (community)
- **Categories:** Developer tools, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.00 / 1,000 results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## GitHub Security Advisories Scraper (GHSA) — Vulnerable Package Version Ranges

Scrape the **GitHub Advisory Database (GHSA)** into a clean, flat dataset: every vulnerability with its **affected packages**, the **exact vulnerable version range**, the **first patched version**, CVSS, EPSS, CWE and references — as JSON, CSV or Excel.

No API key required. No login. No proxy needed.

> **The point of this actor:** a CVE feed tells you *that* something is vulnerable. GHSA tells you **which package, in which ecosystem, in which version range, and what to upgrade to.** That is the data you actually need to fix things.

***

### Why this actor exists (and how it differs from CVE feeds)

Generic CVE feeds (NVD, CIRCL, CPE dictionaries) describe vulnerabilities in **CPE strings** — vendor/product/version tuples designed for enterprise asset inventories. They are close to useless for a modern dependency file, because `cpe:2.3:a:lodash:lodash:4.17.15` does not tell your resolver that `< 4.17.21` is vulnerable and `4.17.21` is the fix.

The GitHub Advisory Database is **package-manager native**. Every advisory carries a machine-readable list of affected packages with:

- `ecosystem` — npm, pip, Maven, NuGet, Composer, Go, RubyGems, Rust, GitHub Actions, …
- `package_name` — the exact registry name (`lodash`, `django`, `org.bouncycastle:bcprov-jdk18on`)
- `vulnerable_version_range` — e.g. `>= 1.59, <= 1.80.1` or `< 2.0.2`
- `first_patched_version` — e.g. `1.80.2` (null when no fix exists yet)
- `vulnerable_functions` — reachable-symbol data where GitHub has it

**How this differs from the sibling actors:**

| Actor | What it gives you |
|---|---|
| **github-advisories-scraper** (this one) | GHSA advisories with **ecosystem-specific vulnerable version ranges** and patched versions, per package |
| [circl-cve-scraper](https://apify.com/ninhothedev/circl-cve-scraper) | Classic CVE records (CVSS, descriptions, references) from the CIRCL CVE database |
| [nist-cpe-scraper](https://apify.com/ninhothedev/nist-cpe-scraper) | NIST CPE dictionary — vendor/product/version identifiers, not package ranges |

Use the CVE actors for vulnerability *identity* and enterprise asset matching. Use this one when you need to know **which dependency to bump**.

***

### One row per (advisory × affected package)

This is the key design decision, and the reason the output is immediately usable in a spreadsheet.

One GHSA advisory can affect **many** packages — a BouncyCastle advisory in our test run affected **24** Maven artifacts, each with its own range. If we emitted one row per advisory, all of that would be buried in a nested array that Excel and Google Sheets flatten into unusable JSON blobs.

So the actor **flattens**: an advisory affecting 3 packages produces **3 rows**, each carrying the full advisory context (`ghsa_id`, severity, CVSS, CWE…) plus that package's own `ecosystem`, `package_name`, `vulnerable_version_range` and `first_patched_version`.

Every row also carries **`affected_package_count`**, the total number of packages the advisory affects, so you can always deduplicate back to advisory level (`GROUP BY ghsa_id`) or spot wide-blast-radius advisories.

An advisory with **zero** listed packages still produces exactly **one** row, with the package fields set to `null` — so you never silently lose an advisory.

A real example: filtering npm + critical returned **100 advisories → 225 rows**, because 23 of them affected more than one package.

***

### Use cases

- **SCA tooling** — feed vulnerable version ranges into your own software composition analysis or dependency scanner instead of paying for a commercial feed.
- **Dependency triage** — join the export against your `package-lock.json`, `requirements.txt`, `pom.xml` or `go.sum` and find out what is actually exploitable in your tree.
- **Security dashboards** — build a live view of new critical advisories per ecosystem, with CVSS and EPSS for risk scoring.
- **Patch prioritisation** — sort by `cvss_score` and `epss_percentage`, filter to rows where `first_patched_version` is not null, and you have a ranked, actionable upgrade list.

***

### Input

| Field | Type | Default | Description |
|---|---|---|---|
| `mode` | select | `advisories` | What to scrape. Currently the GHSA advisory database. |
| `ecosystem` | select | `any` | `any`, `npm`, `pip`, `rubygems`, `maven`, `nuget`, `composer`, `go`, `rust`, `actions` |
| `severity` | select | `any` | `any`, `low`, `medium`, `high`, `critical` |
| `affectsPackage` | string | — | Only advisories affecting this exact package, e.g. `lodash` |
| `advisoryType` | select | `reviewed` | `reviewed` (curated, best quality), `malware`, `unreviewed`, `any` |
| `githubToken` | string (secret) | — | Optional. Raises the rate limit from 60 to 5000 requests/hour |
| `maxItems` | integer | `200` | Max dataset rows (max 5000). Remember: rows ≠ advisories |

```json
{
  "mode": "advisories",
  "ecosystem": "npm",
  "severity": "critical",
  "advisoryType": "reviewed",
  "maxItems": 200
}
```

***

### Rate limits — read this before a big run

The advisories endpoint is **fully public**; the actor works with no credentials at all. But GitHub applies its standard API rate limit:

| Mode | Limit |
|---|---|
| **Keyless (default)** | **60 requests/hour, per IP** |
| With a `githubToken` | **5000 requests/hour** |

Each request returns up to 100 advisories, so keyless you can pull roughly **6000 advisories per hour** — plenty for most filtered runs. If you want to mirror the whole database or run on a tight schedule, create a GitHub personal access token (**no scopes required** — a bare classic token or fine-grained token with read-only public access is enough) and paste it into `githubToken`.

The actor reads the `x-ratelimit-remaining` and `x-ratelimit-reset` response headers on every page, paces itself accordingly, and if the quota runs out it **stops with a descriptive error** naming the 60/hour keyless cap and the reset time rather than looping forever. If some rows were already collected, they are kept and the run finishes with a warning instead of failing.

Pagination uses GitHub's opaque cursor exposed only through the `Link: …; rel="next"` header — there is no page or offset parameter. The actor parses that header and stops cleanly when it is absent (the last page).

***

### Output

One row per (advisory × affected package). All fields are nullable.

| Field | Description |
|---|---|
| `ghsa_id` | GitHub advisory ID, e.g. `GHSA-6wcc-39rp-hh9p` |
| `cve_id` | Linked CVE, if one was assigned |
| `summary` | Short title (capped at 500 chars) |
| `description` | Full advisory text (capped at 8000 chars) |
| `severity` | `low` / `medium` / `high` / `critical` |
| `type` | `reviewed` / `malware` / `unreviewed` |
| `cvss_score`, `cvss_vector` | Primary CVSS score and vector string |
| `cvss_v3_score`, `cvss_v4_score` | Version-specific CVSS scores |
| `epss_percentage`, `epss_percentile` | EPSS exploit-prediction values |
| `cwe_ids`, `cwe_names` | Weakness classifications |
| `ecosystem` | **This row's** package ecosystem |
| `package_name` | **This row's** package name |
| `vulnerable_version_range` | e.g. `>= 1.59, <= 1.80.1` |
| `first_patched_version` | e.g. `1.80.2`, or null if unpatched |
| `vulnerable_functions` | Affected symbols, when known |
| `affected_package_count` | Total packages affected by the advisory |
| `published_at`, `updated_at` | ISO-8601 UTC timestamps |
| `github_reviewed_at`, `nvd_published_at` | Review / NVD publication timestamps |
| `withdrawn_at`, `is_withdrawn` | Withdrawal timestamp and boolean flag |
| `reference_count`, `references` | Reference URLs (up to 10 kept) |
| `credit_logins` | GitHub logins credited for the report |
| `source_code_location` | Upstream repository URL |
| `url` | Public advisory page on github.com |
| `source` | Always `github-advisories` |
| `scraped_at` | ISO-8601 UTC scrape timestamp |

#### Sample row

```json
{
  "ghsa_id": "GHSA-574f-3g2m-x479",
  "cve_id": "CVE-2026-1000",
  "summary": "BouncyCastle vulnerability",
  "severity": "critical",
  "type": "reviewed",
  "cvss_score": 9.8,
  "cvss_vector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H",
  "cwe_ids": ["CWE-89"],
  "ecosystem": "maven",
  "package_name": "org.bouncycastle:bcprov-jdk18on",
  "vulnerable_version_range": ">= 1.59, <= 1.80.1",
  "first_patched_version": "1.80.2",
  "vulnerable_functions": ["doFinal"],
  "affected_package_count": 24,
  "published_at": "2025-11-26T09:31:21Z",
  "is_withdrawn": false,
  "url": "https://github.com/advisories/GHSA-574f-3g2m-x479",
  "source": "github-advisories"
}
```

***

### Pricing

Roughly **$0.50 per 1,000 rows** in Apify platform usage. The actor is a lightweight HTTP client on 512 MB — no browser, no proxy, no residential traffic. A typical 200-row triage run costs a fraction of a cent.

***

### Notes

- Data comes from the public GitHub Advisory Database and is licensed CC-BY-4.0 by GitHub. Attribute accordingly if you republish it.
- `advisoryType: reviewed` is the default because unreviewed advisories are auto-imported and can contain noisy or incomplete package data.
- `withdrawn` advisories are still returned (flagged via `is_withdrawn`) so you can filter them out yourself rather than having them silently disappear.

### Related actors

- [CIRCL CVE Scraper](https://apify.com/ninhothedev/circl-cve-scraper) — classic CVE records with CVSS and references
- [NIST CPE Scraper](https://apify.com/ninhothedev/nist-cpe-scraper) — official CPE product dictionary
- [OpenSSF Scorecard Scraper](https://apify.com/ninhothedev/openssf-scorecard-scraper) — supply-chain security scores for repositories
- [Software EOL Scraper](https://apify.com/ninhothedev/software-eol-scraper) — end-of-life and support windows for software versions

# Actor input Schema

## `mode` (type: `string`):

What to scrape. Currently the actor supports one mode: 'advisories' reads the public GitHub Advisory Database (GHSA) and returns one row per affected package.

## `ecosystem` (type: `string`):

Only return advisories affecting packages of this ecosystem. Choose 'any' to cover all ecosystems at once. Note that one advisory can affect packages in several ecosystems.

## `severity` (type: `string`):

Only return advisories with this GitHub severity rating. Use 'any' to get every severity, or 'critical' to build a patch-prioritisation shortlist.

## `affectsPackage` (type: `string`):

Return only advisories affecting this exact package name, for example 'lodash', 'django' or 'org.bouncycastle:bcprov-jdk18on'. Leave empty to scrape the whole database. Must match the package name used by the ecosystem's registry.

## `advisoryType` (type: `string`):

'reviewed' = curated advisories reviewed by GitHub (recommended, best data quality). 'malware' = malicious package advisories. 'unreviewed' = automatically imported, not yet reviewed. 'any' returns all three.

## `githubToken` (type: `string`):

Optional GitHub personal access token. The advisories endpoint is public, so the actor works without one, but unauthenticated requests are limited to 60 requests per hour per IP. A token (no scopes needed) raises that limit to 5000 requests per hour, which is required for large runs.

## `maxItems` (type: `integer`):

Maximum number of dataset rows to return. Remember that one advisory can produce several rows (one per affected package), so 200 rows is roughly 100-150 advisories.

## Actor input object example

```json
{
  "mode": "advisories",
  "ecosystem": "any",
  "severity": "any",
  "affectsPackage": "lodash",
  "advisoryType": "reviewed",
  "maxItems": 200
}
```

# Actor output Schema

## `advisories` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {};

// Run the Actor and wait for it to finish
const run = await client.actor("ninhothedev/github-advisories-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {}

# Run the Actor and wait for it to finish
run = client.actor("ninhothedev/github-advisories-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{}' |
apify call ninhothedev/github-advisories-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,ninhothedev/github-advisories-scraper"
        }
    }
}

```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/QdyjUsJVgEtC9H8bC/builds/4kHxfW3t9cQxYxFQL/openapi.json
