Skip to content

fix(integrations): validate runtime values the type system only claims to constrain - #7244

Merged
waleedlatif1 merged 2 commits into
stagingfrom
fix/verified-integration-operation-defects
Aug 29, 2026
Merged

fix(integrations): validate runtime values the type system only claims to constrain#7244
waleedlatif1 merged 2 commits into
stagingfrom
fix/verified-integration-operation-defects

Conversation

@waleedlatif1

Copy link
Copy Markdown
Collaborator

Four verified defects from the review of the v0.8.16 release PR (#7224). Each is the same shape: a declared TypeScript type standing in for a check that never runs.

Two other findings on that PR were checked and deliberately not changed — details at the bottom.

Datadog — site decided where the credentials went

DatadogSite is a compile-time union, erased at runtime. site is interpolated straight into the request host, and every Datadog request carries DD-API-KEY and DD-APPLICATION-KEY:

return `https://api.${site || 'datadoghq.com'}${path}`

An unvalidated value therefore chose the destination for the workspace's Datadog credentials. evil.com addresses api.evil.com; datadoghq.com@evil.com addresses evil.com with the expected host parsed as userinfo.

The site list is now a runtime array with DatadogSite derived from it, so the two cannot drift, and both host builders resolve through one validator: datadogApiUrl (31 call sites) and the separate logs-intake host in send_logs. That ternary in send_logs had three branches that all produced the same string, so it collapses to the one expression.

Not reachable from the editor today — the block renders site as a dropdown and the param is user-only, so neither a user nor a model can set it. The value still survives in stored workflow state, which imports and programmatic edits write without passing through that dropdown. This is the defence-in-depth layer, not a live exploit.

CB Insights — optional chaining is not a type check

params.x?.trim() guards undefined, not the type. A block-to-block reference resolving to a number reached .trim() and threw a bare TypeError naming no parameter. The direct sibling, get-commercial-maturity-history, already used parseOptionalStringParam for the identical startDate/endDate pair; the remaining 19 sites now do too.

Everything else is unchanged, and that is checked rather than assumed: compactBody already dropped '', null, and undefined identically, and every use outside it only tests falsiness — so '' and undefined were already interchangeable at all 19 sites. The only behaviour that changes is the non-string case.

CB Insights RAG — the guard contradicted its own contract

message.length > 10_000 admitted a 10,000-character message, while both the thrown error and the tool's param description say "under 10,000 characters". Now >= 10_000, so the code, the error, and the documented contract agree.

Managed Agent — a throw that escaped the result contract

denyMessage was trimmed above the try, so a non-string threw past every success: false path the operation otherwise returns. It is now coerced the same way decision is a few lines above it.

Checked and left alone

Drive addParents/removeParents — the finding says sending the destination in both parameters can make Drive reject the update. Google's own documented move sample does exactly what this code does — fetch all current parents, pass them all as removeParents, pass the destination as addParents, with no exclusion — in C#, Java, Python, and JavaScript. No documentation supports the claimed failure, so changing it would mean deviating from the vendor's canonical pattern on a guess.

Bitbucket zero-byte Range — the finding says Range: bytes=0-N against an empty file can return 416 instead of an empty result. RFC 9110 makes that plausible, but Bitbucket's actual behaviour on the raw endpoint is undocumented and there is no test coverage either way. Unverified, so unchanged.

Verification

  • Each of the four fixes was reverted individually and its test watched go red before being restored.
  • bun run check:audits — 39/39
  • bun run lint — clean
  • type-check — no errors in any touched file (the worktree's other errors are the known stale workspace-package resolution and exist on the base)
  • 162 tests pass across tools/datadog, tools/cbinsights, tools/managed_agent
  • tool-metadata:check, docs:check, integration-catalog:check, block-registry — all pass

…s to constrain

Three defects surfaced by review of the v0.8.16 release PR (#7224), each one a
declared type standing in for a check that never runs.

datadog: `DatadogSite` is a compile-time union, erased at runtime, and `site` is
interpolated straight into the request host while every Datadog request carries
DD-API-KEY and DD-APPLICATION-KEY. An unvalidated value therefore chose where the
workspace's Datadog credentials were sent: `evil.com` addresses api.evil.com, and
`datadoghq.com@evil.com` addresses evil.com with the expected host as userinfo.
The site list is now a runtime array with the type derived from it, and both host
builders -- `datadogApiUrl` (31 call sites) and the logs intake in send_logs --
resolve through one validator. Not reachable from the editor today, since the
block renders a dropdown and the param is user-only; the value still survives in
stored workflow state, which imports and programmatic edits write directly.

cbinsights: `params.x?.trim()` guards undefined, not the type, so a block-to-block
reference resolving to a number threw a bare TypeError naming no parameter. The
sibling history operation already used `parseOptionalStringParam`; the remaining
19 sites now do too. Behaviour is otherwise unchanged -- `compactBody` already
dropped '' and undefined alike, and every non-compactBody use tests falsiness.

cbinsights rag: the guard admitted a 10,000-character message while its own error
and the tool's param description both say "under 10,000".

managed-agent: `denyMessage` was trimmed above the try block, so a non-string
threw past every `success: false` path the operation otherwise returns. It is now
coerced the same way `decision` is a few lines above.

Two further findings on that PR were checked and left alone: the Drive
addParents/removeParents overlap matches Google's own documented move sample in
all four languages, and Bitbucket's Range behaviour on a zero-byte file is
undocumented, so neither is a verified defect.
@vercel

vercel Bot commented Aug 29, 2026

Copy link
Copy Markdown

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

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
docs Skipped Skipped Aug 29, 2026 12:35am

Request Review

@greptile-apps

greptile-apps Bot commented Aug 29, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

The PR adds runtime validation where TypeScript declarations previously allowed malformed stored or referenced values to reach integrations.

  • Centralizes Datadog site validation and routes direct API and logs-intake host builders through the allowlist.
  • Replaces unsafe optional string trimming across CB Insights operations with parameter-aware runtime parsing.
  • Aligns the CB Insights RAG length boundary with its documented contract.
  • Normalizes Managed Agent confirmation text before constructing the provider request.
  • Adds regression coverage for invalid runtime values and Datadog URL builders.

Confidence Score: 5/5

The PR appears safe to merge.

No blocking failure remains.

Important Files Changed

Filename Overview
apps/sim/tools/datadog/utils.ts Adds a runtime Datadog-site allowlist and makes the shared API URL builder validate its host input.
apps/sim/tools/datadog/types.ts Defines the supported Datadog sites as runtime data and derives the compile-time union from that canonical list.
apps/sim/tools/datadog/datadog.test.ts Covers every exported Datadog request URL builder against an attacker-selected site and verifies valid regional hosts.
apps/sim/lib/internal/cbinsights/operations/rag.ts Validates the message runtime type and rejects the documented 10,000-character boundary.
apps/sim/lib/internal/managed-agent/operations/respond-tool-confirmation.ts Normalizes scalar confirmation fields so malformed runtime inputs remain within the operation’s structured result behavior.

Reviews (2): Last reviewed commit: "fix(datadog): route every host builder t..." | Re-trigger Greptile

Comment thread apps/sim/tools/datadog/utils.ts

@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.

1 issue found across 19 files

Confidence score: 4/5

  • In apps/sim/lib/internal/managed-agent/operations/respond-tool-confirmation.ts, a stored workflow object with a non-function toString can throw before the try block, preventing a structured failure response; guard the runtime value or use safe scalar coercion.
Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="apps/sim/lib/internal/managed-agent/operations/respond-tool-confirmation.ts">

<violation number="1" location="apps/sim/lib/internal/managed-agent/operations/respond-tool-confirmation.ts:42">
P2: When stored workflow data contains an object with a non-function `toString` field, this call throws before the `try`, so the operation returns no structured failure. Guard the runtime value or use safe scalar coercion before trimming.</violation>
</file>

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

Fix all with cubic | Re-trigger cubic

Comment thread apps/sim/lib/internal/managed-agent/operations/respond-tool-confirmation.ts Outdated
…scalars safely

Review round 1 on #7244 found the first pass incomplete, and both findings
reproduce.

The site allowlist only covered the shared `datadogApiUrl` and the logs intake.
Ten tools build the host inline -- `const site = params.site || 'datadoghq.com'`
in cancel_downtime, create_downtime, create_event, create_monitor, get_monitor,
list_downtimes, list_monitors, query_logs, query_timeseries and submit_metrics --
so they never reached the validator while still attaching DD-API-KEY and, where
the endpoint needs it, DD-APPLICATION-KEY. All ten now resolve through it. The
new test sweeps the tool registry rather than naming tools, so a future tool that
reintroduces an inline builder fails instead of shipping an unguarded request.

`(value ?? '').toString()` was itself unsafe: an object whose `toString` is not a
function, and one with a null prototype, both throw TypeError, and `String(value)`
throws on the same two. That read sits above the try block, so it escaped the
structured `success: false` result this operation promises. `normalizeScalarText`
converts only the scalar kinds `String()` cannot fail on and returns '' otherwise,
matching how `normalizeStringList` already treats a value of the wrong type. The
identical hazard on `decision` two lines above is fixed with it as well.
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cubic-dev-ai review

@cubic-dev-ai

cubic-dev-ai Bot commented Aug 29, 2026

Copy link
Copy Markdown

@cubic-dev-ai 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 30 files

Confidence score: 5/5

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

Re-trigger cubic

@waleedlatif1
waleedlatif1 merged commit a38492b into staging Aug 29, 2026
27 checks passed
@waleedlatif1
waleedlatif1 deleted the fix/verified-integration-operation-defects branch August 29, 2026 00:41
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