Skip to main content

langdoctor 🩺

Scan your LangGraph/LangChain project for known CVEs, insecure configs, and production footguns — in seconds, offline, no API key.

brew doctor for your agent stack.

PyPI Python CI License: MIT

langdoctor scanning a vulnerable project

Quickstart

pipx run langdoctor        # or: uvx langdoctor

Run it in your project directory. langdoctor reads your dependency files and source, reports issues grouped by severity, and exits non-zero when it finds something at or above your threshold.

langdoctor                 # scan the current directory
langdoctor path/to/project # scan a specific directory
langdoctor list-checks     # every check, with IDs and severities
langdoctor --version       # tool version + advisory DB date

Why

2026 has been a rough year for the agent stack:

  • Langflow is under active attack. CVE-2025-3248 (unauthenticated RCE) was added to the CISA KEV catalog and exploited to deploy the Flodrix botnet; CVE-2026-5027 (path-traversal → RCE) is being exploited across ~7,000 exposed instances.
  • LangGraph checkpointer CVEs — SQL injection and unsafe deserialization in the SQLite/base checkpointers can chain to RCE via forged checkpoint rows.
  • Supply-chain attacks on the CI actions and packages the ecosystem depends on (the tj-actions and LiteLLM incidents) mean a pinned-to-a-tag action or an unpinned dependency is a real risk surface.

These are exactly the things a framework-specific linter can catch before you ship. langdoctor ships the CVE data with the package and runs fully offline.

What it checks

ID Category Severity What it catches
LD101 Known CVEs high SQL injection via metadata filter key in SQLite checkpointer
LD102 Known CVEs medium Unsafe msgpack deserialization in checkpoint loading
LD103 Known CVEs medium Unsafe JSON deserialization in checkpoint loading
LD104 Known CVEs high Path traversal in legacy load_prompt functions
LD105 Known CVEs critical Serialization-injection secret extraction in dumps/loads
LD106 Known CVEs critical 🔴KEV Unauthenticated RCE in /api/v1/validate/code (Langflow)
LD107 Known CVEs medium BaseCache deserialization of untrusted data may lead to RCE
LD108 Known CVEs high RCE in "json" mode of JsonPlusSerializer
LD109 Known CVEs high SQL injection in the SQLite store implementation
LD110 Known CVEs high SQL injection via filter key in SqliteStore
LD111 Known CVEs high 🔴KEV Path traversal → RCE via /api/v2/files upload (Langflow)
LD112 Known CVEs medium Unsafe URL path construction in the LangGraph SDK
LD113 Known CVEs high Template injection via attribute access in prompt templates
LD114 Known CVEs medium Path traversal and sandbox escape in file-search middleware
LD115 Known CVEs low SSRF via image_url token counting
LD116 Known CVEs medium Incomplete f-string validation in prompt templates
LD117 Known CVEs high Unsafe deserialization via overly broad load() allowlists
LD118 Known CVEs medium Namespace prefix matching crosses segments (SQLite store)
LD119 Known CVEs medium Namespace prefix matching crosses segments (Postgres store)
LD120 Known CVEs high 🔴KEV CORS + SameSite token hijack → account takeover (Langflow)
LD121 Known CVEs critical 🔴KEV Unauthenticated RCE via exec_globals in validate (Langflow)
LD122 Known CVEs critical 🔴KEV Unauthenticated RCE via build_public_tmp flow data (Langflow)
LD123 Known CVEs high 🔴KEV IDOR in /api/v1/responses runs another user's flow (Langflow)
LD124 Known CVEs critical 🔴KEV auto_login + validate/code chain → unauth RCE (Langflow)
LD125 Known CVEs critical SSRF via unrestricted OpenAPI RequestsToolkit (community)
LD126 Known CVEs high XXE in EverNoteLoader via unguarded iterparse() (community)
LD127 Known CVEs high SSRF via nested sitemap entries in SitemapLoader (community)
LD150 Known CVEs high Langflow older than the current secure baseline (1.11.0)
LD201 Checkpointer & state high MemorySaver used in a production-bound project
LD202 Checkpointer & state medium SqliteSaver may collapse under write concurrency
LD203 Checkpointer & state high (heuristic) Checkpoint history filtered by user-controlled input
LD204 Checkpointer & state medium Compiled graph with interrupts has no checkpointer
LD301 Graph & runtime config medium No recursion_limit configured for a LangGraph run
LD302 Graph & runtime config low (heuristic) LLM client created without a timeout
LD303 Graph & runtime config info Deprecated pre-1.0 LangChain import
LD304 Graph & runtime config high Legacy load_prompt() usage
LD401 Secrets & exposure critical Hardcoded API key in source
LD402 Secrets & exposure high .env file present but not gitignored
LD403 Secrets & exposure critical Langflow auto-login not explicitly disabled
LD501 Hygiene medium Dependencies are not pinned
LD502 Hygiene medium GitHub Actions uses an unpinned third-party action

