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.
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.
Langflow instances exposed to the internet and hit by unauthenticated RCE — actively exploited to drop botnets.
source: BleepingComputer →Monthly downloads across the LangChain / LangGraph ecosystem — an enormous surface for a single bad default or unpinned dependency.
source: PyPI Stats →Checkpointer & serializer CVEs patched across the stack in 2025–26. State management is where agents break in production.
source: GitHub Advisories →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.
| ID | Severity | Category | What it catches |
|---|---|---|---|
| LD101 | high | Known CVEs | SQL injection via metadata filter key (SQLite checkpointer) |
| LD105 | critical | Known CVEs | Serialization-injection secret extraction in dumps/loads |
| LD106 | criticalKEV | Known CVEs | Unauthenticated RCE in Langflow /api/v1/validate/code |
| LD111 | highKEV | Known CVEs | Path traversal → RCE via Langflow /api/v2/files upload |
| LD120 | highKEV | Known CVEs | CORS + SameSite token hijack → Langflow account takeover |
| LD121 | criticalKEV | Known CVEs | Unauthenticated RCE via Langflow exec_globals |
| LD122 | criticalKEV | Known CVEs | Unauthenticated RCE via Langflow build_public_tmp flow data |
| LD123 | highKEV | Known CVEs | IDOR — Langflow /api/v1/responses runs another user's flow |
| LD124 | criticalKEV | Known CVEs | Langflow auto_login + validate/code chain → unauth RCE |
| LD150 | high | Known CVEs | Langflow older than the current secure baseline (1.11.0) |
| LD201 | high | Checkpointer | MemorySaver used in a production-bound project |
| LD202 | medium | Checkpointer | SqliteSaver may collapse under write concurrency |
| LD203 | high | Checkpointer | Checkpoint history filtered by user-controlled input |
| LD204 | medium | Checkpointer | Compiled graph with interrupts has no checkpointer |
| LD301 | medium | Runtime config | No recursion_limit — runaway-loop cost risk |
| LD302 | low | Runtime config | LLM client created without a timeout |
| LD303 | info | Runtime config | Deprecated pre-1.0 LangChain import |
| LD304 | high | Runtime config | Legacy load_prompt() usage (path-traversal history) |
| LD401 | critical | Secrets | Hardcoded API key in source |
| LD402 | high | Secrets | .env file present but not gitignored |
| LD403 | critical | Exposure | Langflow auto-login not explicitly disabled |
| LD501 | medium | Hygiene | Dependencies not pinned (supply-chain hardening) |
| LD502 | medium | Hygiene | GitHub Actions uses an unpinned third-party action |
…and more. Run langdoctor list-checks for the full set.
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.
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
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.