From ee8dd2442bcc7c48492fb13f4a4782c65ce1c10d Mon Sep 17 00:00:00 2001 From: Mat Milbury Date: Mon, 13 Apr 2026 18:59:26 +0000 Subject: [PATCH 1/2] fix(link-legacy-key): validate response with Zod and add fetch timeout Replace `as LinkResult` cast on the mcp-gateway response with Zod schema parsing to catch malformed responses at runtime instead of silently proceeding with wrong data. Add AbortSignal.timeout(10s) to the fetch call to prevent the login command from hanging indefinitely if mcp-gateway accepts TCP but never responds. Co-Authored-By: Claude Opus 4.6 (1M context) --- package-lock.json | 16 +++++++++++++--- package.json | 3 ++- src/auth/link-legacy-key.ts | 10 ++++------ src/auth/validation.ts | 9 +++++++++ 4 files changed, 28 insertions(+), 10 deletions(-) create mode 100644 src/auth/validation.ts diff --git a/package-lock.json b/package-lock.json index 6d46c12..4c68613 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,17 +1,18 @@ { - "name": "eterna", + "name": "@eterna-hybrid-exchange/cli", "version": "0.3.0", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "eterna", + "name": "@eterna-hybrid-exchange/cli", "version": "0.3.0", "license": "MIT", "dependencies": { "commander": "^13.0.0", "open": "^10.0.0", - "ora": "^8.0.0" + "ora": "^8.0.0", + "zod": "^4.3.6" }, "bin": { "eterna": "dist/cli.js" @@ -3846,6 +3847,15 @@ "funding": { "url": "https://github.com/sponsors/sindresorhus" } + }, + "node_modules/zod": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.3.6.tgz", + "integrity": "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } } } } diff --git a/package.json b/package.json index 39b6387..1d0b5e3 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,8 @@ "dependencies": { "commander": "^13.0.0", "open": "^10.0.0", - "ora": "^8.0.0" + "ora": "^8.0.0", + "zod": "^4.3.6" }, "devDependencies": { "@eslint/js": "^9.39.4", diff --git a/src/auth/link-legacy-key.ts b/src/auth/link-legacy-key.ts index 8fed5c1..87b3c03 100644 --- a/src/auth/link-legacy-key.ts +++ b/src/auth/link-legacy-key.ts @@ -1,10 +1,7 @@ import { getMcpEndpoint } from "./config.js"; +import { LinkResultSchema } from "./validation.js"; -interface LinkResult { - linked: boolean; - agentName: string; - bybitSubMemberId: string | null; -} +const LINK_TIMEOUT_MS = 10_000; /** * Links a legacy mcp-gateway API key to the caller's OAuth identity. @@ -28,6 +25,7 @@ export async function linkLegacyKey( "Content-Type": "application/json", }, body: JSON.stringify({ legacyApiKey }), + signal: AbortSignal.timeout(LINK_TIMEOUT_MS), }); } catch { console.warn( @@ -37,7 +35,7 @@ export async function linkLegacyKey( } if (res.ok) { - const data = (await res.json()) as LinkResult; + const data = LinkResultSchema.parse(await res.json()); if (data.linked) { console.log( `✓ Legacy account linked — existing Bybit subaccount preserved`, diff --git a/src/auth/validation.ts b/src/auth/validation.ts new file mode 100644 index 0000000..2111441 --- /dev/null +++ b/src/auth/validation.ts @@ -0,0 +1,9 @@ +import { z } from "zod"; + +export const LinkResultSchema = z.object({ + linked: z.boolean(), + agentName: z.string(), + bybitSubMemberId: z.string().nullable(), +}); + +export type LinkResult = z.infer; From cc8131e6e7c03fcbb3eb311ade5ef385309280f5 Mon Sep 17 00:00:00 2001 From: Mat Milbury Date: Mon, 27 Apr 2026 11:05:42 +0200 Subject: [PATCH 2/2] fix(link-legacy-key): use safeParse to prevent unhandled ZodError Replace .parse() with .safeParse() so validation failures follow the existing warn-and-return pattern instead of throwing an uncaught ZodError that propagates to login.ts and reports 'Authentication failed' despite a successful OAuth login. Co-Authored-By: Claude Opus 4.6 (1M context) --- src/auth/link-legacy-key.ts | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/auth/link-legacy-key.ts b/src/auth/link-legacy-key.ts index 87b3c03..2f7a056 100644 --- a/src/auth/link-legacy-key.ts +++ b/src/auth/link-legacy-key.ts @@ -35,8 +35,14 @@ export async function linkLegacyKey( } if (res.ok) { - const data = LinkResultSchema.parse(await res.json()); - if (data.linked) { + const result = LinkResultSchema.safeParse(await res.json()); + if (!result.success) { + console.warn( + "Warning: Unexpected response from mcp-gateway link endpoint", + ); + return; + } + if (result.data.linked) { console.log( `✓ Legacy account linked — existing Bybit subaccount preserved`, );