Skip to content

ECLI-006: All extensions receive every configured Elastic credential #512

Description

@margaretjgu

Severity: Medium

Problem

src/extension/context.ts:59–66 passes every credential from the active context to every extension with no scoping by declared service need:

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:

{
  "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 <name> 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 in elastic/infosec#27626 (ECLI-006).

Metadata

Metadata

Assignees

Labels

securitySecurity related

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions