mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-03 11:50:22 +00:00
fix(security): avoid prototype-chain account path checks (#34982)
Merged via squash.
Prepared head SHA: f89cc6a649
Co-authored-by: HOYALIM <166576253+HOYALIM@users.noreply.github.com>
Co-authored-by: dvrshil <81693876+dvrshil@users.noreply.github.com>
Reviewed-by: @dvrshil
This commit is contained in:
@@ -1,11 +1,11 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import type { TranslationMap } from "../../ui/src/i18n/lib/types.ts";
|
||||
import {
|
||||
DEFAULT_LOCALE,
|
||||
SUPPORTED_LOCALES,
|
||||
loadLazyLocaleTranslation,
|
||||
resolveNavigatorLocale,
|
||||
} from "../../ui/src/i18n/lib/registry.ts";
|
||||
import type { TranslationMap } from "../../ui/src/i18n/lib/types.ts";
|
||||
|
||||
function getNestedTranslation(map: TranslationMap | null, ...path: string[]): string | undefined {
|
||||
let value: string | TranslationMap | undefined = map ?? undefined;
|
||||
|
||||
@@ -108,7 +108,7 @@ function hasExplicitProviderAccountConfig(
|
||||
if (!accounts || typeof accounts !== "object") {
|
||||
return false;
|
||||
}
|
||||
return accountId in accounts;
|
||||
return Object.hasOwn(accounts, accountId);
|
||||
}
|
||||
|
||||
export async function collectChannelSecurityFindings(params: {
|
||||
|
||||
@@ -1998,6 +1998,51 @@ description: test skill
|
||||
});
|
||||
});
|
||||
|
||||
it("does not treat prototype properties as explicit Discord account config paths", async () => {
|
||||
await withChannelSecurityStateDir(async () => {
|
||||
const cfg: OpenClawConfig = {
|
||||
channels: {
|
||||
discord: {
|
||||
enabled: true,
|
||||
token: "t",
|
||||
dangerouslyAllowNameMatching: true,
|
||||
allowFrom: ["Alice#1234"],
|
||||
accounts: {},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const pluginWithProtoDefaultAccount: ChannelPlugin = {
|
||||
...discordPlugin,
|
||||
config: {
|
||||
...discordPlugin.config,
|
||||
listAccountIds: () => [],
|
||||
defaultAccountId: () => "toString",
|
||||
},
|
||||
};
|
||||
|
||||
const res = await runSecurityAudit({
|
||||
config: cfg,
|
||||
includeFilesystem: false,
|
||||
includeChannelSecurity: true,
|
||||
plugins: [pluginWithProtoDefaultAccount],
|
||||
});
|
||||
|
||||
const dangerousMatchingFinding = res.findings.find(
|
||||
(entry) => entry.checkId === "channels.discord.allowFrom.dangerous_name_matching_enabled",
|
||||
);
|
||||
expect(dangerousMatchingFinding).toBeDefined();
|
||||
expect(dangerousMatchingFinding?.title).not.toContain("(account: toString)");
|
||||
|
||||
const nameBasedFinding = res.findings.find(
|
||||
(entry) => entry.checkId === "channels.discord.allowFrom.name_based_entries",
|
||||
);
|
||||
expect(nameBasedFinding).toBeDefined();
|
||||
expect(nameBasedFinding?.detail).toContain("channels.discord.allowFrom:Alice#1234");
|
||||
expect(nameBasedFinding?.detail).not.toContain("channels.discord.accounts.toString");
|
||||
});
|
||||
});
|
||||
|
||||
it("audits name-based allowlists on non-default Discord accounts", async () => {
|
||||
await withChannelSecurityStateDir(async () => {
|
||||
const cfg: OpenClawConfig = {
|
||||
|
||||
Reference in New Issue
Block a user