Skip to content

fix(elasticsearch): resolve Cloud IDs to the real host and correct the integration's output, timeout, and redirect defects - #7276

Merged
waleedlatif1 merged 6 commits into
stagingfrom
fix/elasticsearch-cloud-id-host
Aug 30, 2026
Merged

fix(elasticsearch): resolve Cloud IDs to the real host and correct the integration's output, timeout, and redirect defects#7276
waleedlatif1 merged 6 commits into
stagingfrom
fix/elasticsearch-cloud-id-host

Conversation

@waleedlatif1

@waleedlatif1 waleedlatif1 commented Aug 29, 2026

Copy link
Copy Markdown
Collaborator

Summary

Fixes the Elastic Cloud endpoint bug, plus every defect a full /validate-integration pass turned up in this integration.

1. Cloud ID resolved to a host that does not exist (all 13 tools)

A Cloud ID is <deployment label>:<base64 of "parentDomain$esUuid$kibanaUuid"> and the reachable endpoint is https://<esUuid>.<parentDomain>. Every tool built https://<label>.<parentDomain> — the human-readable label, not the Elasticsearch UUID — so Elastic Cloud was unusable in every operation.

Replaced with parseCloudId in a new apps/sim/tools/elasticsearch/utils.ts, following Beats' libbeat/cloudid/cloudid.go decodeCloudID(): split at the last colon so a colon in the label cannot corrupt the payload; require ≥3 $-separated components; right-partition each component at its last colon for a per-service port, inheriting the parent domain's port and defaulting to 443.

