CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



GHSA-7PPG-37FH-VCR6

Vector Injection? No, Just Regular Injection: Milvus Critical Auth Bypass

Amit Schendel
Amit Schendel
Senior Security Researcher

Feb 11, 2026·6 min read·16 visits

Executive Summary (TL;DR)

Milvus exposes its administrative REST API and a debug console on port 9091 by default. Due to missing middleware, requests to this port bypass all authentication. Attackers can create admin users, dump credentials, or execute arbitrary code using the default `by-dev` token.

In the gold rush of the AI revolution, vector databases like Milvus have become the vaults where companies store their most precious semantic data. But while everyone was worried about prompt injection or model poisoning, Milvus accidentally left the back door wide open. A critical vulnerability in the metrics and management interface (port 9091) exposes the entire administrative REST API without authentication. Worse, a debug endpoint allows arbitrary Go expression evaluation with a hardcoded default token. This isn't just a data leak; it's a full system compromise waiting to happen.

The Hook: The AI Vault with a Screen Door

We live in the age of RAG (Retrieval-Augmented Generation). Companies are dumping gigabytes of proprietary documents, customer chats, and trade secrets into vector databases like Milvus to make their LLMs smarter. Milvus is complex software; it has coordinators, proxies, data nodes, and query nodes. To manage this beast, it exposes various ports.

The main entrance, port 19530, handles the high-speed gRPC traffic for vector insertion and searching. This door is usually heavily guarded with authentication, TLS, and API gateways. But software needs to be observed. DevOps teams love metrics. So, Milvus provides a dedicated HTTP server for metrics and health checks on port 9091.

In theory, port 9091 should just reply with some harmless Prometheus-formatted stats. In practice, due to a copy-paste catastrophe in the initialization logic, port 9091 became a fully functional, unauthenticated administrative console. It’s the equivalent of a bank vault having a thermal exhaust port that leads directly to the main reactor—and the door is propped open with a brick.

The Flaw: Middleware Amnesia

The root cause of this vulnerability is a classic case of "Middleware Amnesia." In modern web frameworks like Gin (which Milvus uses), you define routes and then apply middleware to them. Middleware handles things like logging, rate limiting, and—crucially—authentication. If you forget to apply the middleware, the routes still work, they just stop checking ID at the door.

Inside internal/distributed/proxy/service.go, the Milvus developers set up the HTTP server. They correctly initialized the main API group. However, when setting up the metrics server (which runs on a separate port), they decided to register the same business logic handlers to it.

Why? Likely for convenience, so administrators could hit the REST API on the management port if needed. The fatal flaw was that while they copied the routes, they forgot to copy the apiv1.Use(httpserver.RequestHandlerFunc) line (or its equivalent auth check) to the metrics server context. This means GET /api/v1/collection on port 19530 asks for a password, but the exact same request on port 9091 rolls out the red carpet.

The Code: Anatomy of a blunder

Let's look at the smoking gun in internal/distributed/proxy/service.go. This is where the Proxy service spins up its HTTP listeners.

// registerHTTPServer register the http server
func (s *Server) registerHTTPServer() {
    // ... setup code ...
    metricsGinHandler := gin.Default()
    
    // 1. Create the API group on the METRICS handler
    apiv1 := metricsGinHandler.Group(apiPathPrefix) 
    
    // 2. Register the business logic handlers
    handlers := httpserver.NewHandlers(s.proxy)
    handlers.RegisterRoutesTo(apiv1) 
    
    // 3. Register the Proxy REST router
    if p, ok := s.proxy.(*proxy.Proxy); ok {
        p.RegisterRestRouter(apiv1)
    }
    
    // 4. Bind this handler to the metrics server
    mhttp.Register(&mhttp.Handler{
        Path:        mhttp.RootPath,
        Handler:     metricsGinHandler.Handler(),
    })
}

Notice what is missing? There is no authentication middleware attached to apiv1. In the standard HTTP server initialization function (not shown here, but present in the codebase), there is explicit logic that checks Params.ProxyCfg.AuthorizationEnabled and enforces token validation. Here, on the metrics path, the code simply mounts the full RegisterRoutesTo(apiv1) router directly to the open web.

