Skip to the content.

Klavis-AI/klavis — security scan

Repository: Klavis-AI/klavis — 5.7k★, Apache-2.0, an MCP integration platform — a monorepo of 50+ Model Context Protocol servers plus client SDKs. Commit scanned: 669e95dc716b (HEAD of main at scan time) Scan date: 2026-05-20 Disclosure status: Public courtesy issue filed on the Klavis repo. Every finding traces to a published CVE in a dependency — no private coordination required.

Summary

Severity Count (raw) Count (after ignore-file)
Critical 22 22
High 855 703
Medium 679 624
Low 0 0
Info 0 (filtered) 0 (filtered)

1,556 raw findings → 1,349 after suppressing docs/** and examples/**. This is the largest finding count in the series by an order of magnitude — and unlike PraisonAI (where volume was mostly false-positive SQL noise), here the volume is real: ~1,190 Trivy dependency findings across the monorepo’s 50+ independently-managed sub-projects.

Klavis is structurally different from every prior target. It is not one application — it is a monorepo where each mcp_servers/<service>/ directory is its own independently-dependency-managed project, each with its own package-lock.json, requirements.txt, or uv.lock. The security story here is dependency drift at monorepo scale: 50+ sub-projects, each pinning dependencies independently, collectively accumulating into a large surface of known-CVE versions.

Top findings (curated)

1. 22 critical dependency CVEs — three of them matter a lot for an MCP platform

All 22 criticals are Trivy-surfaced published CVEs in dependency lockfiles. Grouped by package:

Package Count CVE Why it matters
authlib 3 CVE-2026-27962 Authentication bypass via JWK Header Injection. Prior to 1.6.9, an unauthenticated attacker can forge arbitrary JWT tokens that pass signature verification when key=None is passed to a JWS deserialization function. Affects google_cloud_toolathlon, Poste.io, and excel MCP servers.
fastmcp 3 CVE-2026-32871 Authenticated SSRF via path traversal in OpenAPI path parameters. Prior to 3.2.0, the OpenAPIProvider’s _build_url() can be coerced into requests to unintended backends. Affects the same three servers.
h11 8 malformed Chunked-Encoding body acceptance Request-smuggling-adjacent; fix is a version bump.
form-data 4 unsafe random boundary generation  
basic-ftp 2 path-traversal file overwrite  
fast-xml-parser 1 XSS via improper handling  
excel-mcp-server 1 path traversal  

The authlib and fastmcp criticals are the ones to fix first. An MCP server is, by definition, a thing that receives tool-invocation requests and acts on them — an auth-bypass or an SSRF in that layer is directly in the threat path. Both fixes are single-line dependency bumps: authlib >= 1.6.9, fastmcp >= 3.2.0.

2. The MCP SDK’s own advisories propagate across ~60 sub-projects

Tool: Trivy (high confidence — named advisories) Verdict: Real, and structurally interesting.

Two advisories against the MCP SDKs themselves show up at scale:

Because Klavis is an MCP platform, the MCP SDK is its single most-depended-on package — so a single SDK advisory multiplies across the whole monorepo. The fix is centralized in principle (bump the SDK pin everywhere) but mechanically spread across ~60 lockfiles. This is the strongest argument in the scan for monorepo-wide dependency automation (see below).

3. ~135 Dockerfiles run as root

Tool: Trivy (missing-user / missing-user-entrypoint, medium confidence) Verdict: Real best-practice, at monorepo scale.

Each MCP server ships its own Dockerfile, and ~135 of them end without a USER directive — every containerized MCP server runs as root. The fix is one mechanical pattern applied broadly:

RUN groupadd -r app && useradd -r -g app -d /app app
USER app

For an MCP platform this matters more than for a typical web app: MCP servers execute tool calls — file operations, shell commands, API requests — so “container compromise” and “runs as root” compound. A shared base image with the USER directive baked in would fix all ~135 at once and prevent the next server from regressing.

4. 41 secret findings — mixed

Tool: Gitleaks Verdict: Mostly false positives (doc-style curl -H "Authorization: Bearer <token>" patterns that survived into non-docs/ files, placeholder .env.example values), but 41 is too many to wave away wholesale. The courtesy issue recommends a Gitleaks pass with a project .gitleaksignore so the real signal — if any — isn’t buried. This scan did not surface a confirmed live credential, but the volume itself is a triage cost worth removing.

Patterns observed

Monorepo dependency drift is a distinct failure mode, and Klavis is a clean specimen of it. Every prior scan in this series was one application (or a small cluster of packages) where dependency findings, when they appeared at all, were a short list — guardrails’ 7 litellm CVEs was the prior high-water mark. Klavis has 50+ sub-projects, each with an independent lockfile, none of them on a shared dependency-update cadence. The result isn’t that any one server is badly maintained — it’s that the aggregate drifts, because no single lockfile is anyone’s daily concern. 1,190 Trivy findings is what dependency entropy looks like when it’s allowed to run across 50 lockfiles for a year.

The fix is process, not patches. Hand-bumping 22 critical CVEs clears today’s criticals; it does nothing about the drift that produced them. The durable fix is monorepo-wide dependency automation — Dependabot or Renovate with a config that covers every mcp_servers/*/ sub-directory — plus a shared Docker base image so the USER directive and a pinned-SDK floor are defined once. The courtesy issue leads with this recommendation rather than the 22-item patch list, because the patch list regenerates itself in three months otherwise.

Volume is not severity, but volume is not nothing either. The PraisonAI scan had 489 findings that curated down to 5 real items — there, volume was noise. Klavis has 1,349 findings and the volume is real: these are named CVEs in shipped dependency versions, not scanner conservatism. The curation work here isn’t “which of these are false positives” — it’s “which of these are reachable enough to fix this week” (the authlib/fastmcp/MCP-SDK criticals) versus “which are part of the standing drift the automation will handle” (the long tail of axios/minimatch/urllib3/path-to-regexp transitive bumps).

--ignore-file paid for itself again. Suppressing docs/** and examples/** removed 207 findings — the curl -H "Authorization: Bearer ..." documentation examples and the example-integration projects’ own lockfiles — none of which are Klavis’s deployed surface. Second monorepo-scale scan (after PraisonAI) where the feature was load-bearing for keeping the curation tractable.

Notes on the tool

This scan stress-tested AI PatchLab harder than any prior one. Backlog items, sharpened:

Disclosure timeline

Reproduce

git clone https://github.com/elfrost/ai-patchlab
cd ai-patchlab
pip install -e ".[dev]"
python scanner/run_scan.py \
  --from-git-url "https://github.com/Klavis-AI/klavis" \
  --reports-dir reports/klavis-ai-klavis \
  --min-severity medium \
  --ignore-file reports/klavis-ai-klavis/.aipatchlabignore

The .aipatchlabignore used (docs/**, examples/**, LLM.md) is in the report directory; without it the raw scan reports 1,556 findings.

External tools (Semgrep, Gitleaks, Trivy, pip-audit) need to be installed separately — see the project README.