brew doctor for your agent stack

Scan your agent stack for CVEs & production footguns.

Deterministic. Offline. No API key. langdoctor audits your LangGraph, LangChain, and Langflow projects for known CVEs, insecure checkpointer configs, hardcoded secrets, and the settings that get agents popped in production.

$ pipx run langdoctor
Star on GitHub
0 network calls per scan 25 checks · advisory DB ships in the package exit codes · SARIF · JSON · markdown
The problem

Agents are shipping. So are the CVEs.

2026 has been a rough year for the LangChain ecosystem. The framework-specific layer is exactly what generic scanners miss.

7,000+

Langflow instances exposed to the internet and hit by unauthenticated RCE — actively exploited to drop botnets.

source: BleepingComputer →
60M+

Monthly downloads across the LangChain / LangGraph ecosystem — an enormous surface for a single bad default or unpinned dependency.

source: PyPI Stats →
7

Checkpointer & serializer CVEs patched across the stack in 2025–26. State management is where agents break in production.

source: GitHub Advisories →
The catalog

38 checks, every one with a stable ID.

Suppress by ID, deep-link the docs, fail CI on a threshold. CVE severities are derived from CVSS; KEV marks known-exploited.

IDSeverityCategoryWhat it catches
LD101highKnown CVEsSQL injection via metadata filter key (SQLite checkpointer)
LD105criticalKnown CVEsSerialization-injection secret extraction in dumps/loads
LD106criticalKEVKnown CVEsUnauthenticated RCE in Langflow /api/v1/validate/code
LD111highKEVKnown CVEsPath traversal → RCE via Langflow /api/v2/files upload
LD120highKEVKnown CVEsCORS + SameSite token hijack → Langflow account takeover
LD121criticalKEVKnown CVEsUnauthenticated RCE via Langflow exec_globals
LD122criticalKEVKnown CVEsUnauthenticated RCE via Langflow build_public_tmp flow data
LD123highKEVKnown CVEsIDOR — Langflow /api/v1/responses runs another user's flow
LD124criticalKEVKnown CVEsLangflow auto_login + validate/code chain → unauth RCE
LD150highKnown CVEsLangflow older than the current secure baseline (1.11.0)
LD201highCheckpointerMemorySaver used in a production-bound project
LD202mediumCheckpointerSqliteSaver may collapse under write concurrency
LD203highCheckpointerCheckpoint history filtered by user-controlled input
LD204mediumCheckpointerCompiled graph with interrupts has no checkpointer
LD301mediumRuntime configNo recursion_limit — runaway-loop cost risk
LD302lowRuntime configLLM client created without a timeout
LD303infoRuntime configDeprecated pre-1.0 LangChain import
LD304highRuntime configLegacy load_prompt() usage (path-traversal history)
LD401criticalSecretsHardcoded API key in source
LD402highSecrets.env file present but not gitignored
LD403criticalExposureLangflow auto-login not explicitly disabled
LD501mediumHygieneDependencies not pinned (supply-chain hardening)
LD502mediumHygieneGitHub Actions uses an unpinned third-party action

…and more. Run langdoctor list-checks for the full set.

Ships to CI

One step. Findings in your Security tab.

SARIF output wires straight into GitHub code scanning. Also runs as a pre-commit hook and in GitLab CI.

.github/workflows/langdoctor.yml
name: langdoctor
on: [push, pull_request]
permissions:
  contents: read
  security-events: write
jobs:
  scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: elaz48/langdoctor@v1
        with:
          fail-on: high
      - uses: github/codeql-action/upload-sarif@v3
        if: always()
        with:
          sarif_file: langdoctor.sarif
FAQ

The trust questions, answered.

Does it send my code anywhere?

No. langdoctor makes zero network calls during a scan. The CVE database ships inside the package and everything runs locally — same input, same output, always.

Does it need an API key or an LLM?

No. It's fully deterministic static analysis — no API key, no LLM calls, no telemetry. A full scan of a typical project runs in a couple of seconds.

Is this a replacement for Semgrep or Snyk?

No — it's the framework-specific layer they miss. langdoctor knows LangGraph checkpointers, Langflow defaults, and LangChain's deprecated APIs by name, and tells you the exact fix. Run it alongside your general SAST, not instead of it.

How does it stay current with new CVEs?

Advisories are data, not code: a new CVE is one entry in a JSON file plus a patch release. Follow the package and pin a version in CI for reproducible scans.