---
name: github-advisory-database-ingestion
description: "How to get GitHub Advisory Database data into a pandas DataFrame and Parquet: access, the request, the format, limits, quirks and terms."
---

# Load a recently changed GitHub advisory into pandas and Parquet

Source entry: https://signal-lab-jet.vercel.app/datasets/github-advisory-database
Provider: https://github.com/github/advisory-database
Checked against the provider's documentation: 2026-11-04

## Access
- No account is needed to clone the public repository.
- This small check uses GitHub's unauthenticated API; use git for bulk ingestion.

## Request
```bash
git clone --filter=blob:none https://github.com/github/advisory-database.git
```

## Format
One OSV JSON file per advisory with ID, dates, aliases, affected packages and ranges, references, severity and review metadata.

## Load into pandas and Parquet
Needs Python 3 with requests, pandas and pyarrow.
```python
"""One recently changed GitHub advisory -> pandas -> Parquet. No key."""
import requests
import pandas as pd

API = "https://api.github.com/repos/github/advisory-database"
headers = {"Accept": "application/vnd.github+json", "User-Agent": "signal-lab-catalog-check"}
commits = requests.get(f"{API}/commits", params={"path": "advisories", "per_page": 10}, headers=headers, timeout=60)
commits.raise_for_status()
advisory = None
for commit in commits.json():
    detail = requests.get(f"{API}/commits/{commit['sha']}", headers=headers, timeout=60)
    detail.raise_for_status()
    files = [f for f in detail.json().get("files", []) if f["filename"].startswith("advisories/") and f["filename"].endswith(".json") and f.get("raw_url")]
    if files:
        data = requests.get(files[0]["raw_url"], headers=headers, timeout=60)
        data.raise_for_status()
        advisory = data.json()
        break
if advisory is None:
    raise RuntimeError("No changed advisory found")
row = {"id": advisory["id"], "published": advisory.get("published"), "modified": advisory.get("modified"), "summary": advisory.get("summary"), "aliases": ";".join(advisory.get("aliases", []))}
pd.DataFrame([row]).to_parquet("github_advisory_sample.parquet", index=False)
ecosystems = sorted({a.get("package", {}).get("ecosystem", "") for a in advisory.get("affected", [])})
print(advisory["id"], "modified", advisory.get("modified"), "ecosystems", ",".join(ecosystems))
```
Run by us on 2026-11-04 (python 3.13.5 | pandas 3.1.0 | pyarrow 26.0.0 | requests 2.34.2). Result: GHSA-7g64-f2hm-vjxp modified 2026-11-04T17:49:18Z ecosystems Maven

## Limits
- Repository download limits: Not stated.
- The unauthenticated REST API has a separate IP-based limit.

## Quirks
- Reviewed and unreviewed advisories use separate directories.
- database_specific fields can change without notice.
- Later commits can correct records.

## Terms and attribution
- The database is CC BY 4.0.
- Give attribution, link the licence and indicate changes.
- Terms page: https://raw.githubusercontent.com/github/advisory-database/main/LICENSE.md

## Sources
- https://github.com/github/advisory-database: "All advisories acknowledged by GitHub are stored as individual files in this repository. They are formatted in the Open Source Vulnerability (OSV) format."
- https://raw.githubusercontent.com/github/advisory-database/main/README.md: "This project is licensed under the terms of the CC-BY 4.0 open source license."

## Help improve this skill
Missing a source, or see something to improve? Call the MCP tool suggest_source or feedback (or POST /api/suggest or /api/feedback). Reviewed ideas: https://signal-lab-jet.vercel.app/agent-suggestions

Information for educational purposes only. Free tiers, limits and licenses belong to the providers and may change; check the provider's own terms before using the data.
