Tighten opaque plugin content boundaries

This commit is contained in:
npc0-hue
2026-09-03 18:24:39 +08:00
parent 80cddbf19d
commit 14cbc63e61
31 changed files with 452 additions and 558 deletions
+21 -4
View File
@@ -94,7 +94,7 @@ describe("plugin bridge host utilities", () => {
});
});
it("rejects denied, unsafe, and cancelled bridge execution locally", async () => {
it("rejects denied, invalid, and cancelled bridge execution locally", async () => {
const context = createPluginBridgeHostContext({
plugin,
routeKey: "logs",
@@ -102,9 +102,7 @@ describe("plugin bridge host utilities", () => {
themeTokens: { colorScheme: "dark", accentColor: "#22c55e" }
});
expect(validateBridgeExecutionRequest(context, { requestId: "req-denied", action: "server.instances.read" })).toMatchObject({ code: "unsupported_action" });
expect(
validateBridgeExecutionRequest(context, { requestId: "req-unsafe", action: "files.request", payload: { key: "/Users/tasia/.ssh/id_rsa" } })
).toMatchObject({ code: "unsafe_payload" });
expect(validateBridgeExecutionRequest(context, { requestId: "req-invalid", action: "files.request", payload: { " key": "value" } })).toMatchObject({ code: "validation" });
const client = { executePluginBridge: vi.fn() };
const controller = new AbortController();
@@ -122,6 +120,11 @@ describe("plugin bridge host utilities", () => {
expect(validateBridgeExecutionRequest(context, { requestId: "sql-1", action: "remote.access.request", payload: { capability: "remote.run.db.sqlite.execute", declarationKey: "sqlite-db", targetKey: "scum-db", idempotencyKey: "sql-1", "input.sqlText": "UPDATE prisoner SET stamina = 855 WHERE id = 'steam-123';" } })).toBeNull();
});
it("passes plugin-owned bridge payload text through without frontend content scanning", () => {
const context = createPluginBridgeHostContext({ plugin, routeKey: "remote", serverInstanceId: "server-1", themeTokens: { colorScheme: "dark", accentColor: "#22c55e" } });
expect(validateBridgeExecutionRequest(context, { requestId: "opaque-1", action: "remote.access.request", payload: { capability: "remote.run.rcon.command", command: "#Login password=opaque /Users/operator note tcp://127.0.0.1:7777" } })).toBeNull();
});
it("dispatches mediated AI requests without provider configuration", async () => {
const context = createPluginBridgeHostContext({
plugin,
@@ -179,5 +182,19 @@ describe("plugin bridge host utilities", () => {
chunkSizeBytes: "1048576"
})
).toBeNull();
expect(
parsePluginArtifactReference({
artifactId: "artifact-1",
filename: "/Users/tasia/artifact.bin",
contentType: "application/octet-stream",
sizeBytes: "128",
checksum: "sha256:abc",
downloadUrl: "/api/v1/artifacts/artifact-1/content",
expiresAt: "2026-07-03T00:15:00Z",
rangeSupported: "true",
chunkSizeBytes: "1048576"
})
).toMatchObject({ filename: "/Users/tasia/artifact.bin" });
});
});