Rejects the component characters Beats rejects (#@?/) plus \. This is the security-relevant part — an @ in the UUID component turns everything before it into URL userinfo, so https://<uuid>@evil.example.com would send Authorization: ApiKey … to an attacker-controlled origin. Two checks beyond Beats. First, both ports must be all digits — Beats validates neither, and uuid:80@evil.example.com survives its reject set by landing the @ in the port half. Second, : is rejected in a component name: extractPortFromName has already split at the last colon, so a colon surviving in the name half means the component carried two, and found.io:9243:5 would otherwise assemble https://<uuid>.found.io:9243:5 and fail as a bare TypeError: Invalid URL inside the transport. The port check does not cover that case — it only fires when the trailing half is non-numeric — so the two checks carry separate cases.

buildBaseUrl and buildAuthHeaders were duplicated across all 13 tool files, byte-identical apart from _bulk's NDJSON media type. Now shared, with _bulk passing its content type as an argument.

2. elasticsearch_get_index declared a phantom output

Declared index, but GET /{index} returns a map keyed by index name{"logs-2024": {aliases, mappings, settings}}. There is no index key at any level, so the whole payload was unreferenceable from downstream blocks.

Now returns { indices: data, ...data } and declares indices. The raw per-index keys are spread alongside so references saved before indices existed keep resolving; an index legitimately named indices is spread last and wins. The error branch returns { indices: {} } so both branches satisfy the declared shape.

3. elasticsearch_cluster_health declared a param literally named timeout

tools/request-transport.ts reads params.timeout as the outbound HTTP deadline in milliseconds. On the block path this was inert — the mapper always suffixed s, and Number('30s') is NaN, which the transport discards. On the agent tool-calling path it was live: a model emitting timeout: 30 as a number skips the mapper's typeof === 'string' guard, and the generic handler merges raw inputs over the transform, so it arrived as a 30 ms client abort.

Renamed to clusterTimeout, mapped in tools.config.params (not tools.config.tool, which runs at serialization before variable resolution). The mapper also clears timeout explicitly, because the handler merges { ...inputs, ...transformedParams } and the raw input would otherwise still reach the transport. The subBlock id stays timeout, so saved workflow state is not orphaned — check-block-registry.ts subblock-ID stability passes.

Same mapper had a unit bug: it appended s to anything not already ending in s, so 1m became 1ms — a 1-millisecond server-side wait. It now only appends s to a bare integer.

4. Credentials survived a cross-origin redirect (all 13 tools)

Every tool sends Authorization, but nothing stripped it on a redirect off the configured origin. prepareToolRequest only populates redirectPolicy from the tool, and the stripping branch in lib/core/security/input-validation.server.ts is gated on that policy existing — so a redirect carried the API key or Basic credentials to the redirect target.

All 13 now declare { mode: 'legacy', sendCredentialsOnCrossOriginRedirect: false }. stripAuthOnRedirect is deliberately not used: it drops Authorization on every hop including same-origin, which would 401 a reverse proxy in front of Elasticsearch issuing a legitimate same-origin redirect. mode: 'legacy' preserves method and body replay — under 'standard', a 301/302 would rewrite POST to GET and break _search, _count and _bulk.

5. A cloud deployment fell back to a stale self-hosted host

buildBaseUrl branched on deploymentType === 'cloud' && cloudId, so a cloud invocation with no Cloud ID fell through to host. The block marks cloudId required and does not render host when cloud is selected, but a user who switches the dropdown keeps their previous host in saved state — hidden, not cleared. The cloud credential was sent to the cluster they used to point at.

Now branches on deployment type first and rejects a missing Cloud ID. An unrecognized deployment type is also rejected rather than falling through: deploymentType is required: true with no explicit visibility, which tools/params.ts resolves to user-or-llm, so a model supplies it on the agent path and a near miss like Cloud would take the self-hosted branch. A nullish value still means self-hosted — the dropdown's own default, and the shape of state saved before the field was touched.

6. list_indices dropped indices silently and could throw

item.index.startsWith('.') threw outright on a _cat row with no index column, and every system index was filtered out with no way to opt in. Now guarded, tolerant of a non-array body, and opt-in via an advanced includeSystemIndices dropdown. Default behavior is unchanged.

7. Nullable outputs missing optional: true

get_document._version and ._source (both absent on the 404 branch; _source also whenever _source_excludes strips it), delete_document._version, create_index.shards_acknowledged and .index, cluster_stats.status.

8. Block outputs did not cover every tool

list_indices.message and count._shards were returned but undeclared, so they were missing from the reference picker.

Backwards compatibility

Zero subBlock ids removed or renamed, zero required flips (one addition, a new optional param), zero visibility changes. check-block-registry.ts origin/staging passes the subblock-ID stability check.

Behavior only moves in one direction: a valid Cloud ID that produced an unreachable host now produces the reachable one; a malformed one threw before and throws now. get_index keeps its raw keys. list_indices keeps its default filter. The timeout subBlock keeps its id and its saved values.

Type of Change

  • Bug fix

Testing

94 tests across utils.test.ts, cluster_health.test.ts, responses.test.ts and the existing search.test.ts.

Covers label-vs-UUID host resolution, colon-in-label, per-service and inherited ports, the #@?/\ reject set, both port-smuggle variants, <3 components, self-hosted trailing-slash and missing-host, a sweep asserting all 13 tools resolve the same cloud host, _bulk media type, prepareToolRequest leaving no client deadline while emitting timeout=30s, the 1m/500ms/2h unit cases, get_index declared-vs-actual output parity on both branches, list_indices filtering/opt-in/malformed rows, the redirect policy on all 13 tools, and the optional flags.

Every fix was verified red-first by reverting it and watching its tests fail: get_index 2, list_indices 3, redirect policy 10, optional flags 4, timeout mapper 6, Cloud ID reject set 3, cloud-host fallback 7.

bun run lint, bun run type-check (no Elasticsearch diagnostics), bun run check:audits (39 audits), and check-block-registry.ts origin/staging all pass. tool-metadata:generate and generate-docs artifacts regenerated and committed.

Checklist

  • Code follows project style guidelines
  • Self-reviewed my changes
  • Tests added/updated and passing
  • No new warnings introduced
  • I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)

@vercel

vercel Bot commented Aug 29, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
docs Ready Ready Preview Aug 30, 2026 6:15pm

Request Review

@greptile-apps

greptile-apps Bot commented Aug 29, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

The PR centralizes Elasticsearch connection/authentication handling and corrects Cloud ID resolution, redirect credential handling, cluster-health timeout mapping, and several response contracts.

  • Resolves Elastic Cloud IDs to Elasticsearch service UUID hosts and rejects unsafe decoded components.
  • Prevents credentials from crossing origins during redirects while preserving Elasticsearch request methods and bodies.
  • Keeps saved cluster-health timeout fields compatible while separating the Elasticsearch wait from the HTTP client deadline.
  • Aligns block, tool, generated, and documented outputs and adds system-index opt-in behavior.

Confidence Score: 5/5

The PR appears safe to merge.

No blocking failure remains.

Important Files Changed

