Join our Newsletter — 33% off our NHI Course
Home› Guides› Search Feature Security: Preventing Injection, Data Leakage and…
Guide Application Security

Search Feature Security: Preventing Injection, Data Leakage and Enumeration

PDF for newsletter subscribers · free to read online

← All guides
By NHI Mgmt Group, edited by Lalit Choda Updated 12 November 2026 16 min read
On this page

A search box is a query interpreter, an authorisation boundary and a data export tool rolled into one input field, and most applications secure it as if it were none of these. Site search, record lookup and typeahead all pass untrusted text to an engine whose index often holds more than the caller may see. This guide covers the risks specific to search features: query injection into search engines, data leakage through what gets indexed and how results, facets and suggestions are built, enumeration of users and records, and resource exhaustion. It is for application security engineers, search developers and architects. General attack classes are in the Web Application Attacks Guide.

Key takeaways

  • The index is a copy of your data with its own access model. Anything indexed can be returned unless permissions travel with the documents and are enforced on every query, suggestion and aggregation.
  • Never hand users a full query language. Map the search box to a match style query and build filters server-side; expose operators only through a constrained parser.
  • Side channels leak as much as results. Result counts, facet totals, autocomplete terms, relevance scores and "no results" wording can reveal records the caller cannot open.
  • Search is the fastest enumeration tool in your application. User directory search, email lookup and record ID search need the same generic responses, rate limits and authorisation as login.
  • Service credentials behind search are high value. The account the application uses to query the engine usually reads every index, so scope it, keep it server-side and monitor it like any privileged non-human identity.

Why search features are a distinct risk

A normal application page shows one object after an authorisation check. A search feature runs one query across many objects and the authorisation check, if any, has to be built into the query itself. Three properties make it different:

  • Denormalised copies: pipelines flatten records, attachments and comments into documents, so fields the interface never shows (internal notes, emails, API keys pasted into tickets) become searchable.
  • Aggregate answers: counts, facets, highlights and suggestions may be computed outside the filter that trims the result list.
  • Expressive input: engines accept Boolean operators, field targeting, wildcards and regular expressions; forwarded user text can change what the query asks.

The attacker goals map cleanly onto MITRE ATT&CK: harvesting content from internal search and knowledge bases is Data from Information Repositories (T1213), and using lookup features to list valid users is Account Discovery (T1087).

Threats to search features at a glance

ThreatHow it shows up in searchPrimary controlWeakness or risk reference
Query injectionUser text is concatenated into a search DSL, Lucene query string, SQL LIKE clause or NoSQL filter, letting the caller add fields, operators or remove the tenant filterStructured query building; match queries for free text; server-side filtersOWASP Injection Prevention Cheat Sheet; NIST SP 800-53 SI-10
Over-indexingSensitive fields or whole records indexed because the pipeline indexes everything by defaultField allow-list in the indexer; data classification before indexingNIST CSF 2.0 PR.DS-01
Missing document-level authorisationResults include records from other users or tenants; direct document fetch by ID after searchPermission metadata on each document, enforced on every queryOWASP API1:2023 Broken Object Level Authorization; SP 800-53 AC-3
Property-level exposureHidden fields returned in the result source, highlights or exportsField-level security; explicit response field listsOWASP API3:2023 Broken Object Property Level Authorization
Side-channel leakageFacet counts, totals, autocomplete terms or scoring reveal hidden recordsCompute aggregations and suggestions inside the permission filter; per-user suggestion sourcesCWE-203 Observable Discrepancy
EnumerationUser or email lookup returns different messages, status codes or timings for existing and missing entriesGeneric responses, consistent timing, rate limits, authentication before directory searchCWE-204 Observable Response Discrepancy
Query string leakageSearch terms containing personal data or secrets stored in web logs, analytics, browser history and Referer headersPOST for sensitive search; log redaction; Referrer-PolicyCWE-598 Use of HTTP Request With Sensitive Query String
Resource exhaustionLeading wildcards, regular expressions, deep pagination and huge page sizesDisable expensive query types; cap size and offset; rate limitOWASP API4:2023 Unrestricted Resource Consumption; SP 800-53 SC-5

Preventing query injection

