fix(config): keep write inputs immutable when using unsetPaths (#24134)

Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 951f8480c3
Co-authored-by: frankekn <4488090+frankekn@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
This commit is contained in:
Frank Yang
2026-02-22 23:51:13 -08:00
committed by GitHub
parent 0e28e50b45
commit f208518cb9
5 changed files with 268 additions and 70 deletions

View File

@@ -204,6 +204,35 @@ describe("config cli", () => {
});
});
describe("path hardening", () => {
it("rejects blocked prototype-key segments for config get", async () => {
await expect(runConfigCommand(["config", "get", "gateway.__proto__.token"])).rejects.toThrow(
"Invalid path segment: __proto__",
);
expect(mockReadConfigFileSnapshot).not.toHaveBeenCalled();
expect(mockWriteConfigFile).not.toHaveBeenCalled();
});
it("rejects blocked prototype-key segments for config set", async () => {
await expect(
runConfigCommand(["config", "set", "tools.constructor.profile", '"sandbox"']),
).rejects.toThrow("Invalid path segment: constructor");
expect(mockReadConfigFileSnapshot).not.toHaveBeenCalled();
expect(mockWriteConfigFile).not.toHaveBeenCalled();
});
it("rejects blocked prototype-key segments for config unset", async () => {
await expect(
runConfigCommand(["config", "unset", "channels.prototype.enabled"]),
).rejects.toThrow("Invalid path segment: prototype");
expect(mockReadConfigFileSnapshot).not.toHaveBeenCalled();
expect(mockWriteConfigFile).not.toHaveBeenCalled();
});
});
describe("config unset - issue #6070", () => {
it("preserves existing config keys when unsetting a value", async () => {
const resolved: OpenClawConfig = {