mirror of
https://github.com/moltbot/moltbot.git
synced 2026-04-28 08:52:45 +00:00
fix(config): soften antigravity removal fallout (#25538)
Land #25538 by @chilu18 to keep legacy google-antigravity-auth config entries non-fatal after removal (see #25862). Co-authored-by: chilu18 <chilu.machona@icloud.com>
This commit is contained in:
@@ -11,6 +11,7 @@ Docs: https://docs.openclaw.ai
|
|||||||
|
|
||||||
### Fixes
|
### Fixes
|
||||||
|
|
||||||
|
- Config/Plugins: treat stale removed `google-antigravity-auth` plugin references as compatibility warnings (not hard validation errors) across `plugins.entries`, `plugins.allow`, `plugins.deny`, and `plugins.slots.memory`, so startup no longer fails after antigravity removal. (#25538, #25862) Thanks @chilu18.
|
||||||
- Security/Workspace FS: normalize `@`-prefixed paths before workspace-boundary checks (including workspace-only read/write/edit and sandbox mount path guards), preventing absolute-path escape attempts from bypassing guard validation. This ships in the next npm release. Thanks @tdjackey for reporting.
|
- Security/Workspace FS: normalize `@`-prefixed paths before workspace-boundary checks (including workspace-only read/write/edit and sandbox mount path guards), preventing absolute-path escape attempts from bypassing guard validation. This ships in the next npm release. Thanks @tdjackey for reporting.
|
||||||
- Security/Native images: enforce `tools.fs.workspaceOnly` for native prompt image auto-load (including history refs), preventing out-of-workspace sandbox mounts from being implicitly ingested as vision input. This ships in the next npm release. Thanks @tdjackey for reporting.
|
- Security/Native images: enforce `tools.fs.workspaceOnly` for native prompt image auto-load (including history refs), preventing out-of-workspace sandbox mounts from being implicitly ingested as vision input. This ships in the next npm release. Thanks @tdjackey for reporting.
|
||||||
- Security/Exec approvals: bind `system.run` command display/approval text to full argv when shell-wrapper inline payloads carry positional argv values, and reject payload-only `rawCommand` mismatches for those wrapper-carrier forms, preventing hidden command execution under misleading approval text. This ships in the next npm release. Thanks @tdjackey for reporting.
|
- Security/Exec approvals: bind `system.run` command display/approval text to full argv when shell-wrapper inline payloads carry positional argv values, and reject payload-only `rawCommand` mismatches for those wrapper-carrier forms, preventing hidden command execution under misleading approval text. This ships in the next npm release. Thanks @tdjackey for reporting.
|
||||||
|
|||||||
@@ -103,6 +103,48 @@ describe("config plugin validation", () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("warns for removed legacy plugin ids instead of failing validation", async () => {
|
||||||
|
const home = await createCaseHome();
|
||||||
|
const removedId = "google-antigravity-auth";
|
||||||
|
const res = validateInHome(home, {
|
||||||
|
agents: { list: [{ id: "pi" }] },
|
||||||
|
plugins: {
|
||||||
|
enabled: false,
|
||||||
|
entries: { [removedId]: { enabled: true } },
|
||||||
|
allow: [removedId],
|
||||||
|
deny: [removedId],
|
||||||
|
slots: { memory: removedId },
|
||||||
|
},
|
||||||
|
});
|
||||||
|
expect(res.ok).toBe(true);
|
||||||
|
if (res.ok) {
|
||||||
|
expect(res.warnings).toEqual(
|
||||||
|
expect.arrayContaining([
|
||||||
|
{
|
||||||
|
path: `plugins.entries.${removedId}`,
|
||||||
|
message:
|
||||||
|
"plugin removed: google-antigravity-auth (stale config entry ignored; remove it from plugins config)",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "plugins.allow",
|
||||||
|
message:
|
||||||
|
"plugin removed: google-antigravity-auth (stale config entry ignored; remove it from plugins config)",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "plugins.deny",
|
||||||
|
message:
|
||||||
|
"plugin removed: google-antigravity-auth (stale config entry ignored; remove it from plugins config)",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "plugins.slots.memory",
|
||||||
|
message:
|
||||||
|
"plugin removed: google-antigravity-auth (stale config entry ignored; remove it from plugins config)",
|
||||||
|
},
|
||||||
|
]),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
it("surfaces plugin config diagnostics", async () => {
|
it("surfaces plugin config diagnostics", async () => {
|
||||||
const home = await createCaseHome();
|
const home = await createCaseHome();
|
||||||
const pluginDir = path.join(home, "bad-plugin");
|
const pluginDir = path.join(home, "bad-plugin");
|
||||||
|
|||||||
@@ -22,6 +22,8 @@ import { findLegacyConfigIssues } from "./legacy.js";
|
|||||||
import type { OpenClawConfig, ConfigValidationIssue } from "./types.js";
|
import type { OpenClawConfig, ConfigValidationIssue } from "./types.js";
|
||||||
import { OpenClawSchema } from "./zod-schema.js";
|
import { OpenClawSchema } from "./zod-schema.js";
|
||||||
|
|
||||||
|
const LEGACY_REMOVED_PLUGIN_IDS = new Set(["google-antigravity-auth"]);
|
||||||
|
|
||||||
function isWorkspaceAvatarPath(value: string, workspaceDir: string): boolean {
|
function isWorkspaceAvatarPath(value: string, workspaceDir: string): boolean {
|
||||||
const workspaceRoot = path.resolve(workspaceDir);
|
const workspaceRoot = path.resolve(workspaceDir);
|
||||||
const resolved = path.resolve(workspaceRoot, value);
|
const resolved = path.resolve(workspaceRoot, value);
|
||||||
@@ -313,6 +315,19 @@ function validateConfigObjectWithPluginsBase(
|
|||||||
}
|
}
|
||||||
|
|
||||||
const { registry, knownIds, normalizedPlugins } = ensureRegistry();
|
const { registry, knownIds, normalizedPlugins } = ensureRegistry();
|
||||||
|
const pushMissingPluginIssue = (path: string, pluginId: string) => {
|
||||||
|
if (LEGACY_REMOVED_PLUGIN_IDS.has(pluginId)) {
|
||||||
|
warnings.push({
|
||||||
|
path,
|
||||||
|
message: `plugin removed: ${pluginId} (stale config entry ignored; remove it from plugins config)`,
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
issues.push({
|
||||||
|
path,
|
||||||
|
message: `plugin not found: ${pluginId}`,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const pluginsConfig = config.plugins;
|
const pluginsConfig = config.plugins;
|
||||||
|
|
||||||
@@ -320,10 +335,7 @@ function validateConfigObjectWithPluginsBase(
|
|||||||
if (entries && isRecord(entries)) {
|
if (entries && isRecord(entries)) {
|
||||||
for (const pluginId of Object.keys(entries)) {
|
for (const pluginId of Object.keys(entries)) {
|
||||||
if (!knownIds.has(pluginId)) {
|
if (!knownIds.has(pluginId)) {
|
||||||
issues.push({
|
pushMissingPluginIssue(`plugins.entries.${pluginId}`, pluginId);
|
||||||
path: `plugins.entries.${pluginId}`,
|
|
||||||
message: `plugin not found: ${pluginId}`,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -334,10 +346,7 @@ function validateConfigObjectWithPluginsBase(
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!knownIds.has(pluginId)) {
|
if (!knownIds.has(pluginId)) {
|
||||||
issues.push({
|
pushMissingPluginIssue("plugins.allow", pluginId);
|
||||||
path: "plugins.allow",
|
|
||||||
message: `plugin not found: ${pluginId}`,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -347,19 +356,13 @@ function validateConfigObjectWithPluginsBase(
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!knownIds.has(pluginId)) {
|
if (!knownIds.has(pluginId)) {
|
||||||
issues.push({
|
pushMissingPluginIssue("plugins.deny", pluginId);
|
||||||
path: "plugins.deny",
|
|
||||||
message: `plugin not found: ${pluginId}`,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const memorySlot = normalizedPlugins.slots.memory;
|
const memorySlot = normalizedPlugins.slots.memory;
|
||||||
if (typeof memorySlot === "string" && memorySlot.trim() && !knownIds.has(memorySlot)) {
|
if (typeof memorySlot === "string" && memorySlot.trim() && !knownIds.has(memorySlot)) {
|
||||||
issues.push({
|
pushMissingPluginIssue("plugins.slots.memory", memorySlot);
|
||||||
path: "plugins.slots.memory",
|
|
||||||
message: `plugin not found: ${memorySlot}`,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let selectedMemoryPluginId: string | null = null;
|
let selectedMemoryPluginId: string | null = null;
|
||||||
|
|||||||
Reference in New Issue
Block a user