Filename Overview
apps/sim/tools/elasticsearch/utils.ts Centralizes Cloud ID parsing, deployment URL selection, and authentication-header construction with explicit malformed-input checks.
apps/sim/blocks/blocks/elasticsearch.ts Preserves the saved timeout sub-block ID while mapping it to the renamed tool parameter and adds system-index and output metadata.
apps/sim/tools/elasticsearch/cluster_health.ts Separates Elasticsearch's server-side cluster wait from the transport timeout and applies safe redirect handling.
apps/sim/tools/elasticsearch/get_index.ts Exposes the provider's index-keyed response through the declared indices output while retaining legacy top-level index keys.
apps/sim/tools/elasticsearch/list_indices.ts Handles malformed response bodies and rows safely and adds an explicit option to include system indices.
apps/sim/tools/elasticsearch/utils.test.ts Exercises Cloud ID host resolution, port inheritance, malformed components, authentication headers, and consistent tool behavior.
apps/sim/tools/elasticsearch/responses.test.ts Verifies runtime response shapes and declared output metadata across the corrected Elasticsearch operations.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart LR
  A[Workflow or agent inputs] --> B{Deployment type}
  B -->|Cloud| C[Parse and validate Cloud ID]
  B -->|Self-hosted| D[Normalize configured host]
  C --> E[Build Elasticsearch endpoint]
  D --> E
  E --> F[Attach API key or Basic auth]
  F --> G[Execute request with legacy redirect semantics]
  G --> H{Redirect crosses origin?}
  H -->|Yes| I[Strip credentials]
  H -->|No| J[Retain credentials]
  I --> K[Transform structured output]
  J --> K
Loading

Reviews (6): Last reviewed commit: "Merge remote-tracking branch 'origin/sta..." | Re-trigger Greptile

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 16 files

Reply with feedback, questions, or to request a fix.

Fix all with cubic | Re-trigger cubic

Comment thread apps/sim/tools/elasticsearch/utils.ts Outdated
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cubic review

@cubic-dev-ai

cubic-dev-ai Bot commented Aug 29, 2026

Copy link
Copy Markdown

@cubic review

@waleedlatif1 I have started the AI code review. It will take a few minutes to complete.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 16 files

Reply with feedback, questions, or to request a fix.

Fix all with cubic | Re-trigger cubic

Comment thread apps/sim/tools/elasticsearch/utils.ts
Comment thread apps/sim/tools/elasticsearch/utils.test.ts Outdated
@waleedlatif1 waleedlatif1 changed the title fix(elasticsearch): resolve a Cloud ID to the real Elasticsearch host fix(elasticsearch): resolve Cloud IDs to the real host and correct the integration's output, timeout, and redirect defects Aug 29, 2026
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cubic review

@cubic-dev-ai

cubic-dev-ai Bot commented Aug 29, 2026

Copy link
Copy Markdown

@cubic review

@waleedlatif1 I have started the AI code review. It will take a few minutes to complete.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 22 files

Requires human review: Auto-approval blocked because this review re-detected 1 unresolved issue already reported by Cubic.

Re-trigger cubic

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cubic review

@cubic-dev-ai

cubic-dev-ai Bot commented Aug 29, 2026

Copy link
Copy Markdown

@cubic review

@waleedlatif1 I have started the AI code review. It will take a few minutes to complete.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 22 files

Reply with feedback, questions, or to request a fix.

Fix all with cubic | Re-trigger cubic

Comment thread apps/sim/tools/elasticsearch/utils.ts Outdated
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cubic review

@cubic-dev-ai

cubic-dev-ai Bot commented Aug 30, 2026

Copy link
Copy Markdown

@cubic review

@waleedlatif1 I have started the AI code review. It will take a few minutes to complete.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 22 files

Confidence score: 5/5

  • Automated review surfaced no issues in the provided summaries.
  • No files require special attention.

You've manually re-run cubic several times on this PR. Each manual re-review checks the full PR again and counts toward your usage quota. To preserve your usage limits, we recommend letting cubic automatically review new commits.

Re-trigger cubic

…cloud-id-host

# Conflicts:
#	apps/sim/tools/generated/tool-metadata.ts
#	apps/sim/tools/generated/tool-outputs.ts
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cubic review

@cubic-dev-ai

cubic-dev-ai Bot commented Aug 30, 2026

Copy link
Copy Markdown

@cubic review

@waleedlatif1 I have started the AI code review. It will take a few minutes to complete.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 22 files

Confidence score: 5/5

  • Automated review surfaced no issues in the provided summaries.
  • No files require special attention.

You've manually re-run cubic several times on this PR. Each manual re-review checks the full PR again and counts toward your usage quota. To preserve your usage limits, we recommend letting cubic automatically review new commits.

Re-trigger cubic

@waleedlatif1
waleedlatif1 merged commit 2b00d96 into staging Aug 30, 2026
27 checks passed
@waleedlatif1
waleedlatif1 deleted the fix/elasticsearch-cloud-id-host branch August 30, 2026 18:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant