mirror of
https://github.com/openclaw/openclaw.git
synced 2026-07-04 17:33:40 +00:00
* fix(config): stop config.patch replacePaths index suffix from widening array consent normalizeConfigPatchReplacePath stripped a trailing array bracket, so an entry/index-scoped token like bindings[0] or bindings[] collapsed onto the bare whole-array token (bindings). That bare token is both the merge replaceArrayPaths key and the destructive-array gate's exact-path token, so an index-scoped consent silently authorized a full-array replacement and dropped unrelated base entries on the gateway config.patch path, and the same collapse let the agent self-edit tool truncate id-keyed arrays whenever no protected path happened to be involved. Keep the interior index normalization (agents.list[0].skills -> agents.list[].skills) but no longer collapse a trailing bracket, so a bracket/index-suffixed token never matches the bare whole-array token and the destructive-array gate stays fail-closed unless the documented exact path is passed. Update the agent-tool test whose expectation depended on the old collapse: agents.list[0] now does a non-destructive id-keyed merge that only changes model and is correctly allowed. * fix(config): distinguish indexed and array replace consent * test(config): cover replace consent syntax * fix(config): make replace path normalization idempotent --------- Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
23 lines
690 B
TypeScript
23 lines
690 B
TypeScript
// Normalizes config.patch replacePaths shared by Gateway and agent preflight checks.
|
|
export function normalizeConfigPatchReplacePath(value: string): string {
|
|
const trimmed = value.trim();
|
|
if (trimmed.endsWith("[]")) {
|
|
return trimmed.slice(0, -2).replace(/\[\d+\](?=\.)/g, "[]");
|
|
}
|
|
return trimmed.replace(/\[\d+\](?=\.)/g, "[]");
|
|
}
|
|
|
|
export function normalizeConfigPatchReplacePaths(
|
|
values: readonly unknown[] | undefined,
|
|
): Set<string> {
|
|
if (!values) {
|
|
return new Set();
|
|
}
|
|
return new Set(
|
|
values
|
|
.filter((value): value is string => typeof value === "string")
|
|
.map(normalizeConfigPatchReplacePath)
|
|
.filter((value) => value.length > 0),
|
|
);
|
|
}
|