Your Elasticsearch is answering the public internet, and it has no password by default
Elasticsearch and OpenSearch are the search and analytics engines behind a huge number of apps: product search, log storage, the data powering a Kibana dashboard. They're meant to live on the inside, on port 9200, talking only to your application servers. And there's a piece of history that makes an exposed one genuinely dangerous: for years, Elasticsearch shipped with no authentication at all by default. Reach the cluster and you could read every index, no password required. That default is the source of countless "millions of records leaked from an open Elasticsearch" headlines.
The reason this surfaces in a web scan, rather than a port scan, is a specific mistake: someone reverse-proxies the raw search engine onto port 443 at the website host. Now the cluster that was supposed to be internal-only answers https://yoursite.com/ (or a subdomain), and the cluster root, every index, and the /_search API are reachable from any browser on earth.
The banner that gives it away
You don't have to guess whether a host is running Elasticsearch. The engine announces itself. A GET to the cluster root returns a JSON banner with the cluster name, the version, and a hardcoded tagline: Elasticsearch's is the literal string "You Know, for Search", baked into its source. OpenSearch (the fork) identifies itself with "distribution":"opensearch" and its own project tagline.
That clean 200 banner is the whole signal. It means an unauthenticated request reached the search engine itself, not a dashboard, not an app, the data store. From there, if security is off (the historical default and still the case on plenty of older or hastily-deployed clusters), GET /_cat/indices lists every index, and GET /<index>/_search returns the documents. Whatever you indexed, logs, user records, product data, is readable.
Why the scanner is careful here
There's an important boundary in how this gets checked, and it's worth understanding because it keeps the check honest. Modern Elasticsearch 8.x ships with security on by default, and answers the root with a 401 realm="security" instead of a banner. That auth-walled case is not flagged, because a 401 means the cluster is doing the right thing, and flagging it would be a false alarm. The finding fires only on the clean 200 JSON banner, the cluster that's genuinely answering anonymous requests with its identity. So a hit isn't "you run Elasticsearch"; it's "your Elasticsearch is talking to strangers."
The check is also strictly passive: a single GET of /, reading the banner. No /_search, no query, no attempt to pull indices, that would cross from reading what the server volunteers into actively interrogating your data store. The exposed banner is signal enough; the rest is left alone.
Shutting it
Two things fix this, and you want both: turn authentication on, and stop exposing the raw engine to the web.
# nginx puts the raw cluster on the public host
location / { proxy_pass http://localhost:9200; }
# and the cluster has security disabled (or never enabled)
# -> anyone hitting / reads every indexEnable authentication on the cluster, on Elasticsearch 8.x it's on by default, but verify it, and on anything older set it explicitly and create real credentials. Then remove the reverse proxy that put 9200 on the public host; the search engine should be reachable only from your application servers on the internal network. If you genuinely need a public search feature, put your own API in front of the cluster, exposing exactly the one scoped query you intend, never the raw engine. (Direct :9200 port-scanning from the outside isn't something a passive web scan does, that edges into active, so the only way this surfaces is when it's been proxied onto the web, which is precisely the misconfiguration worth catching.)
Reading it from outside
Whether your search cluster answers the public internet is something a stranger settles with one GET of the root, which is exactly what SurfaceCheckr does, from outside, no credentials. It reads the banner and confirms a hit only on the clean 200 JSON identity, the Elasticsearch tagline or the OpenSearch distribution marker, never on the 401 that a properly-secured 8.x cluster returns. It reads what the engine volunteers about itself and stops; it never sends a search or touches an index. An open search cluster is one of the highest-stakes things a passive scan can find, because it's the data itself, sitting on the web with a default that historically required no password, and it only shows up when someone proxied it where it doesn't belong. For the dashboard side of the same stack, an exposed Kibana or OpenSearch Dashboards is the related read, and the broader passive-recon picture is the frame around all of it.
Find it before someone else does.
Paste your domain. The grade and issue count are free, and you'll see in a couple of minutes exactly what's reachable from outside.