fix(cron): preserve isolated message targets#69153
Conversation
Greptile SummaryThis PR fixes a bug where explicit message targets in Confidence Score: 5/5Safe to merge — all prior P1 concerns are resolved, logic is correct, and new tests cover both the explicit-target forwarding and the bare-none early-exit path. The previous thread's core concern (channel defaulting to 'last' making hasMessageTargetContext always true) is addressed by scoping the 'last' default only to announce mode in delivery-plan.ts. The hasMessageTargetContext guard correctly uses to/threadId/accountId rather than channel. Tests are thorough. No files require special attention. Reviews (2): Last reviewed commit: "test(cron): fix isolated target test typ..." | Re-trigger Greptile |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 4bd5fe7b9a
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@greptile-apps review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: c7bd3290a6
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
c7bd329 to
bf6ca5e
Compare
🔒 Aisle Security AnalysisWe found 1 potential security issue(s) in this PR:
1. 🟠 Cron isolated runs allow messaging target context even when delivery is not requested (mode:none)
Description
This can enable a control/authorization bypass depending on who can create/modify cron jobs:
Vulnerable logic (changed behavior): const hasMessageTargetContext =
deliveryPlan.mode !== "webhook" &&
(deliveryPlan.to !== undefined ||
deliveryPlan.threadId !== undefined ||
deliveryPlan.accountId !== undefined);
if (!deliveryPlan.requested && !hasMessageTargetContext) {
// ... skip resolution
}
// otherwise resolves delivery target even when requested=falseIf cron definitions are tenant-controlled or editable by less-trusted actors, this enables arbitrary outbound messaging/spam/exfiltration from cron runs by embedding a target in the job definition (or by causing implicit “last target” resolution via session state). RecommendationTighten the conditions under which delivery target context is resolved/forwarded when Options (pick one based on intended product behavior):
const hasExplicitMessageTarget =
deliveryPlan.mode === "none" && typeof deliveryPlan.to === "string" && deliveryPlan.to.trim();
if (!deliveryPlan.requested && !hasExplicitMessageTarget) {
// do not resolve delivery target
}Additionally, consider enforcing requireExplicitMessageTarget: params.resolvedDelivery.ok && (params.deliveryRequested || params.deliveryMode === "none")Finally, ensure Analyzed PR: #69153 at commit Last updated on: 2026-04-20T02:40:05Z |
|
Landed in 7d9a9d8 via squash merge from 05a1627.\n\n- source: https://github.com/openclaw/openclaw/pull/69153/commits/05a16277f89fd3579a63c0de4fd0763870eae723\n- merge: 7d9a9d8 |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 05a16277f8
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| (deliveryPlan.to !== undefined || | ||
| deliveryPlan.threadId !== undefined || | ||
| deliveryPlan.accountId !== undefined); |
There was a problem hiding this comment.
Avoid resolving target for mode=none without explicit recipient
This condition treats threadId or accountId alone as “message target context”, which skips the early return and then calls resolveDeliveryTarget with channel: "last" later in the function; as a result, jobs like delivery: { mode: "none", accountId: "ops" } (or only threadId) can still inherit a session/default recipient and set currentChannelId, allowing agent message calls with no explicit target to go to a stale/default destination. That reintroduces implicit routing for a mode:none configuration that did not provide an explicit recipient.
Useful? React with 👍 / 👎.
* test(cron): cover delivery target context for mode none * fix(cron): preserve target context for delivery mode none * test(cron): cover isolated message target forwarding * fix(cron): forward isolated message targets into embedded runs * fix(cron): ignore implicit last-target context for mode none * fix(cron): keep mode none channel explicit only * test(cron): fix isolated target test typing * fix: preserve isolated message targets (openclaw#69153) * fix: preserve isolated message targets (openclaw#69153)
* test(cron): cover delivery target context for mode none * fix(cron): preserve target context for delivery mode none * test(cron): cover isolated message target forwarding * fix(cron): forward isolated message targets into embedded runs * fix(cron): ignore implicit last-target context for mode none * fix(cron): keep mode none channel explicit only * test(cron): fix isolated target test typing * fix: preserve isolated message targets (openclaw#69153) * fix: preserve isolated message targets (openclaw#69153)
* test(cron): cover delivery target context for mode none * fix(cron): preserve target context for delivery mode none * test(cron): cover isolated message target forwarding * fix(cron): forward isolated message targets into embedded runs * fix(cron): ignore implicit last-target context for mode none * fix(cron): keep mode none channel explicit only * test(cron): fix isolated target test typing * fix: preserve isolated message targets (openclaw#69153) * fix: preserve isolated message targets (openclaw#69153)
* test(cron): cover delivery target context for mode none * fix(cron): preserve target context for delivery mode none * test(cron): cover isolated message target forwarding * fix(cron): forward isolated message targets into embedded runs * fix(cron): ignore implicit last-target context for mode none * fix(cron): keep mode none channel explicit only * test(cron): fix isolated target test typing * fix: preserve isolated message targets (openclaw#69153) * fix: preserve isolated message targets (openclaw#69153)
* test(cron): cover delivery target context for mode none * fix(cron): preserve target context for delivery mode none * test(cron): cover isolated message target forwarding * fix(cron): forward isolated message targets into embedded runs * fix(cron): ignore implicit last-target context for mode none * fix(cron): keep mode none channel explicit only * test(cron): fix isolated target test typing * fix: preserve isolated message targets (openclaw#69153) * fix: preserve isolated message targets (openclaw#69153)
* test(cron): cover delivery target context for mode none * fix(cron): preserve target context for delivery mode none * test(cron): cover isolated message target forwarding * fix(cron): forward isolated message targets into embedded runs * fix(cron): ignore implicit last-target context for mode none * fix(cron): keep mode none channel explicit only * test(cron): fix isolated target test typing * fix: preserve isolated message targets (openclaw#69153) * fix: preserve isolated message targets (openclaw#69153)
Preserves explicit target context for isolated cron runs with
delivery.mode: none, and forwards that context into embedded agent messaging.