Docker Security Scanner / qdrant/qdrant / latest / detailed

qdrant/qdrant:latest

CRITICAL · 88/100 · now✓ Trusted source · Vendor image · QdrantScanned Jul 16–17, 2026 · Trivy DB 2026-07-08 · base Debian 13.5 · runs as root
88
/100
now
Current threat score
CRITICAL
4 Critical · 26 High findings
The image as shipped today, before any hardening — see the last box below for the score after the Wolfi rebuild.
Verdict & recommended action
Risky as shipped

A Rust vector-database server shipped on a full Debian 13.5 base and running as root by default: 233 vulnerability findings (102 unique CVEs), 4 Critical and 26 High. The danger is not in qdrant's own code — it is the fat Debian base. Three of the four Criticals sit in perl-base, which a Rust binary never invokes; the fourth is a test framework (vitest) recorded in the dashboard's build SBOM. Do not deploy it as-is, as root, on this base.

Concretely: 212 of the findings live in the Debian OS layer — perl, util-linux, pam, ncurses, glibc — packages a single-binary server never runs, but they arm any attacker who reaches a shell and fail every compliance scan. 15 come from the web dashboard's build SBOM (Node/build tools, not browser-executable). 6 are Rust cargo crates compiled into the binary — the only genuinely embedded residue. 0 findings are in CISA KEV and EPSS is low across the set — high on paper, no current mass-exploitation.

233
Total findings
as scanned · 102 unique CVEs
→ CVE log
46
OS patched
apt upgrade clears them
→ Hardening
166
Base bloat removed
Wolfi base = 0 OS CVEs
→ Hardening
15
npm dashboard
API-only build removes it
→ Residue
=
6
residual
LOW risk
0 Critical · 1 High after rebuild
Tip: each box links to its section. The reduction is two real moves — rebase to Wolfi (OS layer → 0) and drop the web dashboard (npm → 0). The last figure is the count of genuinely-embedded residual findings, not a scanner trick.
What the runbook contains (Фазы 0–8)
  1. 0
    Eligibility gate
    qdrant is Debian + Rust → fails the strict Alpine+Go gate; we proceed in fixability mode, disclosed honestly
  2. 1
    Tooling
    Trivy, Syft (SBOM), cosign v2.4.1, Docker; EPSS/KEV enrichment — no Rust binary-reachability tool exists
  3. 2
    Initial scan & baseline
    233 findings / 102 CVEs; functional baseline probed (healthz, collections, vector search) before touching anything

Everything an AI agent needs to run the hardening around this button end-to-end — three rebuilds, each built and re-scanned, with a functional parity gate.

Note: the Wolfi rebuild removes the OS layer by construction — the 3 perl Criticals are gone, not hidden. The 6 cargo residual stay until an upstream qdrant rebuild.

  1. 3
    Hardening — 3 rebuilds
    trixie-slim → Wolfi → Wolfi API-only, each built and re-scanned; 233 → 6, all 4 Criticals eliminated
  2. 4-5
    Residue & VEX / SBOM
    trace where each residual finding physically lives; honest VEX scoped by evidence level; SBOM kept, cosign verified
  3. 6-8
    Evidence & parity gate
    artifacts recorded; vector create / upsert / search all 200 on the hardened non-root read-only runtime

Hardening