The Exploit: God Mode via `by-dev`

If the unauthenticated API wasn't bad enough, Milvus includes a debug endpoint located at /expr. This endpoint allows the caller to evaluate arbitrary internal Go expressions. Yes, you read that right. It's essentially a web-based eval() for the running Go process.

Access to this endpoint is theoretically restricted by an auth parameter. However, the default value for this check is derived from etcd.rootPath. In almost every default installation, and in the Docker Compose examples provided by Milvus, this value is set to by-dev.

So, we have an unauthenticated Remote Code Execution (or at least Remote Configuration Execution) primitive. Here is how an attacker creates a "Kill Chain":

  1. Leak Secrets: The attacker calls /expr to read the global configuration memory. They can extract the MinIO SecretAccessKey (used for S3 storage) and the root user's password hash.
requests.get("http://target:9091/expr", params={
    "auth": "by-dev",
    "code": "param.MinioCfg.SecretAccessKey.GetValue()"
})
  1. Shutdown: If the attacker just wants to watch the world burn, they can call internal lifecycle methods.
requests.get("http://target:9091/expr", params={
    "auth": "by-dev",
    "code": "proxy.Stop()"
})
  1. Persistence: Using the unauthenticated REST API on the same port, the attacker creates a new admin user to ensure they have legitimate access to the main data port (19530) even if the metrics port is later patched.
requests.post("http://target:9091/api/v1/credential", json={
    "username": "apt_group",
    "password": "base64_encoded_payload"
})

The Impact: Total Recall (of Data)

The impact here is catastrophic for any organization running Milvus exposed to the internet or an untrusted internal network. Because Milvus is a vector database, it holds the meaning of your data.

Data Theft: An attacker can simply list all collections and query the vectors. If they have the MinIO keys (which they can get via /expr), they can bypass Milvus entirely and download the raw data segments from your object storage bucket.

Data Poisoning: In a RAG context, poisoning the vector store is a subtle and dangerous attack. An attacker could insert vectors that are semantically close to common queries but contain malicious or incorrect data. This forces the downstream LLM to hallucinate or provide harmful responses to users.

Infrastructure Compromise: The /expr endpoint can theoretically be used to modify file paths for logging. If an attacker can trick the server into writing logs to a script file (e.g., a web shell or a cron job location), they can achieve full OS-level Remote Code Execution.

The Mitigation: Close the Door

If you are running Milvus versions prior to 2.5.27 or 2.6.10, you are vulnerable. The patch applied by the maintainers simply removes the registration of the API router and the debug endpoint from the metrics port.

Immediate Steps:

  1. Upgrade: Update to v2.5.27 or v2.6.10 immediately.
  2. Firewall: Block TCP port 9091 from external access. This port should strictly be for internal Prometheus scraping, not public internet access.
  3. Config Hardening: Change the etcd.rootPath in your configuration from by-dev to a random high-entropy string. This acts as the password for the /expr endpoint if it is ever accidentally exposed again.

> [!NOTE] > Many Kubernetes deployments expose the metrics port via a Service for monitoring. Ensure your Ingress controller does NOT route external traffic to port 9091.

Official Patches

MilvusMilvus Release Notes v2.5.27
MilvusMilvus Release Notes v2.6.10

Fix Analysis (1)

Technical Appendix

CVSS Score
9.8/ 10
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H

Affected Systems

Milvus Vector Database

Affected Versions Detail

Product
Affected Versions
Fixed Version
Milvus
LF AI & Data
< 2.5.272.5.27
Milvus
LF AI & Data
>= 2.6.0, < 2.6.102.6.10
AttributeDetail
CWE IDCWE-306 (Missing Authentication for Critical Function)
CVSS Score9.8 (Critical)
Attack VectorNetwork (Port 9091)
Secondary WeaknessCWE-1188 (Insecure Default Initialization of Resource)
Exploit StatusPoC Available / High Reliability
Default Tokenauth=by-dev

MITRE ATT&CK Mapping

T1190Exploit Public-Facing Application
Initial Access
T1552Unsecured Credentials
Credential Access
T1059.006Command and Scripting Interpreter: Python
Execution
CWE-306
Missing Authentication for Critical Function

