Skip to content

fix(ipc): validate workload payload on utils:get-workload-available-tools handler#2037

Merged
samuv merged 5 commits intomainfrom
fix/ipc-workload-validation
Apr 20, 2026
Merged

fix(ipc): validate workload payload on utils:get-workload-available-tools handler#2037
samuv merged 5 commits intomainfrom
fix/ipc-workload-validation

Conversation

@samuv
Copy link
Copy Markdown
Collaborator

@samuv samuv commented Apr 17, 2026

#1978 flagged that the utils:get-workload-available-tools IPC handler forwarded its workload argument straight into getWorkloadAvailableTools without validation. The fix in that PR introduced an ad-hoc Workload interface (name: string) that didn't match the real CoreWorkload type — where name is optional — and shipped an isWorkload type guard that only checked typeof value === 'object' while claiming to verify a name property (so the value is Workload assertion was unsound). This PR replaces that with a real type guard against the generated CoreWorkload shape and tightens the preload API contract so callers aren't handed unknown.

  • Add isCoreWorkload in main/src/ipc-handlers/utils.ts that rejects non-objects, null, and arrays, and validates name, url, transport_type, proxy_mode, port, and remote match their declared types when present — the subset actually consumed by createTransport / getWorkloadAvailableTools
  • Reject malformed payloads at the IPC boundary with a TypeError instead of forwarding unknown into the AI SDK / MCP client, while still allowing valid partial workloads (the consumer already handles !workload.name by returning null)
  • Reuse GithubComStacklokToolhivePkgCoreWorkload from @common/api/generated/types.gen rather than redefining a parallel local Workload interface
  • Tighten preload/src/api/utils.ts so utils.getWorkloadAvailableTools(workload: CoreWorkload) is strongly typed on both the runtime wrapper and the exported UtilsAPI interface, instead of unknown. The sole caller (renderer/.../customize-tools/page.tsx) already passes a CoreWorkload, so no downstream changes are required

How to validate

  • pnpm run type-check and pnpm run lint pass
  • From the renderer, window.electronAPI.utils.getWorkloadAvailableTools({}) (or any non-object payload) should reject with a TypeError at the main-process boundary rather than reaching createTransport
  • Passing a well-formed CoreWorkload — the only real caller path via the Customize Tools page — should behave exactly as before

Not changed in this PR (deliberate)

  • No change to getWorkloadAvailableTools itself; its existing !workload.name → null contract is preserved
  • No change to other IPC handlers. A broader audit of ipcMain.handle(...) call sites for similar unvalidated payloads can be a follow-up

Closes #1978.

Copilot AI review requested due to automatic review settings April 17, 2026 12:30
@samuv samuv self-assigned this Apr 17, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR strengthens the Electron IPC boundary for utils:get-workload-available-tools by validating the incoming workload payload against the generated CoreWorkload type (rather than a local ad-hoc interface), and by tightening the preload typing so renderer callers use a strongly typed API.

Changes:

  • Add an isCoreWorkload runtime validator in the main-process IPC handler and reject malformed payloads with a TypeError.
  • Switch the preload utils.getWorkloadAvailableTools API from (workload: unknown) to (workload: CoreWorkload) to improve type-safety for callers.
  • Reuse GithubComStacklokToolhivePkgCoreWorkload from @common/api/generated/types.gen instead of redefining a parallel type.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.

File Description
main/src/ipc-handlers/utils.ts Adds runtime validation for the IPC workload payload and rejects invalid inputs before calling getWorkloadAvailableTools.
preload/src/api/utils.ts Tightens the preload API typing so getWorkloadAvailableTools requires a CoreWorkload at compile time.

Comment thread main/src/ipc-handlers/utils.ts Outdated
Comment thread main/src/ipc-handlers/utils.ts Outdated
Comment thread main/src/ipc-handlers/utils.ts
Comment thread preload/src/api/utils.ts
samuv added a commit that referenced this pull request Apr 17, 2026
…-tools

Address Copilot review on #2037: the previous guard accepted any string
for transport_type / proxy_mode and any number for port, so prototype
keys like `__proto__` would fall through into createTransport, and
`NaN` / non-http URLs could reach `new URL(...)` at the transport layer.

- Restrict `transport_type` to {stdio, streamable-http, sse} and
  `proxy_mode` to {sse, streamable-http} via explicit allowlists
- Require `port` to be a finite integer in [0, 65535]
- Require `url` to be an http(s) URL parseable by `new URL` (empty
  string still tolerated; createTransport falls back to localhost)
@github-actions github-actions Bot added size/S and removed size/XS labels Apr 17, 2026
samuv added 5 commits April 17, 2026 14:42
…ools handler

The handler previously forwarded the raw `workload` argument straight to
getWorkloadAvailableTools, which expects the generated CoreWorkload type.
An earlier attempt (#1978) introduced a local `Workload` interface with
`name: string` and an `isWorkload` guard that only checked `typeof value' ===
`object`, so it neither matched the real type nor actually enforced a name.

- Add `isCoreWorkload` that rejects non-objects, `null`, and arrays, and
  validates `name`, `url`, `transport_type`, `proxy_mode`, `port`, and
  `remote` match their declared types when present
- Throw a `TypeError` at the IPC boundary for malformed payloads instead of
  forwarding them into the AI SDK / MCP client
- Reuse `GithubComStacklokToolhivePkgCoreWorkload` from
  `@common/api/generated/types.gen` rather than defining a parallel type
…kload

The preload wrapper and `UtilsAPI` interface both typed the workload
parameter as `unknown`, which hid the real contract from callers and
prevented the TypeScript compiler from catching misuse. The only caller
(`customize-tools/page.tsx`) already passes a CoreWorkload, so no call-site
changes are needed.

- Import `GithubComStacklokToolhivePkgCoreWorkload` and use it for both the
  runtime wrapper and the exported `UtilsAPI` type
…-tools

Address Copilot review on #2037: the previous guard accepted any string
for transport_type / proxy_mode and any number for port, so prototype
keys like `__proto__` would fall through into createTransport, and
`NaN` / non-http URLs could reach `new URL(...)` at the transport layer.

- Restrict `transport_type` to {stdio, streamable-http, sse} and
  `proxy_mode` to {sse, streamable-http} via explicit allowlists
- Require `port` to be a finite integer in [0, 65535]
- Require `url` to be an http(s) URL parseable by `new URL` (empty
  string still tolerated; createTransport falls back to localhost)
The main-process implementation returns `null` when `workload.name` is
missing, but the preload API declared only `… | undefined`. Align the
type so renderer callers see the real contract.
Add focused vitest coverage for the utils IPC handlers: rejection of
non-object, prototype-key, out-of-range, and non-http payloads; happy
paths for a full workload and an empty object; plus smoke tests for
the other three handlers in the module.
@samuv samuv force-pushed the fix/ipc-workload-validation branch from de779e4 to 1737295 Compare April 17, 2026 12:42
@samuv samuv enabled auto-merge (squash) April 17, 2026 12:54
@samuv samuv merged commit 88d3e98 into main Apr 20, 2026
16 checks passed
@samuv samuv deleted the fix/ipc-workload-validation branch April 20, 2026 08:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants