mirror of
https://github.com/openclaw/openclaw.git
synced 2026-06-06 05:51:15 +08:00
fix(agents): bound runtime tool list projection
This commit is contained in:
@@ -134,6 +134,32 @@ describe("runtime tool input schema projection", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("reports invalid runtime tool list lengths", () => {
|
||||
const healthy = {
|
||||
name: "healthy",
|
||||
parameters: { type: "object", properties: {} },
|
||||
};
|
||||
const proxy = new Proxy([healthy] as Array<typeof healthy>, {
|
||||
get(target, property, receiver) {
|
||||
if (property === "length") {
|
||||
return -1;
|
||||
}
|
||||
return Reflect.get(target, property, receiver);
|
||||
},
|
||||
});
|
||||
|
||||
expect(filterRuntimeCompatibleTools(proxy)).toEqual({
|
||||
tools: [],
|
||||
diagnostics: [
|
||||
{
|
||||
toolName: "tool[0]",
|
||||
toolIndex: 0,
|
||||
violations: ["runtime tool list length is invalid"],
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
it("quarantines unreadable runtime tool fields without dropping healthy siblings", () => {
|
||||
const unreadable = {
|
||||
name: "fuzzplugin_unreadable",
|
||||
|
||||
@@ -41,15 +41,18 @@ type RuntimeToolEntryRead<TTool extends Pick<AnyAgentTool, "name" | "parameters"
|
||||
|
||||
type ToolSchemaInspectionMode = "runtime" | "provider-normalizable";
|
||||
|
||||
const MAX_RUNTIME_TOOL_ENTRY_READS = 10_000;
|
||||
|
||||
function unreadableRuntimeToolEntry(
|
||||
toolIndex: number,
|
||||
violation = `tool[${toolIndex}] is unreadable`,
|
||||
): RuntimeToolEntryRead<Pick<AnyAgentTool, "name" | "parameters">> {
|
||||
return {
|
||||
ok: false,
|
||||
diagnostic: {
|
||||
toolName: `tool[${toolIndex}]`,
|
||||
toolIndex,
|
||||
violations: [`tool[${toolIndex}] is unreadable`],
|
||||
violations: [violation],
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -63,6 +66,24 @@ function readRuntimeToolEntries<TTool extends Pick<AnyAgentTool, "name" | "param
|
||||
} catch {
|
||||
return [unreadableRuntimeToolEntry(0) as RuntimeToolEntryRead<TTool>];
|
||||
}
|
||||
if (!Number.isSafeInteger(length) || length < 0) {
|
||||
return [
|
||||
unreadableRuntimeToolEntry(
|
||||
0,
|
||||
"runtime tool list length is invalid",
|
||||
) as RuntimeToolEntryRead<TTool>,
|
||||
];
|
||||
}
|
||||
// Projection is a safety check for plugin-controlled tool lists. Reject
|
||||
// hostile array-like lengths before diagnostics become an unbounded loop.
|
||||
if (length > MAX_RUNTIME_TOOL_ENTRY_READS) {
|
||||
return [
|
||||
unreadableRuntimeToolEntry(
|
||||
MAX_RUNTIME_TOOL_ENTRY_READS,
|
||||
`runtime tool list length exceeds ${MAX_RUNTIME_TOOL_ENTRY_READS}`,
|
||||
) as RuntimeToolEntryRead<TTool>,
|
||||
];
|
||||
}
|
||||
const entries: RuntimeToolEntryRead<TTool>[] = [];
|
||||
for (let toolIndex = 0; toolIndex < length; toolIndex += 1) {
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user