fix(cron): prevent isolated hook session-key double-prefixing (land #27333, @MaheshBhushan)
Co-authored-by: MaheshBhushan <mkoduri73@gmail.com>
This commit is contained in:
@@ -13,6 +13,7 @@ Docs: https://docs.openclaw.ai
|
||||
|
||||
### Fixes
|
||||
|
||||
- Cron/Hooks isolated routing: preserve canonical `agent:*` session keys in isolated runs so already-qualified keys are not double-prefixed (for example `agent:main:main` no longer becomes `agent:main:agent:main:main`). Landed from contributor PR #27333 by @MaheshBhushan. (#27289, #27282)
|
||||
- Security/Plugin channel HTTP auth: normalize protected `/api/channels` path checks against canonicalized request paths (case + percent-decoding + slash normalization), and fail closed on malformed `%`-encoded channel prefixes so alternate-path variants cannot bypass gateway auth.
|
||||
- Security/Exec approvals forwarding: prefer turn-source channel/account/thread metadata when resolving approval delivery targets so stale session routes do not misroute approval prompts.
|
||||
- Onboarding/Gateway: seed default Control UI `allowedOrigins` for non-loopback binds during onboarding (`localhost`/`127.0.0.1` plus custom bind host) so fresh non-loopback setups do not fail startup due to missing origin policy. (#26157) thanks @stakeswky.
|
||||
|
||||
28
src/cron/isolated-agent/run.session-key.test.ts
Normal file
28
src/cron/isolated-agent/run.session-key.test.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { resolveCronAgentSessionKey } from "./run.js";
|
||||
|
||||
describe("resolveCronAgentSessionKey", () => {
|
||||
it("builds an agent-scoped key for legacy aliases", () => {
|
||||
expect(resolveCronAgentSessionKey({ sessionKey: "main", agentId: "main" })).toBe(
|
||||
"agent:main:main",
|
||||
);
|
||||
});
|
||||
|
||||
it("preserves canonical agent keys instead of prefixing twice", () => {
|
||||
expect(resolveCronAgentSessionKey({ sessionKey: "agent:main:main", agentId: "main" })).toBe(
|
||||
"agent:main:main",
|
||||
);
|
||||
});
|
||||
|
||||
it("normalizes canonical keys to lowercase before reuse", () => {
|
||||
expect(
|
||||
resolveCronAgentSessionKey({ sessionKey: "AGENT:Main:Hook:Webhook:42", agentId: "x" }),
|
||||
).toBe("agent:main:hook:webhook:42");
|
||||
});
|
||||
|
||||
it("keeps hook keys scoped under the target agent", () => {
|
||||
expect(resolveCronAgentSessionKey({ sessionKey: "hook:webhook:42", agentId: "main" })).toBe(
|
||||
"agent:main:hook:webhook:42",
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -40,7 +40,11 @@ import {
|
||||
import type { AgentDefaultsConfig } from "../../config/types.js";
|
||||
import { registerAgentRunContext } from "../../infra/agent-events.js";
|
||||
import { logWarn } from "../../logger.js";
|
||||
import { buildAgentMainSessionKey, normalizeAgentId } from "../../routing/session-key.js";
|
||||
import {
|
||||
buildAgentMainSessionKey,
|
||||
normalizeAgentId,
|
||||
parseAgentSessionKey,
|
||||
} from "../../routing/session-key.js";
|
||||
import {
|
||||
buildSafeExternalPrompt,
|
||||
detectSuspiciousPatterns,
|
||||
@@ -142,10 +146,7 @@ export async function runCronIsolatedAgentTurn(params: {
|
||||
};
|
||||
|
||||
const baseSessionKey = (params.sessionKey?.trim() || `cron:${params.job.id}`).trim();
|
||||
const agentSessionKey = buildAgentMainSessionKey({
|
||||
agentId,
|
||||
mainKey: baseSessionKey,
|
||||
});
|
||||
const agentSessionKey = resolveCronAgentSessionKey({ sessionKey: baseSessionKey, agentId });
|
||||
|
||||
const workspaceDirRaw = resolveAgentWorkspaceDir(params.cfg, agentId);
|
||||
const agentDir = resolveAgentDir(params.cfg, agentId);
|
||||
@@ -646,3 +647,18 @@ export async function runCronIsolatedAgentTurn(params: {
|
||||
|
||||
return resolveRunOutcome({ delivered, deliveryAttempted });
|
||||
}
|
||||
|
||||
export function resolveCronAgentSessionKey(params: {
|
||||
sessionKey: string;
|
||||
agentId: string;
|
||||
}): string {
|
||||
const baseSessionKey = params.sessionKey.trim();
|
||||
const normalizedBaseSessionKey = baseSessionKey.toLowerCase();
|
||||
if (parseAgentSessionKey(normalizedBaseSessionKey)) {
|
||||
return normalizedBaseSessionKey;
|
||||
}
|
||||
return buildAgentMainSessionKey({
|
||||
agentId: params.agentId,
|
||||
mainKey: baseSessionKey,
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user