The OWASP Injection Prevention Cheat Sheet describes injection as untrusted data sent to an interpreter, prefers a safe parameterised API, treats allow-list validation as useful but not a complete defence, and keeps interpreter-specific escaping for cases where no parameterised API exists. Search engines are interpreters, and the same order applies.

  • Use a match style query for the search box: Elastic's query_string documentation does not recommend that query for search boxes because it errors on invalid syntax, pointing instead to match or simple_query_string. A match query treats input as text, not operators.
  • Build filters in code, never from text: tenant, owner, status and date filters belong in a structured filter clause assembled from the authenticated session.
  • Allow-list advanced options: accept only known sort and facet field names, mapped server-side.
  • Never forward client-supplied query DSL: use stored templates with typed parameters; the front end is controlled by the attacker.
  • Database-backed search: where search is a SQL LIKE or full-text predicate, bind the search term as a parameter and escape the wildcard characters % and _ if users should not control pattern matching. See the SQL Injection Prevention Guide. For document stores, filters built from JSON bodies are a classic operator injection path: see the NoSQL Injection Prevention Guide.
  • Encode results on output: search pages reflect the query back ("results for ...") and render highlighted snippets that contain stored content. Encode both as untrusted output. See the Cross-Site Scripting (XSS) Prevention Guide.

Controlling what gets indexed

The most reliable way to stop a search feature leaking data is not to put the data in the index.

  1. Classify sources before connecting them. List each source system, the classification of its data and who may see it. See the Data Classification Guide.
  2. Index an allow-list of fields, marking each searchable, retrievable or filter-only; dynamic mapping indexes everything sent.
  3. Scan content for secrets and personal data at ingest, redact matches and have exposed secrets rotated.
  4. Propagate deletions and permission changes, or the index becomes a shadow archive. Measure sync lag as a security metric.
  5. Separate indexes by tenant or sensitivity where volume allows, so a filter mistake returns nothing instead of another tenant's data. See the Multi-Tenant SaaS Authorisation and Tenant Isolation Guide.

Enforcing document and field permissions in the engine

There are two broad patterns. In application-side trimming, the application works out the caller's identity and groups and adds a filter to every query. In engine-side enforcement, the engine itself evaluates the caller's identity against permission metadata or role queries. The examples below show how three widely used engines document these controls. Platforms are listed alphabetically; this is not a ranking.

Azure AI Search

Microsoft documents security trimming as a filter pattern: a Collection(Edm.String) field such as group_ids, set filterable and not retrievable, holds the user or group identifiers per document, and each query carries a filter such as group_ids/any(g:search.in(g, 'group_id1, group_id2')). The documentation notes that the principal is only a string in a filter and that marking a field not retrievable is not a substitute for access control, so the application must establish group membership itself and apply the filter to every query. Microsoft also documents engine-side options (ACL and RBAC scopes for ADLS Gen2 and Blob content, SharePoint ACLs and Purview sensitivity labels) where the user's Microsoft Entra token is passed in the x-ms-query-source-authorization header. Permission changes reach results only after the index metadata is synchronised. Availability: as checked in November 2026, security filters are generally available and the other three approaches are in preview.

Elasticsearch

Elastic documents document level security as a query added to an entry in a role's indices array, and field level security as a field_security object with grant and except lists. Role queries can be templated with Mustache placeholders such as _user.username and _user.metadata, so one role can restrict each user to their own documents. Elastic notes that when a user holds several roles, document queries combine with OR and a role without a query removes the restriction. The limitations list states that aggregations can reveal field names and term counts from hidden documents and that relevance scoring ignores the role query, which matters for the side channels below. Elastic also says these restrictions are intended for read-only accounts.

OpenSearch

OpenSearch documents document-level security as a dls query in a role's index_permissions, with parameter substitution for ${user.name}, ${user.roles} and user attributes such as ${attr.jwt.<name>}. Queries from several DLS roles combine with OR, and the plugins.security.dfm_empty_overrides_all setting decides whether a role without DLS overrides another role's restrictions for the same user. The documentation states that DLS limits reads only, does not restrict write operations, and advises not to give DLS users write permissions.

Choosing a pattern: a single-tenant application with simple ownership rules can use an application-side filter, provided tests fail any query built without it. Strict multi-tenant isolation is best served by an index or alias per tenant with a tenant filter as defence in depth. Enterprise content with existing source ACLs suits engine-side permission metadata, accepting sync lag. Where analysts query the engine directly, use engine roles with document and field restrictions and review users holding several roles.

Closing side channels: counts, facets, suggestions and scores

