feat(agent): 完善权限与结果引用安全

This commit is contained in:
2026-08-06 18:41:52 +08:00
parent a5e91ac2b8
commit b19af8846a
22 changed files with 621 additions and 47 deletions
+49 -2
View File
@@ -1,5 +1,5 @@
import { afterEach, beforeEach, describe, expect, it } from "bun:test";
import { mkdtemp, rm, writeFile } from "node:fs/promises";
import { mkdtemp, rm, stat, writeFile } from "node:fs/promises";
import { tmpdir } from "node:os";
import { join } from "node:path";
@@ -18,7 +18,7 @@ describe("ResultReferenceResolver", () => {
beforeEach(async () => {
tempDir = await mkdtemp(join(tmpdir(), "tjwater-result-ref-"));
store = new ResultReferenceStore(tempDir, 60_000);
resolver = new ResultReferenceResolver(store);
resolver = new ResultReferenceResolver(store, tempDir, 1024 * 1024);
await store.initialize();
});
@@ -193,6 +193,53 @@ describe("ResultReferenceResolver", () => {
"DMA-2": "#00ff00",
},
});
await expect(stat(filePath)).rejects.toThrow();
});
it("rejects render payload files outside the configured import directory", async () => {
const outsideDir = await mkdtemp(join(tmpdir(), "tjwater-result-outside-"));
const filePath = join(outsideDir, "render-wrapper.json");
await writeFile(
filePath,
JSON.stringify({
metadata: {},
location: { file_path: filePath },
data: { node_area_map: { J1: "DMA-1" } },
}),
"utf8",
);
try {
await expect(
resolver.registerRenderPayloadFile(filePath, {
actorKey: "actor-4",
clientSessionId: "client-4",
projectKey: "project-key-4",
sessionId: "session-4",
source: RESULT_REFERENCE_SOURCE.agentGenerated,
traceId: "trace-4",
}),
).rejects.toThrow("RESULT_REF_IMPORT_DIR");
} finally {
await rm(outsideDir, { force: true, recursive: true });
}
});
it("rejects oversized render payload files before parsing", async () => {
const filePath = join(tempDir, "oversized.json");
await writeFile(filePath, "x".repeat(128), "utf8");
const sizeLimitedResolver = new ResultReferenceResolver(store, tempDir, 64);
await expect(
sizeLimitedResolver.registerRenderPayloadFile(filePath, {
actorKey: "actor-5",
clientSessionId: "client-5",
projectKey: "project-key-5",
sessionId: "session-5",
source: RESULT_REFERENCE_SOURCE.agentGenerated,
traceId: "trace-5",
}),
).rejects.toThrow("RESULT_REF_IMPORT_MAX_BYTES");
});
});