From 34e62d8725956da3d293b325ced7bf43883dac9b Mon Sep 17 00:00:00 2001 From: diegosouzapw Date: Fri, 22 May 2026 15:09:07 -0300 Subject: [PATCH] fix(security): crypto-secure cloud-agent IDs + exact-hostname check (CodeQL #251, #252) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - #251 (Insecure randomness): baseAgent.generateTaskId/generateActivityId used Math.random().toString(36) for IDs that flow into session/external identifiers (e.g. jules.ts task externalId). Switched to crypto randomBytes(8).toString("hex"). - #252 (Incomplete URL substring sanitization): the antigravity discovery test matched the upstream host via url.includes("…googleapis.com"), which a look-alike host could bypass. Switched to an exact `new URL(url).hostname === …` comparison. --- src/lib/cloudAgent/baseAgent.ts | 7 +++++-- tests/unit/antigravity-discovery-bootstrap.test.ts | 5 ++++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/lib/cloudAgent/baseAgent.ts b/src/lib/cloudAgent/baseAgent.ts index 9f5689b90b..0acf3cb475 100644 --- a/src/lib/cloudAgent/baseAgent.ts +++ b/src/lib/cloudAgent/baseAgent.ts @@ -1,3 +1,4 @@ +import { randomBytes } from "node:crypto"; import type { CloudAgentTask, CloudAgentStatus, @@ -86,10 +87,12 @@ export abstract class CloudAgentBase { } protected generateTaskId(): string { - return `task_${Date.now()}_${Math.random().toString(36).substring(2, 11)}`; + // Cryptographically secure suffix (not Math.random) — task IDs flow into + // session/external identifiers, so they must be unpredictable (CodeQL js/insecure-randomness). + return `task_${Date.now()}_${randomBytes(8).toString("hex")}`; } protected generateActivityId(): string { - return `act_${Date.now()}_${Math.random().toString(36).substring(2, 11)}`; + return `act_${Date.now()}_${randomBytes(8).toString("hex")}`; } } diff --git a/tests/unit/antigravity-discovery-bootstrap.test.ts b/tests/unit/antigravity-discovery-bootstrap.test.ts index 3d0aa82f98..11f8c43097 100644 --- a/tests/unit/antigravity-discovery-bootstrap.test.ts +++ b/tests/unit/antigravity-discovery-bootstrap.test.ts @@ -152,7 +152,10 @@ describe("ensureAntigravityProjectAssigned", () => { const mockFetch = async (url: string, _init?: RequestInit): Promise => { hitUrls.push(url); - if (url.includes("daily-cloudcode-pa.googleapis.com")) { + // Exact hostname match (not substring .includes) so the check can't be fooled by a + // look-alike host like daily-cloudcode-pa.googleapis.com.evil.com (CodeQL + // js/incomplete-url-substring-sanitization). + if (new URL(url).hostname === "daily-cloudcode-pa.googleapis.com") { // First URL fails return new Response("not found", { status: 404 }); }