ECLI-006: All extensions receive every configured Elastic credential
- Dominant language
- TypeScript
- Stars
- 41
- Forks
- 24
- Avg merge
- 1d 3h
- Merged PRs (30d)
- 56
Description
**Severity: Medium**
### Problem
[src/extension/context.ts:59–66](https://github.com/elastic/cli/blob/main/src/extension/context.ts#L59-L66) passes every credential from the active context to every extension with no scoping by declared service need:
```ts
export function buildContextEnv (config: ResolvedConfig): EnvMap {
const env: EnvMap = {}
const { elasticsearch, kibana, cloud } = config.context
if (elasticsearch != null) Object.assign(env, serviceEnv('ELASTIC_ES', elasticsearch))
if (kibana != null) Object.assign(env, serviceEnv('ELASTIC_KIBANA', kibana))
if (cloud != null) Object.assign(env, serviceEnv('ELASTIC_CLOUD', cloud))
return env
}
```
When the active context contains a Cloud credential, every extension receives `ELASTIC_CLOUD_API_KEY`, even if it does not use the Cloud API.
Each credential carries the privileges assigned when it was issued. A Cloud API key may authorize organization- or deployment-management operations, while Elasticsearch and Kibana credentials may also be broadly privileged. Passing credentials for unrelated services therefore unnecessarily expands an extension's available authority.
The README documents six variables but `context.ts` exports up to ten — `ELASTIC_ES_USERNAME`, `ELASTIC_ES_PASSWORD`, `ELASTIC_KIBANA_USERNAME`, and `ELASTIC_KIBANA_PASSWORD` are omitted. Extension authors who rely solely on the README do not know their process environment contains basic-auth passwords.
### Fix
**Short-term:** Require extensions to declare the services they need in their manifest or extension registry entry. Only pass credentials for declared services:
```json
{
"elastic": {
"services": ["elasticsearch"]
}
}
```
`buildContextEnv` reads this declaration and omits `ELASTIC_CLOUD_*` and `ELASTIC_KIBANA_*` entirely for an extension declaring only `"elasticsearch"`.
At installation, display the requested credential scopes, require confirmation, and persist the approved scopes in the registry. On upgrade, require renewed consent before granting additional services. Fix the README table to document all ten exported variables.
- Provide an `elastic extension inspect ` command showing: source, installed version or commit, entrypoint, declared credential scopes, and the environment variables the extension will receive.
- Fail closed when the extension manifest has no credential declaration. Do not treat absence as a grant of all credentials.
### Risk
**Medium.** A compromised extension receives the Cloud credential and whatever management-plane privileges that credential carries. Least-privilege gap, not privilege escalation.
---
Copied from the [security review](https://github.com/elastic/infosec/issues/27626#issuecomment-5172341916) in elastic/infosec#27626 (ECLI-006).
Contributor guide
Assessment
This issue has not been assessed yet.