aboutsummaryrefslogtreecommitdiff
path: root/src/cdp
diff options
context:
space:
mode:
authoramankumarsingh77 <amankumarsingh7702@gmail.com>2026-07-28 00:53:19 +0530
committerAman Kumar <145339995+amankumarsingh77@users.noreply.github.com>2026-08-02 19:12:46 +0530
commitb9c77bb6f9b8b83574489344ef6efd207a611e98 (patch)
tree3c59bf53bcce3ac5c6bbf9a22884b6e6f787dc91 /src/cdp
parent1c73f4af643aa60ca554a3770264791d299e64e2 (diff)
refactor: validate JSON at every parse boundary
Ten sites cast or implicitly typed JSON.parse output; JSON.parse("null") would have satisfied all of them. parseJson returns a Result and validates against a typebox schema. js.ts keeps unknown — user script output has no fixed shape. daemon/bridge.ts assigned JSON.parse straight to CdpRawMessage with no guard at all; it now uses isCdpRawMessage like the transport does. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Diffstat (limited to 'src/cdp')
-rw-r--r--src/cdp/discovery.ts19
1 files changed, 12 insertions, 7 deletions
diff --git a/src/cdp/discovery.ts b/src/cdp/discovery.ts
index 295df20..b4be31c 100644
--- a/src/cdp/discovery.ts
+++ b/src/cdp/discovery.ts
@@ -2,6 +2,9 @@ import { readFile, stat } from "node:fs/promises";
import { join } from "node:path";
import { connect as netConnect } from "node:net";
import { request as httpRequest } from "node:http";
+import { Type } from "typebox";
+import { Compile } from "typebox/compile";
+import { parseJson } from "../schemas/parse";
import { type Result, err, ok } from "../util/result";
import { userDataDirCandidates } from "../profile/paths";
import { type CdpError, cdpError } from "./errors";
@@ -9,6 +12,13 @@ import { type CdpError, cdpError } from "./errors";
const PORT_PROBE_DEADLINE_MS = 30_000;
const PORT_PROBE_INTERVAL_MS = 1_000;
+const VersionResponse = Type.Object(
+ { webSocketDebuggerUrl: Type.Optional(Type.String()) },
+ { additionalProperties: true },
+);
+
+const versionValidator = Compile(VersionResponse);
+
/**
* A live CDP endpoint plus, when discovery went through a DevToolsActivePort
* file, the user-data-dir that file lives in. That directory is the browser's
@@ -76,13 +86,8 @@ const queryLiveWsUrl = (port: number, timeoutMs = 1_500): Promise<string | null>
const chunks: Buffer[] = [];
res.on("data", (c: Buffer) => chunks.push(c));
res.on("end", () => {
- try {
- const json = JSON.parse(Buffer.concat(chunks).toString("utf8")) as Record<string, unknown>;
- const ws = json["webSocketDebuggerUrl"];
- resolve(typeof ws === "string" ? ws : null);
- } catch {
- resolve(null);
- }
+ const parsed = parseJson(Buffer.concat(chunks).toString("utf8"), versionValidator);
+ resolve(parsed.success ? parsed.data.webSocketDebuggerUrl ?? null : null);
});
},
);