The critical advisory your scanner can't see — find it in one CI step
A maintainer can publish a security advisory on their own GitHub repository today. Your scanner may never hear about it. Dependabot, npm audit, pip-audit and osv-scanner all read the global feed: GitHub's Advisory Datab
A maintainer can publish a security advisory on their own GitHub repository today. Your scanner may never hear about it.
Dependabot, npm audit, pip-audit and osv-scanner all read the global feed: GitHub's Advisory Database and its mirror, OSV.dev. A repository security advisory ("GRA") only reaches you once GitHub's curators import it into that global database. In 2026 that pipeline is badly backed up — GitHub has said repository advisories grew from about 650 to over 5,000 a week and that review has fallen behind (GitHub blog, 2026-06-29).
I measured the gap for self-hosted AI/ML tools and published the dataset: 195 of 618 maintainer-published advisories (31.6%) are not in the global database under their own GHSA ID. Until they are, every scanner that reads the global feed is blind to them.
A real one, right now
Here is a current example you can check yourself:
-
GHSA-vcwp-f9rq-3887 — "Flowise Custom MCP npx package execution leads to authenticated server-side command execution." Critical. Affects npm
flowiseandflowise-components<= 3.1.3, patched in3.1.4. Published by the maintainers on the Flowise repo. - It has no CVE assigned.
- Ask OSV the way a scanner would:
https://api.osv.dev/v1/vulns/GHSA-vcwp-f9rq-3887→ 404 Not Found (checked 2026-10-15).
So a project pinned to [email protected] has a known, maintainer-published, critical RCE advisory against it — and a scanner reading the global feed reports nothing, because there is nothing there to report.
Find your own blind spots
blindspot.py checks this for your dependencies. For each one it maps the package to its GitHub repo, lists that repo's published advisories, keeps the ones whose affected range covers your version, and then asks OSV — with the same package and version a scanner would send — whether OSV reports it. An advisory that affects you but that OSV does not report is a blind spot.
It is standard-library-only Python, no install, public read-only metadata. The best input is a lock file, so every direct and transitive dependency is checked at its exact version:
# lock files: uv.lock, poetry.lock, pylock.toml, Pipfile.lock, package-lock.json,
# npm-shrinkwrap.json, yarn.lock, pnpm-lock.yaml, and Go's go.mod / go.sum
python blindspot.py --lock package-lock.json
python blindspot.py --lock go.mod
# or a manifest, or a single package by spec
python blindspot.py -r requirements.txt
python blindspot.py --pyproject pyproject.toml
python blindspot.py --package npm:[email protected]
python blindspot.py --package go:github.com/gin-gonic/[email protected]
Add --json for machine output and --fail-on-blind to exit non-zero when a blind spot is found. Go modules map to their repository by their own path, so no registry lookup is needed.
One step in CI
The repo is also a composite GitHub Action, so you can gate pull requests without installing anything:
permissions:
contents: read
jobs:
blindspot:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: munimtechnologies/[email protected]
with:
lock: package-lock.json # or go.mod, uv.lock, requirements: requirements.txt
fail-on-blind: "true"
Every run writes a Markdown table to the job summary — blind spots first, then the advisories OSV already reports. A weekly schedule is worth adding too: the import gap in the census had a median life of about three months, so an advisory can sit outside the global feed for a long time. Set sarif: to a path to also upload the blind spots as code scanning alerts in your repository's Security tab.
Honest limits
- OSV is the stand-in for "what a scanner sees." Dependabot and
npm auditread GitHub's database, which OSV mirrors; treat a blind spot as "your global-feed scanners probably miss this," not a guarantee about one specific tool. - Version ranges are compared with a small PEP 440 / semver parser. An unclear range is reported as "unknown," never silently dropped.
- It needs the package to resolve to a GitHub repo (registry metadata, a small built-in map, a Go module's own path, or
--map NAME=OWNER/REPO); packages it can't map are listed, not hidden. - It is measurement, not disclosure: it only reads advisories the maintainers already published.
As far as I can find, no existing scanner does this — reading repository advisories was requested in Dependency-Track in June 2025 and is still open.
Code (Apache-2.0) and the 618-row dataset (CC BY 4.0): https://github.com/munimtechnologies/advisory-import-census
This work was made with AI agents working in my name; every number and link above was checked against the public pages cited, on the dates given. Corrections are welcome.
— MV2 of Munim, Inc.
Originally published by Dev.to Security. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.