Three rebuilds, each built and re-scanned. The Wolfi rebase — not a Debian patch — is what clears the OS layer.
233
Original
6
Hardened v3
BuildBaseFindingsCritHighWhat changed
OriginalDebian 13.5233426
Hardened v1trixie-slim + apt upgrade187423OS patch; base bloat stays (perl is Essential on Debian)
Hardened v2Wolfi (Chainguard)2115OS layer → 0 CVEs; all 3 perl Criticals gone
Hardened v3Wolfi, API-only601+ web dashboard removed (drops all 15 npm incl. the vitest Critical)
1
v1 — Debian trixie-slim + apt upgrade
Clears the 46 patchable OS findings and drops 4 packages absent from slim (openssl/lzma — qdrant uses rustls, no libssl needed). Honest correction: perl-base and util-linux are Essential in Debian and cannot be removed — the base bloat and the 3 perl Criticals remain here.
233 → 187 · Criticals stay
2
v2 — Rebase to Wolfi (Chainguard)
Wolfi is glibc 2.43 (≥ trixie's 2.41), so the Rust binary runs without recompilation. It ships no perl / util-linux / pam, so the base bloat — and all 3 perl Criticals — are gone by construction, not hidden. Only apk add libunwind libgcc was needed for the binary's runtime deps.
OS layer → 0 CVEs · 233 → 21
3
v3 — Wolfi, API-only (remove the dashboard)
Additionally removes the web dashboard (/qdrant/static, 16.5 MB). This drops all 15 npm findings — including the vitest Critical — because the component is genuinely gone, not merely re-classified.
→ 6 findings · 0 Critical
4
Runtime hardening (all three builds)
non-root uid 10001, --read-only, --cap-drop ALL, --security-opt no-new-privileges, --memory 1g --cpus 2, telemetry disabled, writable paths on tmpfs.
fixes the root default
Result: 233 → 6 findings · threat band CRITICALLOW, all 4 Criticals eliminated. What remains is 6 Rust crates compiled into the binary — fixable only by an upstream cargo update.

Reachability / residue analysis

Honest scope: qdrant is Rust/npm, so no Go call-graph reachability applies (govulncheck is Go-only). Instead we traced where each residual finding physically lives.
−227
Removed by rebuild
6
Genuinely embedded
Method: no Rust binary-mode reachability tool exists analogous to govulncheck-for-Go. Residue assessed by where the code physically lives (image inspection of the SBOMs) + severity + EPSS/KEV + package nature. The bundle grep is indicative, not proof.
Affected — embedded6

Rust cargo crates compiled into the binary

From /qdrant/qdrant.spdx.json — an SBOM documenting crates compiled into the 82 MB binary (pyo3, serde_with, rand). They are real and present; find for their code is moot (it lives in the binary). Marked honestly affected — the only fix is an upstream cargo update.
Build-only / Node-only14

npm findings that are not browser-executable

From /qdrant/static/qdrant-web-ui.spdx.json — the dashboard's build SBOM. find for node_modules/vitest returned nothing: these are not shipped as code, the dashboard is pre-compiled static JS. The Critical (vitest) and all Highs are build tools or Node-only libraries — see the full triage in npm dashboard analysis.
Possibly bundled1

js-yaml (Medium) — under investigation

The one npm package with a hit in the compiled bundle (1 grep match). A rigorous verdict needs the bundle's import graph — left as under_investigation rather than waved through.
Removed by rebuild212

Debian OS layer — gone under Wolfi

perl, util-linux, pam, ncurses, glibc, sqlite, systemd, tar, gzip — packages a single-binary server never runs. The Wolfi rebase removes them by construction (0 OS CVEs on re-scan). Not hidden — provable by re-scanning the hardened image.
Findings by layer (as shipped)
Overall severity mix across all 233 findings:CriticalHighMediumLowUnknown
OS · Debian 13.5 · removed via Wolfi
apt / no Rust
212
app · npm dashboard · removed via API-only
build SBOM · static JS
15
app · cargo · residual (affected)
compiled into binary
6

Runtime hardening & functional parity

The hardened image must still satisfy the functional contract of the original. It does — every API path that worked before works after.
PASS
Parity gate
0
Regressions
1
Run non-root, read-only, cap-dropped
uid 10001, --read-only, --cap-drop ALL, --security-opt no-new-privileges, --memory 1g --cpus 2, telemetry off, writable paths on tmpfs.
fixes root default
2
Functional baseline (before) → parity (after)
Probed identical on original and hardened Wolfi build: GET /healthz → 200; create collection → 200 {"result":true}; upsert vectors → 200 {"status":"completed"}; vector search → 200, correct ranked result (id 1, score 0.3).
create · upsert · search all 200
3
Dashboard intentionally gone (API-only build)
GET /dashboard → 404 — expected; the UI is deliberately removed. Every API path is preserved.
expected 404
Parity gate: PASS. A production cutover should still re-run the deploying org's own test suite. Deliberately not claimed: "all remaining are unreachable" — nothing is marked not-affected on a reachability basis (see the honest caveats below).
Deep dive — the sections below are collapsed; expand what you need

What still ships in the binary

The 6 residual findings are Rust crates compiled into the 82 MB qdrant binary. None are Critical, none in KEV — but they are genuinely present, and only an upstream rebuild removes them.
6 residual · 0 Critical
6 cargo findings are compiled into the binary — marked honestly affected, not not_affected. The only fix is an upstream cargo update (qdrant's job, or a source fork). All are trivial version bumps. A qdrant issue tracking these already exists (#9879).
SeverityCrateAdvisoryFix
HIGHpyo3GHSA-36hh-v3qg-5jq4→ 0.29.0
MEDIUMpyo3GHSA-chgr-c6px-7xpp→ 0.29.0
MEDIUMserde_withGHSA-7gcf-g7xr-8hxj→ 3.21.0
LOW ×3randGHSA-cq8v-f236-94qc→ 0.8.6 / 0.9.3
These live inside the compiled binary — the honest fix is an upstream rebuild with cargo update. Until then they persist through any base change, because they are the application, not the OS.

npm dashboard analysis

The 15 npm findings come from the dashboard's build SBOM. Per-package triage: which are actually shipped to the browser?
1
Critical (dev)
13
Not in browser
1
Investigate
All 15 come from /qdrant/static/qdrant-web-ui.spdx.json — the dashboard is pre-compiled static JS; node_modules/vitest are not shipped as code. The API-only build (v3) removes the whole component and all 15 findings with it.
PackageSeverityNatureShipped to browser?
vitestCRITtest framework (marked DEV in SBOM)no — builds the bundle, not in it
viteHIGHbundlerno — produces the bundle
@babel/coreLOWtranspilerno — build-only
undici, form-data, ws, tar, @tootallnate/onceH M LNode-only librariesno — cannot execute in a browser
react-routerMEDbrowser routernot found in the compiled bundle
js-yamlMEDYAML parserpossibly yes (1 hit in bundle)
Conclusion: of the 15, the Critical (vitest) and all Highs are build tools or Node-only libraries — not browser-executable attack surface. Only js-yaml (Medium) is a possible genuine bundled finding. Method caveat: the bundle grep is indicative, not proof; a rigorous verdict needs the bundle's import graph.

Image reputation & trust

Who publishes this image — context for how much to trust the source (as distinct from its contents).
Vendor
First-party
Popular
Vector DB
Current
Debian 13.5
Publisher
Qdrant — the first-party vendor image for the Qdrant open-source vector database. A vendor-maintained image, the norm for first-party application images.
Base freshness
Debian 13.5 (trixie) — current, not EOSL. The risk is base size, not age: a full Debian userland behind a single Rust binary.
Integrity
Scan pinned by digest, so the analysis matches exactly what runs. Exposes 6333 (REST) and 6334 (gRPC); defaults to root — the one bad default, fixed by the runtime hardening.
Provenance to still check
Vendor origin confirms the source, not a signature. cosign sign-blob / verify-blob verified working on the toolchain (Verified OK); attach an SBOM attestation if your policy requires it.
Verdict: trustworthy source. The risk in this report is about the image's base composition (a fat Debian userland + root default), not its origin. Trust the publisher; act on the findings above — pin by digest, not :latest.

Key findings log

The documented findings — 4 Criticals, the 15 npm dashboard packages, and the 6 residual cargo crates. The remaining ~208 OS findings (mostly Low/Unknown Debian base packages) are removed wholesale by the Wolfi rebase and enumerated in the Trivy JSON artifact.
4
Critical
4
High
5
Medium
6
Low
Honest caveat: a scanner "0" is never zero vulnerabilities — the 6 cargo remain real even though a naive image could hide them by stripping the SBOM (which we refuse to do). Counts are relative to the Trivy DB at scan time (2026-07-08); the full 233-row scan lives in scans/qdrant/scan.json. Re-scan by digest.
IDSeverityPackageLayerStatusFixed inSummary
CVE-2026-13221CRITICALperl-baseOS · DebianRemoved (Wolfi)base swapPerl regex miscompilation — a Rust vector DB never invokes perl
CVE-2026-42496CRITICALperl-baseOS · DebianRemoved (Wolfi)base swapArchive-Tar path traversal
CVE-2026-8376CRITICALperl-baseOS · DebianRemoved (Wolfi)base swapPerl heap overflow
CVE-2026-47429CRITICALvitestnpm · dashboardRemoved (API-only)component goneVitest RCE — a test framework in the build SBOM, not shipped as executable code
GHSA (npm)HIGHvitenpm · dashboardRemoved (API-only)component goneBundler — produces the bundle, not in it
GHSA (npm)HIGHundicinpm · dashboardRemoved (API-only)component goneNode-only HTTP client — cannot execute in a browser
GHSA (npm)HIGHwsnpm · dashboardRemoved (API-only)component goneNode-only WebSocket library
GHSA (npm)MEDIUMform-datanpm · dashboardRemoved (API-only)component goneNode-only multipart library
GHSA (npm)MEDIUMreact-routernpm · dashboardRemoved (API-only)component goneBrowser router — not found in the compiled bundle
GHSA (npm)MEDIUMjs-yamlnpm · dashboardUnder investigationcomponent goneYAML parser — possibly bundled (1 hit); removed anyway in API-only build
GHSA (npm)LOWtarnpm · dashboardRemoved (API-only)component goneNode-only archive library
GHSA (npm)LOW@tootallnate/oncenpm · dashboardRemoved (API-only)component goneNode-only utility
GHSA (npm)LOW@babel/corenpm · dashboardRemoved (API-only)component goneTranspiler — build-only
GHSA-36hh-v3qg-5jq4HIGHpyo3cargo · binaryAffected0.29.0Compiled into the binary — fix by upstream cargo update
GHSA-chgr-c6px-7xppMEDIUMpyo3cargo · binaryAffected0.29.0Compiled into the binary — fix by upstream cargo update
GHSA-7gcf-g7xr-8hxjMEDIUMserde_withcargo · binaryAffected3.21.0Compiled into the binary — fix by upstream cargo update
GHSA-cq8v-f236-94qcLOWrandcargo · binaryAffected0.8.6 / 0.9.3Compiled into the binary (finding 1 of 3) — fix by upstream cargo update
GHSA-cq8v-f236-94qcLOWrandcargo · binaryAffected0.8.6 / 0.9.3Compiled into the binary (finding 2 of 3) — fix by upstream cargo update
GHSA-cq8v-f236-94qcLOWrandcargo · binaryAffected0.8.6 / 0.9.3Compiled into the binary (finding 3 of 3) — fix by upstream cargo update
Plus ~208 additional OS findings (Debian base: glibc, sqlite, systemd, tar, gzip, util-linux, pam, ncurses …) not enumerated here — all removed by the Wolfi rebase (0 OS CVEs on re-scan). Full list: scans/qdrant/scan.json.

Honest caveats

Per REPORT-SPEC §5 — the limits of this analysis, stated plainly.
This image fails the strict Alpine+Go gate. No Go call-graph reachability was produced; the Rust/npm residue is assessed by fixability + severity + EPSS/KEV + package nature, not by a proven call graph.
VEX ≠ proof. Nothing here is marked not-affected on a reachability basis. Only where the code is literally absent (component removed → provable by re-scan), or by a reasoned, disclosed argument. The 6 cargo are marked honestly affected.
"Base-slim" needs a functional test. The Wolfi rebuild was built and tested (parity PASS); a production cutover should re-run the deploying org's own suite.
Scanner "0" ≠ zero vulnerabilities. The 6 cargo remain real even though a naive image could hide them by stripping the SBOM — which we refuse to do. Counts are relative to the Trivy DB at scan time (2026-07-08).
Point-in-time. New CVEs land against the residual continuously; re-scan by digest and rebuild on a cadence.