encodePathParam in src/es/request-builder.ts percent-encodes /, ?, # (per #106), but leaves ., .., and "" untouched. fetch then normalizes those segments away, so the request targets the cluster root instead of an index.
Reproduced against Elasticsearch 9.4.4 (start-local), two indices seeded:
elastic stack es search --index public-index -> hits from ['public-index']
elastic stack es search --index .. -> hits from ['public-index', 'secret-index']
elastic stack es search --index . -> hits from ['public-index', 'secret-index']
elastic stack es search --index "" -> hits from ['public-index', 'secret-index']
The user asked for one index and got documents from every index. There is no error and no warning, so the widened scope is not visible from the output.
indices delete --index .. likewise sends DELETE /. Elasticsearch rejects that with action_request_validation_exception, so there is no data loss, but the target is still silently rewritten client-side.
src/lib/sanitize.ts:106 already treats . and .. as reserved index names, and sanitizeIndexName has test coverage. That logic is not wired into the request path.
Suggested fix: reject path-param segments that are empty, ., or .. in encodePathParam rather than passing them through.
Test plan
encodePathParaminsrc/es/request-builder.tspercent-encodes/,?,#(per #106), but leaves.,.., and""untouched.fetchthen normalizes those segments away, so the request targets the cluster root instead of an index.Reproduced against Elasticsearch 9.4.4 (start-local), two indices seeded:
The user asked for one index and got documents from every index. There is no error and no warning, so the widened scope is not visible from the output.
indices delete --index ..likewise sendsDELETE /. Elasticsearch rejects that withaction_request_validation_exception, so there is no data loss, but the target is still silently rewritten client-side.src/lib/sanitize.ts:106already treats.and..as reserved index names, andsanitizeIndexNamehas test coverage. That logic is not wired into the request path.Suggested fix: reject path-param segments that are empty,
., or..inencodePathParamrather than passing them through.Test plan
test/es/request-builder.test.tsasserting.,.., and""path params throwtest/cloud/request-builder.test.ts(shares the encoding approach)idx1,idx2still passes through