mirror of
https://github.com/moltbot/moltbot.git
synced 2026-03-08 06:54:24 +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
|
||||
|
||||
- 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/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.
|
||||
|
||||
@@ -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 () => {
|
||||
const home = await createCaseHome();
|
||||
const pluginDir = path.join(home, "bad-plugin");
|
||||
|
||||
@@ -22,6 +22,8 @@ import { findLegacyConfigIssues } from "./legacy.js";
|
||||
import type { OpenClawConfig, ConfigValidationIssue } from "./types.js";
|
||||
import { OpenClawSchema } from "./zod-schema.js";
|
||||
|
||||
const LEGACY_REMOVED_PLUGIN_IDS = new Set(["google-antigravity-auth"]);
|
||||
|
||||
function isWorkspaceAvatarPath(value: string, workspaceDir: string): boolean {
|
||||
const workspaceRoot = path.resolve(workspaceDir);
|
||||
const resolved = path.resolve(workspaceRoot, value);
|
||||
@@ -313,6 +315,19 @@ function validateConfigObjectWithPluginsBase(
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
@@ -320,10 +335,7 @@ function validateConfigObjectWithPluginsBase(
|
||||
if (entries && isRecord(entries)) {
|
||||
for (const pluginId of Object.keys(entries)) {
|
||||
if (!knownIds.has(pluginId)) {
|
||||
issues.push({
|
||||
path: `plugins.entries.${pluginId}`,
|
||||
message: `plugin not found: ${pluginId}`,
|
||||
});
|
||||
pushMissingPluginIssue(`plugins.entries.${pluginId}`, pluginId);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -334,10 +346,7 @@ function validateConfigObjectWithPluginsBase(
|
||||
continue;
|
||||
}
|
||||
if (!knownIds.has(pluginId)) {
|
||||
issues.push({
|
||||
path: "plugins.allow",
|
||||
message: `plugin not found: ${pluginId}`,
|
||||
});
|
||||
pushMissingPluginIssue("plugins.allow", pluginId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -347,19 +356,13 @@ function validateConfigObjectWithPluginsBase(
|
||||
continue;
|
||||
}
|
||||
if (!knownIds.has(pluginId)) {
|
||||
issues.push({
|
||||
path: "plugins.deny",
|
||||
message: `plugin not found: ${pluginId}`,
|
||||
});
|
||||
pushMissingPluginIssue("plugins.deny", pluginId);
|
||||
}
|
||||
}
|
||||
|
||||
const memorySlot = normalizedPlugins.slots.memory;
|
||||
if (typeof memorySlot === "string" && memorySlot.trim() && !knownIds.has(memorySlot)) {
|
||||
issues.push({
|
||||
path: "plugins.slots.memory",
|
||||
message: `plugin not found: ${memorySlot}`,
|
||||
});
|
||||
pushMissingPluginIssue("plugins.slots.memory", memorySlot);
|
||||
}
|
||||
|
||||
let selectedMemoryPluginId: string | null = null;
|
||||
|
||||
Reference in New Issue
Block a user