Correctly filtered results are not enough if the extras around them are computed over the unfiltered set.

  • Totals and facets: "312 results" and "HR (4)" are answers in their own right. Compute them inside the same permission filter as the hits, and test by searching as a low-privilege user for a term that only appears in restricted documents. The count must be zero.
  • Autocomplete and suggestions: suggesters are usually built from a global term dictionary or a log of popular queries. Both leak: the first reveals terms from restricted documents, the second reveals what other users searched for. Build suggestions from per-tenant or permission-filtered sources, or switch them off for sensitive indexes. Elastic's documentation notes that suggesters are ignored under document level security, and Microsoft notes autocomplete and suggest are unavailable on Purview-enabled indexes: plan for this rather than routing suggestions through a separate unrestricted path.
  • Highlights: restrict highlight fields to the returned field list.

User directory search, "find a colleague", email lookup during sign-up and order or case number search all answer the question "does this exist?". The OWASP Authentication Cheat Sheet's guidance for login and recovery applies directly to these lookups: return a generic message whether or not the entry exists, keep HTTP status codes identical, avoid a quick exit when nothing matches so that response time is similar, and limit attempts at scale.

  • Require authentication for directory search and scope results to the caller's organisation. Public people search should return only deliberately public profiles.
  • Do not confirm identifiers to anonymous users. Send a message to the address instead of confirming it on screen.
  • Recheck authorisation on every fetch after search and use non-guessable record IDs. See the Broken Access Control Prevention Guide.
  • Set a minimum query length and small result pages, so a one-character query cannot dump the directory.
  • Rate limit per account, per IP range and per tenant, with separate budgets for typeahead and full search. See the Rate Limiting and API Abuse Guide.

Protecting availability and query strings

  • Expensive queries: Elastic's query_string documentation warns that leading wildcards force a check of every term in the index and that regular expressions such as /.*n/ can visit every term; it exposes allow_leading_wildcard and a max_determinized_states limit (default 10000). Turn off leading wildcards and regular expressions for user-facing queries and use the engine's setting for disallowing expensive queries where available.
  • Pagination, size and time: cap page size, maximum offset and per-query time; use cursor-based paging for legitimate deep access.
  • Search terms in URLs: CWE-598 notes that query strings are saved in browser history, passed in Referer headers and stored in web logs. Use POST for search over sensitive data, set Referrer-Policy: strict-origin-when-cross-origin or stricter, and redact search parameters in web server logs and analytics.

Where identity fits

Every search feature has a non-human identity behind it: the service account, API key or managed identity the application uses to query the engine, and another used by the indexing pipeline to read source systems. A leaked query key that reads every index turns search into bulk export. Give query and indexing identities separate credentials, scope query credentials read-only to specific indexes, keep admin and write keys out of browsers and apps, prefer managed identities or federation over static keys, and rotate keys. See the Elasticsearch and OpenSearch Security Guide for engine hardening and the Permission-Aware RAG Guide where search results feed an AI assistant.

Implementation roadmap

The sequence below is an NHI Mgmt Group recommendation.

  1. Inventory search features, with engine, index, credential and data sources for each.
  2. Map index contents to classifications. For each index, list fields and classify them. Remove or redact fields that no search use case needs.
  3. Fix query construction. Replace string-built queries with structured builders and match style queries; move all filters server-side. Add unit tests that fail if a query is built without a tenant or permission filter.
  4. Add permission enforcement in audit mode. Run the permission filter in parallel with the current query in a pilot and log the difference in hit counts. A non-zero difference shows where users are currently seeing data they should not.
  5. Turn enforcement on in rings (internal users, pilot tenants, everyone) behind a feature flag; roll back only the toggle, never by widening credentials.
  6. Close side channels and enumeration. Move facets, counts and suggestions inside the filter, add generic responses and rate limits to lookups.
  7. Test continuously with two users, two tenants and restricted terms, after every new data source.

Decision guidance

Small teams with one application get most of the benefit from application-side filtering, a separate read-only query key, generic lookup responses and engine limits on expensive queries, and should keep restricted data out of the index until permissions are designed. Large or multi-tenant platforms should invest in index-per-tenant isolation, engine-side permission metadata synchronised from source systems and automated cross-tenant tests. For enterprise search over many sources, treat each connector as an integration with its own owner and permission sync, and prefer keeping highly sensitive sources out over relying on a preview feature.

Detection and measurement

