Find vulnerabilities in your dependencies.

Fehlo reads which packages your projects actually run and shows known vulnerabilities (CVE, GitHub advisories) with the version that fixes them. For npm, pnpm, Yarn, Bun, Python, Ruby, PHP and Go.

The scan adds to Dependabot, npm audit or pip-audit in your CI; it does not replace them. What it adds: it knows which versions run on your servers, and it reports new advisories even when nobody has touched the code for weeks.

Where Fehlo gets your package list

Fehlo needs the packages and their versions. They come from one of three sources, and the best one wins:

  1. A lockfile from GitHub. When the project is linked to a repository (GitHub integration), Fehlo reads the lockfiles at the root or under the configured path: on every push to the default branch that changes one, on every release that names a commit, and once a day.
  2. A lockfile from CI. Without GitHub, upload the file after the build with an API token that has write access to the project. Release, environment and host are optional.
  3. Packages from error events. Without a lockfile, Fehlo uses the module list the SDK sends with each error. Python, Ruby and Go send installed versions. Node.js sends only the range from package.json, such as ^14.2.0, so those findings read "possibly affected". Browser, iOS, Android and .NET projects get no package check without a lockfile.
CI or cron
curl -fsS -X POST -H "Authorization: Bearer $FEHLO_TOKEN" \
  --data-binary @package-lock.json \
  "https://app.fehlo.de/api/0/projects/<organisation>/<project>/dependencies/?filename=package-lock.json&release=$GIT_SHA&environment=production"

# yarn.lock, poetry.lock, Gemfile.lock and composer.lock with their manifest
curl -fsS -X POST -H "Authorization: Bearer $FEHLO_TOKEN" \
  -F file=@yarn.lock -F manifest=@package.json \
  "https://app.fehlo.de/api/0/projects/<organisation>/<project>/dependencies/"

# on the server: what is actually installed there
pip freeze | curl -fsS -X POST -H "Authorization: Bearer $FEHLO_TOKEN" --data-binary @- \
  "https://app.fehlo.de/api/0/projects/<organisation>/<project>/dependencies/?filename=requirements.txt&host=$(hostname)"

A lockfile takes over from the SDK data of its ecosystem for its environment and host. When you switch from SDK data to a lockfile, ignored findings stay ignored and reported findings stay reported.

Supported lockfiles

EcosystemFilesNote
npmpackage-lock.json, npm-shrinkwrap.json (versions 1 to 3)full tree, direct and indirect, development and runtime
pnpmpnpm-lock.yaml (versions 5 to 9)full tree
Yarnyarn.lock (classic and Berry)needs the package.json next to it to tell direct and development packages apart
Bunbun.lock
Pythonpoetry.lock, uv.lock, Pipfile.lock, pinned requirements.txt, pip freeze outputPipfile.lock and pip freeze have no tree; Poetry needs pyproject.toml for direct and development
RubyGemfile.lockwith the Gemfile next to it for direct and development
PHPcomposer.lockdevelopment packages from packages-dev, direct with composer.json
Gogo.mod, go.sumgo.sum has no tree; Go has no development dependencies

From GitHub, Fehlo fetches the manifest itself. For uploads, send it as the manifest field. Without it, Fehlo counts everything as runtime, which is the cautious side.

What you see

Every six hours Fehlo checks the packages against OSV.dev, the open database that merges CVE records, GitHub Security Advisories and the registries' own databases. A finding shows:

  • the package with its installed version and the hosts that run it,
  • where the version came from, such as "from package-lock.json, commit abc1234",
  • for indirect packages, the path to them, such as @auth/drizzle-adapter > @auth/core,
  • the version that fixes it, and a note when that is a new major version,
  • an "Am I affected?" checklist when the advisory has such a section; many don't,
  • runtimes past their end of life, such as an old Node.js or Python version (data from endoflife.date).

Advisories that describe the same issue under several identifiers (CVE, GHSA, PYSEC, GO) count once. Withdrawn advisories are dropped. Disputed ones get a label, sort last and stay out of the mail.

Ignoring, with a reason

Not every advisory affects you. When you ignore one, you pick a reason: code not reachable, build or development only, preconditions not met, already fixed but not yet reported, risk accepted, or package not used. Add a note. You can ignore a whole package, also for future findings if you like, and take any decision back later. Three months on, your team still knows why something stayed open.

One mail a day

Once a day, owners, managers, admins and members of the project's teams get a mail with new findings, grouped by package. The same digest goes to the chat and webhook channels of your alerts. Each project has a threshold: critical, high or medium. Packages only needed for development stay out unless you include them. Every finding is reported at most once.

What the scan does not do

  • It does not read your code. Whether your app calls the affected function is your call.
  • It opens no pull requests with updates. Dependabot or Renovate do that.
  • Without a lockfile it depends on your errors: a project with no recent errors is only refreshed through a lockfile.
  • .NET reports assembly versions rather than NuGet packages, so without a lockfile there is no check.
  • When an advisory's text and its version range disagree, Fehlo goes by the range.

What it costs

The scan is part of every project, on the Free plan too. Uploaded lockfiles do not count against the event quota. Fehlo accepts a limited number of uploads per project per hour, which is plenty for one per build. Plans are listed under pricing.

AI agents read findings through the MCP server, ignore them with a reason and trigger a re-check, if your role allows it.

Questions

Does Fehlo replace Dependabot or npm audit?

No. Keep them in CI. Fehlo also checks what is actually deployed and reports new advisories for packages you no longer touch.

Which database does Fehlo use?

OSV.dev, the open database that merges CVE records, GitHub Security Advisories and PyPI, Go, RubyGems, Packagist and npm advisories. Fehlo queries it every six hours.

Does Fehlo send my code to OSV.dev?

No. Only package name, ecosystem and version go to OSV.dev. Lockfiles and code stay with Fehlo in Germany.

Do I have to connect GitHub?

No. You can upload the lockfile from CI. For Python, Ruby and Go, the data the SDK sends with each error is often enough.

Why does Node.js say "possibly affected"?

Without a lockfile Fehlo only knows the range from package.json, such as ^14.2.0, and checks its lowest version. With package-lock.json, pnpm-lock.yaml, yarn.lock or bun.lock the versions are exact.