From 6abc3cec883552880d933a2d348dcb551ee0855e Mon Sep 17 00:00:00 2001 From: Dong Liu Date: Fri, 12 Jun 2026 00:04:11 +0000 Subject: [PATCH] fix(validators): isSchemaKind no longer accepts inherited prototype keys 'value in schemas' walks the prototype chain, so inherited keys like "toString" passed assertSchemaKind and then crashed ajv.compile with a misleading 'schema must be object or boolean' error (e.g. via the CLI). Use Object.hasOwn for an own-property check. Adds unit tests rejecting prototype keys and asserting every real schema kind still passes. Fixes #13 --- packages/validators/src/index.test.ts | 19 ++++++++++++++++++- packages/validators/src/schemas.ts | 2 +- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/packages/validators/src/index.test.ts b/packages/validators/src/index.test.ts index 76304b4..947480b 100644 --- a/packages/validators/src/index.test.ts +++ b/packages/validators/src/index.test.ts @@ -2,7 +2,8 @@ import { readFileSync } from "node:fs"; import { dirname, resolve } from "node:path"; import { fileURLToPath } from "node:url"; import { describe, expect, it } from "vitest"; -import { parseDocument, validate } from "./index.js"; +import { assertSchemaKind, parseDocument, schemas, validate } from "./index.js"; +import { isSchemaKind } from "./schemas.js"; describe("LogicSRC validators", () => { it("validates the task fixture", () => { @@ -26,3 +27,19 @@ describe("LogicSRC validators", () => { expect(result.ok).toBe(false); }); }); + +describe("isSchemaKind / assertSchemaKind prototype safety", () => { + it("rejects inherited Object.prototype keys", () => { + for (const key of ["toString", "constructor", "valueOf", "hasOwnProperty"]) { + expect(isSchemaKind(key)).toBe(false); + expect(() => assertSchemaKind(key)).toThrow(/Unknown schema kind/); + } + }); + + it("still accepts every real schema kind", () => { + for (const key of Object.keys(schemas)) { + expect(isSchemaKind(key)).toBe(true); + expect(assertSchemaKind(key)).toBe(key); + } + }); +}); diff --git a/packages/validators/src/schemas.ts b/packages/validators/src/schemas.ts index b8f026c..18575da 100644 --- a/packages/validators/src/schemas.ts +++ b/packages/validators/src/schemas.ts @@ -27,5 +27,5 @@ export const schemas = { export type SchemaKind = keyof typeof schemas; export function isSchemaKind(value: string): value is SchemaKind { - return value in schemas; + return Object.hasOwn(schemas, value); }