From b25859caf339ac3e9ad62c9bbc1f9ac9b6dc0942 Mon Sep 17 00:00:00 2001 From: Aniruddha Adak Date: Sat, 3 Oct 2026 10:13:20 +0530 Subject: [PATCH] fix(compute): reject prototype keys as a doctor target `provider()` guarded the reviewed broker table with `in`, which also matches Object.prototype members. A target such as "toString" or "constructor" passed the guard, so `DOCTOR_SPECS[target]` returned an inherited function instead of a Spec: `spec.cli` read as undefined and reached the executable attestation path, and `doctor()` recorded a failed connection check for a provider that does not exist. Use an own-property check, the idiom already used elsewhere in the CLI. --- CHANGELOG.md | 2 ++ backend/cli/src/compute/provider-cli.ts | 6 +++++- backend/cli/test/tool/provider-compute.test.ts | 11 +++++++++++ 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a38e52207..d3afb108a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,8 @@ tagged release also ships native binaries for Linux, macOS, and Windows. - Fix duration day/minute boundaries, file directory and extension labels, and payload-size rounding. Unknown payload sizes now display clearly. Background queues process undefined items, reject invalid concurrency, and release timeout timers when an operation fails. +- Reject inherited object property names as compute provider doctor targets instead of treating them as reviewed CLI brokers. + - Expand account, privacy, and usage documentation; clarify prepaid Ace access, fixed optional reloads, and current account requirements. ### Changed diff --git a/backend/cli/src/compute/provider-cli.ts b/backend/cli/src/compute/provider-cli.ts index 79bce95c8..d6d83fc11 100644 --- a/backend/cli/src/compute/provider-cli.ts +++ b/backend/cli/src/compute/provider-cli.ts @@ -241,7 +241,11 @@ export namespace ProviderCli { function provider(target: string): Provider { const canonical = target === "prime" ? "prime_intellect" : target - if (!(canonical in DOCTOR_SPECS)) throw new Error(`Compute provider ${target} has no reviewed native CLI broker`) + // An own-property check: `in` also matches Object.prototype keys, so + // "toString" or "constructor" would otherwise resolve to an inherited + // member instead of a Spec and reach the executable attestation path. + if (!Object.hasOwn(DOCTOR_SPECS, canonical)) + throw new Error(`Compute provider ${target} has no reviewed native CLI broker`) return canonical as Provider } diff --git a/backend/cli/test/tool/provider-compute.test.ts b/backend/cli/test/tool/provider-compute.test.ts index c7d7353b1..ab39ba9b2 100644 --- a/backend/cli/test/tool/provider-compute.test.ts +++ b/backend/cli/test/tool/provider-compute.test.ts @@ -55,6 +55,17 @@ test("provider_compute owns every executable and exact official read argv", () = expect(() => ProviderCli.preview("lambda", "resource_status", "../../account")).toThrow("requires") }) +test("provider_compute rejects inherited Object.prototype names instead of reading them as a Spec", () => { + // `in` also matches prototype keys, so these names used to pass the provider + // guard and then fail deep in the operation grammar as an unknown provider. + for (const key of ["toString", "constructor", "hasOwnProperty", "valueOf", "__proto__", "isPrototypeOf"]) { + expect(() => ProviderCli.preview(key, "list_resources")).toThrow("has no reviewed native CLI broker") + } + // The reviewed names, including the documented alias, still resolve. + expect(ProviderCli.preview("prime", "list_resources").provider).toBe("prime_intellect") + expect(ProviderCli.preview("tensorpool", "list_resources").cli).toBe("tp") +}) + test("provider_compute asks on the exact read before resolving a saved credential and forwards cancellation", async () => { const asked: Parameters[0][] = [] const calls: unknown[][] = []