Severities for CVE checks are derived from the CVSS score; 🔴KEV marks Known-Exploited vulnerabilities, which are always surfaced first.

A finding can arrive without a fix line. Some advisories have no released fix — LD127 is patched upstream but no langchain-community release carries it yet — and langdoctor reports those as affected with no upgrade to recommend rather than inventing a version or staying quiet.

CI integration

GitHub Action

# .github/workflows/langdoctor.yml
name: langdoctor
on: [push, pull_request]
permissions:
  contents: read
  security-events: write   # to upload SARIF
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

Findings show up in your repo's Security → Code scanning tab.

pre-commit

# .pre-commit-config.yaml
repos:
  - repo: https://github.com/elaz48/langdoctor
    rev: v0.1.0
    hooks:
      - id: langdoctor

GitLab CI

langdoctor:
  image: python:3.12-slim
  script:
    - pip install langdoctor
    - langdoctor --format sarif > gl-langdoctor.sarif
  artifacts:
    reports:
      sast: gl-langdoctor.sarif

Configuration

Configure defaults in pyproject.toml; command-line flags take precedence.

[tool.langdoctor]
fail-on = "high"            # critical | high | medium | low | never
ignore  = ["LD203", "LD302"]
exclude = ["examples", "vendor"]

Suppress a single finding inline — by LD id, CVE, or any alias:

API_KEY = get_key()  # langdoctor: ignore=LD401
langgraph==1.0.5  # langdoctor: ignore=LD102

Suppressed findings are always reported as a suppressed: N count so nothing disappears silently.

Output formats

--format console (default) · json · sarif · markdown

  • sarif — GitHub code scanning; security-severity carries the real CVSS.
  • markdown — paste straight into a PR or issue.
  • json — machine-readable, with a per-severity summary.

Exit codes: 0 clean (or below --fail-on), 1 findings at/above threshold, 2 scan error. Heuristic checks never affect the exit code unless --strict.

What langdoctor is NOT

  • ❌ Not a runtime guard. It scans code and dependencies; it does not sit in your request path.
  • ❌ Not an LLM firewall. It does no prompt-injection or content analysis.
  • ❌ Not a replacement for Semgrep/Snyk. It's the framework-specific layer those miss — LangGraph/LangChain/Langflow footguns, by ID, with fixes.

It is deterministic (no AI calls), offline (CVE data ships in the package), and zero-config.

Development

pip install -e ".[dev]"
pytest
ruff check .

Requires Python 3.10+. See CLAUDE.md for design principles, the check-ID conventions, and the "advisories are data" model.

License

MIT © 2026 elaz48

Topics: langgraph · langchain · langflow · security · sast · ai-agents · llm-security · devsecops · cli

Metadata

Release files for langdoctor 0.1.5

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for langdoctor 0.1.5
File Size Uploaded
langdoctor-0.1.5.tar.gz 903.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for langdoctor 0.1.5
File Interpreter ABI Platform
langdoctor-0.1.5-py3-none-any.whl Python 3 none any Details

Total release size: 943.8 kB

Release files / langdoctor-0.1.5.tar.gz

Download URL langdoctor-0.1.5.tar.gz
Size 903.2 kB
Tags Source
SHA-256 checksum
How to use checksums
5394ddb7120519e155c068a0fcd9e46dad9f29838f315a1f85acb81e6c3d2076
BLAKE2b-256 checksum
How to use checksums
593b8d1ec9766d00c6df52bb3a96951f9a2b56b295eb0e8ad50c91a44af95e36
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 27, 2026.

Transparency log

Release files / langdoctor-0.1.5-py3-none-any.whl

Download URL langdoctor-0.1.5-py3-none-any.whl
Size 40.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
18e0046c2ae0ee128590808553ce173abf021de8f787fb94836f838c7243ea37
BLAKE2b-256 checksum
How to use checksums
f8ec8cb6acec0902ec0e0baebd895416f038bfff48295d5d74962fa0e84b6ff9
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 27, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.5 This release

2 release files

0.1.4

2 release files

0.1.3

2 release files

0.1.2

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page