The software does not perform any authentication for functionality that requires a provable user identity.

Known Exploits & Detection

ManualRequests to port 9091 with 'auth=by-dev' query parameter.

Vulnerability Timeline

Vulnerability Published
2026-02-11
Patched Versions 2.5.27 and 2.6.10 Released
2026-02-11

References & Sources

  • [1]GitHub Advisory
  • [2]OSV Database Entry

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.

More Reports

•22 minutes ago•CVE-2026-53722
5.4

CVE-2026-53722: Reflected DOM-based Cross-Site Scripting (XSS) in Nuxt <NuxtLink>

A reflected DOM-based Cross-Site Scripting (XSS) vulnerability was identified in Nuxt's core <NuxtLink> component. Prior to the patched versions, the component failed to validate or sanitize the target URI schemes before directly rendering them into the 'href' attribute of native HTML anchor elements. An attacker who controls the input bound to the 'to' or 'href' properties can inject executable URI schemes, such as 'javascript:' or 'data:', leading to arbitrary script execution in the context of the user's browser session.

Amit Schendel
Amit Schendel
1 views•6 min read
•about 13 hours ago•GHSA-PW6J-QG29-8W7F
5.9

GHSA-pw6j-qg29-8w7f: State Persistence and Sensitive Credential Leakage in Tornado CurlAsyncHTTPClient

A state persistence vulnerability exists in Tornado's CurlAsyncHTTPClient component where pooled pycurl.Curl handles are reused across asynchronous requests without a complete state reset. Consequently, sensitive per-request configurations, such as client TLS certificates or proxy basic authentication credentials, persist on the shared handle. This behavior leads to subsequent requests leaking these credentials to unauthorized remote servers.

Amit Schendel
Amit Schendel
7 views•7 min read
•about 14 hours ago•CVE-2026-48748
7.5

CVE-2026-48748: Netty HTTP/3 QPACK Blocked Streams Memory Exhaustion

CVE-2026-48748 is a denial-of-service vulnerability in Netty's HTTP/3 codec (netty-codec-http3) occurring when QPACK dynamic tables are enabled but the blocked streams limit is not explicitly configured. A bug in limit checking and a memory leak in stream tracking allow unauthenticated remote attackers to exhaust the JVM heap memory and crash the server.

Amit Schendel
Amit Schendel
8 views•6 min read
•about 14 hours ago•CVE-2026-50009
4.8

CVE-2026-50009: Stateless Reset Token Exposure in Netty QUIC

CVE-2026-50009 is a cryptographic design vulnerability in the Netty network application framework. Prior to version 4.2.15.Final, the framework's QUIC protocol implementation fails to cryptographically segregate the generated Connection IDs and the associated Stateless Reset Tokens. An on-path network attacker who sniffs traffic during a Connection ID rotation can extract secret token material from cleartext headers, enabling them to inject spoofed reset packets and terminate active connections.

Alon Barad
Alon Barad
7 views•6 min read
•about 15 hours ago•CVE-2026-50010
7.5

CVE-2026-50010: Hostname Verification Bypass in Netty TLS Client

A critical hostname verification bypass vulnerability exists in the Netty network application framework when configured as a TLS client. When a developer registers a custom plain X509TrustManager, Netty wraps it inside an X509TrustManagerWrapper to adapt it to the X509ExtendedTrustManager API. However, this wrapper discards the SSLEngine context, bypassing critical hostname checks. Because the wrapper is identified as an X509ExtendedTrustManager, standard cryptographic engines and Netty's OpenSSL wrappers do not re-wrap it, failing to execute any hostname validation. Consequently, clients silently accept certificates for any host, enabling unauthenticated Man-in-the-Middle (MitM) attacks.

Amit Schendel
Amit Schendel
10 views•8 min read
•about 15 hours ago•CVE-2026-50011
7.5

CVE-2026-50011: Unbounded Resource Pre-Allocation in Netty Redis Codec

An uncontrolled resource pre-allocation flaw in the Netty Redis codec module allows remote unauthenticated attackers to cause a denial of service (OutOfMemoryError) by sending a crafted Redis Serialization Protocol (RESP) array header.

Amit Schendel
Amit Schendel
5 views•7 min read