diff --git a/packages/cli/src/utils/motionSpec.test.ts b/packages/cli/src/utils/motionSpec.test.ts index c336cfe6bb3..3c867fe46f4 100644 --- a/packages/cli/src/utils/motionSpec.test.ts +++ b/packages/cli/src/utils/motionSpec.test.ts @@ -47,6 +47,16 @@ describe("parseMotionSpec", () => { if (!result.ok) expect(result.errors[0]).toContain("unknown assertion kind"); }); + it.each(["constructor", "__proto__", "hasOwnProperty", "toString", "valueOf"])( + "rejects inherited validator name %s as an unknown assertion kind", + (kind) => { + expect(parseMotionSpec({ assertions: [{ kind }] })).toEqual({ + ok: false, + errors: [`assertions[0]: unknown assertion kind ${JSON.stringify(kind)}`], + }); + }, + ); + it("reports per-field errors for missing required fields", () => { const result = parseMotionSpec({ assertions: [ @@ -160,6 +170,22 @@ describe("readMotionSpec", () => { if (!result.ok) expect(result.errors[0]).toContain("no assertions"); }); + it("reports an inherited kind alongside other validation errors from a sidecar", () => { + const dir = tempDir("motion-inherited-"); + const path = join(dir, "index.motion.json"); + writeFileSync( + path, + JSON.stringify({ assertions: [{ kind: "__proto__" }, { kind: "before", a: "#a" }] }), + ); + expect(readMotionSpec(path)).toEqual({ + ok: false, + errors: [ + 'assertions[0]: unknown assertion kind "__proto__"', + 'assertions[1] (before): "b" must be a non-empty string', + ], + }); + }); + it("parses a valid sidecar file", () => { const dir = tempDir("motion-valid-"); const path = join(dir, "main.motion.json"); diff --git a/packages/cli/src/utils/motionSpec.ts b/packages/cli/src/utils/motionSpec.ts index b6dec6bab3b..dd0440f653e 100644 --- a/packages/cli/src/utils/motionSpec.ts +++ b/packages/cli/src/utils/motionSpec.ts @@ -69,7 +69,10 @@ const VALIDATORS: Record = { function validateAssertion(raw: unknown, index: number): MotionAssertion | string { const at = `assertions[${index}]`; if (!isObject(raw)) return `${at}: must be an object`; - const validator = typeof raw.kind === "string" ? VALIDATORS[raw.kind] : undefined; + const validator = + typeof raw.kind === "string" && Object.hasOwn(VALIDATORS, raw.kind) + ? VALIDATORS[raw.kind] + : undefined; if (!validator) return `${at}: unknown assertion kind ${JSON.stringify(raw.kind)}`; return validator(raw, at); }