Log each search request with the authenticated principal, tenant, index, filter applied (or a hash of it), result count and latency. Alert on queries without a permission filter, unusual indexes, very high result counts or offsets, bursts of short-prefix typeahead calls and engine access by credentials outside the application.

MetricWhat it showsTarget
Queries executed without a permission or tenant filterGaps in enforcementZero in production
Indexed fields without an assigned classificationOver-indexing riskZero for indexes holding personal or restricted data
Permission sync lag (source change to index update)How long revoked users keep seeing documentsAgreed per data class, measured continuously
Cross-tenant and restricted-term test pass rateRegression in authorisation100% on every release
Search credentials with write or admin rights used by applicationsOver-privileged non-human identitiesZero

Framework mapping

FrameworkReferenceRelevance to search
NIST SP 800-53 Rev 5AC-3 Access Enforcement; AC-6 Least PrivilegeDocument permissions on every query; scoped query credentials
NIST SP 800-53 Rev 5SI-10 Information Input Validation; SI-11 Error HandlingStructured query building; generic error and no-result responses
NIST CSF 2.0PR.AA-05; PR.DS-01; DE.CM-09Least privilege on indexes; protecting indexed data at rest; monitoring search use
CIS Controls v8.1Control 3 Data Protection; Control 16 Application Software SecurityData inventory and handling for indexes; secure search code
ISO/IEC 27001:2022 Annex A8.3 Information access restriction; 8.28 Secure codingPermission trimming; injection-safe query construction
OWASP API Security Top 10 2023API1, API3, API4Object and property level authorisation; resource consumption
MITRE ATT&CK v20T1213, T1087Repository harvesting and account discovery through search

Common failure patterns

  • Filtering results but not facets: the list is empty but the sidebar shows "Legal (12)". Every aggregation needs the same filter as the hits.
  • Forwarding front-end query JSON: the single-page app builds the engine query and the API passes it through, so anyone with browser tools can remove the tenant clause.
  • Role combination widening access: a user given a second, unrestricted role for one task loses document restrictions everywhere, because in Elasticsearch a role without a document query removes the restriction for that index, and in OpenSearch the same happens when dfm_empty_overrides_all is enabled.
  • Query keys in client code: a key embedded in a mobile app or JavaScript bundle has wider rights than the search page needs, turning the engine into an open data store.
  • Directory search as an oracle: sign-up or invite lookups confirm which email addresses have accounts.

Practitioner checklist

  • Replace string-built queries with structured builders; use match style queries for free text and never forward client query DSL.
  • Index only allow-listed fields, scan content for secrets and personal data at ingest, and propagate deletions.
  • Enforce document permissions on every query path, including counts, facets, highlights, suggestions and exports.
  • Return generic, constant-time responses for user and record lookups, require authentication and set minimum query lengths.
  • Disable leading wildcards and regular expressions for user queries; cap page size, offset and query time.
  • Send sensitive searches by POST, set a strict Referrer-Policy and redact search terms in logs and analytics.
  • Give query and indexing identities separate, read-only scoped credentials kept server-side, and rotate them.
  • Run cross-tenant and restricted-term tests on every release and track permission sync lag.

Standards and references

Related NHI Mgmt Group resources: Web Application Attacks Guide · Broken Access Control Prevention Guide · Elasticsearch and OpenSearch Security Guide · Permission-Aware RAG Guide

PDF for subscribers

Take this guide with you

Every section, table and checklist in one PDF, with links to the sources and related guides. Subscribe to our weekly NHI & AI Identity Journal and we’ll email you a download link.

Free weekly newsletter

Subscribe to the NHI & AI Identity Journal

The latest on NHI and Agentic AI security – articles, research, breaches, news and events every week.

Bonus 33% off our NHI Course when you subscribe.

NHIMG Editorial Note
Researched and written by the NHI Mgmt Group editorial team using AI tools, under the editorial direction of Lalit Choda. Facts are drawn from the sources listed on this page and checked by our automated quality process. Last updated 12 November 2026. Spotted an error? Use our contact page.
NHI Mgmt Group, the independent authority on Non-Human Identity, IAM and Agentic AI security. nhimg.org

PDF Downloads for Newsletter Subscribers

Get the guide

Enter your details and we’ll email you a download link.

The full guide is free to read online. The PDF is a thank you for subscribing.

Fill in all fields marked * and tick the PDF box to continue.