From e07c33d82db12fdd8d6ff17cec6be712d3f2c2ac Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Sun, 10 May 2026 13:03:14 +0100 Subject: [PATCH] test: clear file-transfer policy broad matchers --- .../file-transfer/src/shared/policy.test.ts | 81 +++++++++++-------- 1 file changed, 49 insertions(+), 32 deletions(-) diff --git a/extensions/file-transfer/src/shared/policy.test.ts b/extensions/file-transfer/src/shared/policy.test.ts index 6e37474d067..5aa47a81c1c 100644 --- a/extensions/file-transfer/src/shared/policy.test.ts +++ b/extensions/file-transfer/src/shared/policy.test.ts @@ -50,23 +50,35 @@ function withConfig(fileTransfer: Record | undefined) { } } +function expectResultFields(result: unknown, fields: Record) { + expect(typeof result).toBe("object"); + expect(result).not.toBeNull(); + if (typeof result !== "object" || result === null) { + throw new Error("policy result was not an object"); + } + const record = result as Record; + for (const [key, value] of Object.entries(fields)) { + expect(record[key]).toEqual(value); + } +} + describe("evaluateFilePolicy — default deny", () => { it("returns NO_POLICY when no plugin config block is present", () => { getRuntimeConfigMock.mockReturnValue({}); const r = evaluateFilePolicy({ nodeId: "n1", kind: "read", path: "/tmp/x" }); - expect(r).toMatchObject({ ok: false, code: "NO_POLICY", askable: false }); + expectResultFields(r, { ok: false, code: "NO_POLICY", askable: false }); }); it("returns NO_POLICY when plugin policy block is missing", () => { getRuntimeConfigMock.mockReturnValue({ plugins: { entries: { "file-transfer": {} } } }); const r = evaluateFilePolicy({ nodeId: "n1", kind: "read", path: "/tmp/x" }); - expect(r).toMatchObject({ ok: false, code: "NO_POLICY" }); + expectResultFields(r, { ok: false, code: "NO_POLICY" }); }); it("returns NO_POLICY when no entry exists for the node and no '*' fallback", () => { withConfig({ "other-node": { allowReadPaths: ["/tmp/**"] } }); const r = evaluateFilePolicy({ nodeId: "n1", kind: "read", path: "/tmp/x" }); - expect(r).toMatchObject({ ok: false, code: "NO_POLICY" }); + expectResultFields(r, { ok: false, code: "NO_POLICY" }); }); it("prefers the current runtime config over a stale passed plugin config", () => { @@ -93,7 +105,7 @@ describe("evaluateFilePolicy — default deny", () => { }, }, }); - expect(r).toMatchObject({ ok: true, reason: "matched-allow" }); + expectResultFields(r, { ok: true, reason: "matched-allow" }); }); }); @@ -107,7 +119,7 @@ describe("evaluateFilePolicy — '..' traversal short-circuit", () => { kind: "read", path: "/allowed/../etc/passwd", }); - expect(r).toMatchObject({ ok: false, code: "POLICY_DENIED", askable: false }); + expectResultFields(r, { ok: false, code: "POLICY_DENIED", askable: false }); expect(r.ok ? "" : r.reason).toMatch(/\.\./); }); @@ -120,7 +132,7 @@ describe("evaluateFilePolicy — '..' traversal short-circuit", () => { kind: "read", path: "/tmp/foo/..", }); - expect(r).toMatchObject({ ok: false, code: "POLICY_DENIED" }); + expectResultFields(r, { ok: false, code: "POLICY_DENIED" }); }); it("rejects bare '..'", () => { @@ -128,7 +140,7 @@ describe("evaluateFilePolicy — '..' traversal short-circuit", () => { n1: { allowReadPaths: ["/**"] }, }); const r = evaluateFilePolicy({ nodeId: "n1", kind: "read", path: ".." }); - expect(r).toMatchObject({ ok: false, code: "POLICY_DENIED" }); + expectResultFields(r, { ok: false, code: "POLICY_DENIED" }); }); }); @@ -145,7 +157,7 @@ describe("evaluateFilePolicy — denyPaths always wins", () => { kind: "read", path: "/tmp/.ssh/id_rsa", }); - expect(r).toMatchObject({ ok: false, code: "POLICY_DENIED", askable: false }); + expectResultFields(r, { ok: false, code: "POLICY_DENIED", askable: false }); expect(r.ok ? "" : r.reason).toMatch(/deny/); }); @@ -161,7 +173,7 @@ describe("evaluateFilePolicy — denyPaths always wins", () => { kind: "read", path: "/var/secrets/api.key", }); - expect(r).toMatchObject({ ok: false, code: "POLICY_DENIED", askable: false }); + expectResultFields(r, { ok: false, code: "POLICY_DENIED", askable: false }); }); }); @@ -183,26 +195,27 @@ describe("evaluateFilePolicy — allow matching", () => { n1: { allowReadPaths: ["/tmp/**"], maxBytes: 1024 }, }); const r = evaluateFilePolicy({ nodeId: "n1", kind: "read", path: "/tmp/x" }); - expect(r).toMatchObject({ ok: true, maxBytes: 1024 }); + expectResultFields(r, { ok: true, maxBytes: 1024 }); }); it("uses kind=write to consult allowWritePaths, not allowReadPaths", () => { withConfig({ n1: { allowReadPaths: ["/tmp/**"], allowWritePaths: ["/srv/**"] }, }); - expect(evaluateFilePolicy({ nodeId: "n1", kind: "write", path: "/srv/out.txt" })).toMatchObject( - { ok: true }, - ); - expect(evaluateFilePolicy({ nodeId: "n1", kind: "write", path: "/tmp/out.txt" })).toMatchObject( - { ok: false, code: "POLICY_DENIED" }, - ); + expectResultFields(evaluateFilePolicy({ nodeId: "n1", kind: "write", path: "/srv/out.txt" }), { + ok: true, + }); + expectResultFields(evaluateFilePolicy({ nodeId: "n1", kind: "write", path: "/tmp/out.txt" }), { + ok: false, + code: "POLICY_DENIED", + }); }); it("propagates followSymlinks=false by default and =true when configured", () => { withConfig({ n1: { allowReadPaths: ["/tmp/**"] }, }); - expect(evaluateFilePolicy({ nodeId: "n1", kind: "read", path: "/tmp/x" })).toMatchObject({ + expectResultFields(evaluateFilePolicy({ nodeId: "n1", kind: "read", path: "/tmp/x" }), { ok: true, followSymlinks: false, }); @@ -210,7 +223,7 @@ describe("evaluateFilePolicy — allow matching", () => { withConfig({ n2: { allowReadPaths: ["/tmp/**"], followSymlinks: true }, }); - expect(evaluateFilePolicy({ nodeId: "n2", kind: "read", path: "/tmp/x" })).toMatchObject({ + expectResultFields(evaluateFilePolicy({ nodeId: "n2", kind: "read", path: "/tmp/x" }), { ok: true, followSymlinks: true, }); @@ -221,26 +234,28 @@ describe("evaluateFilePolicy — allow matching", () => { withConfig({ n1: { allowReadPaths: ["~/Screenshots/**"] }, }); - expect( + expectResultFields( evaluateFilePolicy({ nodeId: "n1", kind: "read", path: path.join(home, "Screenshots", "shot.png"), }), - ).toMatchObject({ ok: true }); + { ok: true }, + ); }); it("matches Windows node paths without gateway-local path semantics", () => { withConfig({ n1: { allowReadPaths: ["C:/Users/me/**"] }, }); - expect( + expectResultFields( evaluateFilePolicy({ nodeId: "n1", kind: "read", path: "C:\\Users\\me\\file.txt", }), - ).toMatchObject({ ok: true }); + { ok: true }, + ); }); }); @@ -250,7 +265,7 @@ describe("evaluateFilePolicy — ask modes", () => { n1: { ask: "on-miss", allowReadPaths: ["/var/log/**"] }, }); const r = evaluateFilePolicy({ nodeId: "n1", kind: "read", path: "/tmp/x" }); - expect(r).toMatchObject({ + expectResultFields(r, { ok: false, code: "POLICY_DENIED", askable: true, @@ -268,7 +283,7 @@ describe("evaluateFilePolicy — ask modes", () => { }, }); const r = evaluateFilePolicy({ nodeId: "n1", kind: "read", path: "/tmp/x" }); - expect(r).toMatchObject({ + expectResultFields(r, { ok: false, code: "POLICY_DENIED", askable: true, @@ -283,7 +298,7 @@ describe("evaluateFilePolicy — ask modes", () => { n1: { ask: "on-miss", allowReadPaths: ["/tmp/**"] }, }); const r = evaluateFilePolicy({ nodeId: "n1", kind: "read", path: "/tmp/x" }); - expect(r).toMatchObject({ ok: true, reason: "matched-allow" }); + expectResultFields(r, { ok: true, reason: "matched-allow" }); }); it("ask=always always returns ask-always (prompt on every call)", () => { @@ -291,7 +306,7 @@ describe("evaluateFilePolicy — ask modes", () => { n1: { ask: "always", allowReadPaths: ["/tmp/**"] }, }); const r = evaluateFilePolicy({ nodeId: "n1", kind: "read", path: "/tmp/x" }); - expect(r).toMatchObject({ ok: true, reason: "ask-always", askMode: "always" }); + expectResultFields(r, { ok: true, reason: "ask-always", askMode: "always" }); }); it("ask=off returns non-askable POLICY_DENIED on miss", () => { @@ -299,7 +314,7 @@ describe("evaluateFilePolicy — ask modes", () => { n1: { ask: "off", allowReadPaths: ["/var/log/**"] }, }); const r = evaluateFilePolicy({ nodeId: "n1", kind: "read", path: "/tmp/x" }); - expect(r).toMatchObject({ ok: false, code: "POLICY_DENIED", askable: false }); + expectResultFields(r, { ok: false, code: "POLICY_DENIED", askable: false }); }); it("invalid ask values normalize to off", () => { @@ -307,7 +322,7 @@ describe("evaluateFilePolicy — ask modes", () => { n1: { ask: "sometimes", allowReadPaths: ["/var/log/**"] }, }); const r = evaluateFilePolicy({ nodeId: "n1", kind: "read", path: "/tmp/x" }); - expect(r).toMatchObject({ ok: false, askable: false }); + expectResultFields(r, { ok: false, askable: false }); }); }); @@ -316,28 +331,30 @@ describe("evaluateFilePolicy — node-id resolution", () => { withConfig({ "Lobster MacBook": { allowReadPaths: ["/tmp/**"] }, }); - expect( + expectResultFields( evaluateFilePolicy({ nodeId: "node-abc-123", nodeDisplayName: "Lobster MacBook", kind: "read", path: "/tmp/x", }), - ).toMatchObject({ ok: true }); + { ok: true }, + ); }); it("falls back to '*' wildcard when neither id nor displayName matches", () => { withConfig({ "*": { allowReadPaths: ["/tmp/**"] }, }); - expect( + expectResultFields( evaluateFilePolicy({ nodeId: "n1", nodeDisplayName: "anything", kind: "read", path: "/tmp/x", }), - ).toMatchObject({ ok: true }); + { ok: true }, + ); }); });