Elasticsearch/OpenSearch: When Search Scores Describe Hidden Documents

Elasticsearch and OpenSearch document-level security can remove private documents from a search response while the search engine still uses those documents to calculate relevance. This chapter applies the isolation test to that different observable: a score rather than a response time. The goal is to understand how document frequency and prefix expansion can expose terms from filtered documents, why n-gram structure can preserve meaning, and which prerequisites keep the result from becoming a universal claim about every search deployment.

A visible score can depend on an invisible corpus

A full-text search engine does not rank a document by looking only at the query and the document that will be shown. A common ranking family, BM25, also uses statistics about the corpus. Two concepts are enough to follow the side channel.

Term frequency describes how often a term appears in one document. Repetition can make that term more relevant to that document. Document frequency describes how many documents in the entire corpus contain the term. A term that appears everywhere is less useful for distinguishing one document from another, so its inverse document frequency is lower. The score for a visible document can therefore depend on documents that the current user is not permitted to read.

Document-level security, or DLS, changes which documents cross the result boundary. In the studied architecture, the search and scoring process can operate over the corpus first, while a DLS predicate determines which documents are returned to the caller. If a private document changes a term's document frequency, it can alter the score of an attacker-controlled document that is allowed to remain visible. The hidden document is not returned, but its participation in corpus-wide statistics changes the response.

The earlier PostgreSQL case exposed a difference in how much work a query performed. The search case exposes a difference in the numerical description of a visible result. The common failure is the same: a private object influences a computation whose output survives filtering.

The basic comparison uses controlled documents. An attacker creates one visible document containing a term chosen to be fresh in the index and another visible document containing the term they want to test. They search for the control term and record its score, then search for the tested term and record its score. If the tested term exists only in the attacker-created document, its corpus frequency can resemble the fresh control's frequency. If it also appears in a private document, the tested term has a higher document frequency and receives a lower score. A difference between the scores becomes evidence that the term exists somewhere in the corpus, including a portion the caller cannot read.

This is not direct access to the private document. The attacker sees an allowed document and its score. The leak comes from the fact that the score was computed using shared corpus state. That distinction matters when judging both the severity and the prerequisites. The caller needs a search interface that exposes scores or a response behavior derived from them, and in the construction described by the paper they need permission to insert documents that make the score comparison interpretable. Removing either capability may break this particular oracle without changing the underlying scoring design.

The ordinary exact-term channel is already a problem for high-entropy data.