fix(cron): accept opaque session target keys#86578
Conversation
|
Codex review: needs maintainer review before merge. Reviewed May 25, 2026, 7:46 PM ET / 23:46 UTC. Summary PR surface: Source 0, Tests +67. Total +67 across 7 files. Reproducibility: yes. from source: current main rejects Review metrics: 1 noteworthy metric.
Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Rank-up moves:
Risk before merge
Maintainer options:
Next step before merge Security Review detailsBest possible solution: Merge after cron/session owners confirm the routing-vs-filesystem boundary, preserving strict run-log job-id validation and the new regression coverage. Do we have a high-confidence way to reproduce the issue? Yes, from source: current main rejects Is this the best way to solve the issue? Yes, with maintainer sign-off: the patch keeps the change narrow by relaxing only the runtime session-target validator while leaving cron job IDs and run-log validation strict. The safer alternative would be a narrower channel-native allowlist if maintainers do not want arbitrary separator-bearing custom session keys. AGENTS.md: found and applied where relevant. Codex review notes: model gpt-5.5, reasoning high; reviewed against 3a4f2b17fcfc. Label changesLabel changes:
Label justifications:
Evidence reviewedPR surface: Source 0, Tests +67. Total +67 across 7 files. View PR surface stats
What I checked:
Likely related people:
What the crustacean ranks mean
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics. How this review workflow works
|
|
ClawSweeper PR egg ✨ Hatched: 🥚 common Neon Diff Drake Hatch commandComment Hatchability rules:
Rarity: 🥚 common. What is this egg doing here?
|
9c2f51f to
875e7d8
Compare
875e7d8 to
97398e0
Compare
58e61b2 to
5194974
Compare
|
Proof before merge:
What was not tested: no live DingTalk/model delivery; this is cron target normalization and routing-contract coverage. |
Summary
Fixes #64030.
session:<id>targets to carry opaque channel-native session keys, including DingTalk-style keys with/or\.sessionTargetrouting keys.AI Assistance Disclosure
Codex assisted with issue research, implementation, tests, review, and proof collection. I reviewed and understand the affected cron session-target, Gateway cron, run-log, and session-key paths.
Root Cause
assertSafeCronSessionTargetIdused filename-safety rules forsession:<id>targets. That rejected/and\even though these values are runtime routing/session keys, not filenames. Current cron job ids are UUID-backed, and run-log filename access validates job ids through a separate path-boundary guard.Dependency Contract
No external dependency behavior is relied on here. Internal contract proof:
src/routing/session-key.tsandsrc/routing/resolve-route.tskeep channel peer ids opaque when building route/session keys.src/cron/service/jobs.tscreates cron job ids withcrypto.randomUUID(), so the raw session key is not the run-log filename.src/cron/run-log.tsandsrc/gateway/protocol/schema/cron.tsseparately reject slash-bearing job ids for run-log lookup.src/config/sessions/types.tsandsrc/config/sessions/paths.tsuse the store entrysessionIdfor transcript filenames rather than the store key/session key.Real Behavior Proof
Behavior addressed:
openclaw cron add --session session:<opaque channel key>accepts a DingTalk-style slash-bearing session key and preserves it through Gateway persistence/readback.Real environment tested: Local OpenClaw CLI and foreground Gateway on a throwaway
OPENCLAW_STATE_DIR/OPENCLAW_CONFIG_PATH, loopback port 41965,gateway.auth.mode=none,OPENCLAW_SKIP_CHANNELS=1, no real credentials.Exact steps or command run after this patch:
Evidence after fix:
Observed result after fix: The CLI/Gateway accepted and persisted the slash-bearing custom session target unchanged; the separate
cron.runsjob-id validator still rejected a slash-bearing job id.What was not tested: Live DingTalk delivery and model execution were not run; the proof intentionally used no real channel credentials or model credentials.
Regression Test Plan
node scripts/run-vitest.mjs src/cron/session-target.test.ts src/cron/normalize.test.ts src/cron/service.jobs.test.ts src/cron/service/store.test.ts src/gateway/server-cron.test.ts src/gateway/server.cron.test.tsnode scripts/run-vitest.mjs src/cron/run-log.test.ts src/gateway/protocol/cron-validators.test.tsPATH="/tmp/openclaw-pnpm-shim:$PATH" OPENCLAW_HEAVY_CHECK_LOCK_SCOPE=worktree corepack pnpm check:changed --base upstream/main --head HEADcodex review --base upstream/mainSecurity Impact
This does not relax filesystem path validation for cron run logs. It only stops treating runtime session keys as filename components. The proof includes a negative
cron.runsrequest showing slash-bearing job ids still fail Gateway protocol validation.Human Verification
I checked the reported source path before changing code, checked issue-linked/broad PR context, and verified there was no exact open PR for #64030 before opening this draft.
CODEOWNERS / Owner Review
No exact CODEOWNERS pattern matched the touched files. Adjacent cron service production code has
/src/cron/service/jobs.ts @openclaw/openclaw-secops, so cron/session-state owner review would still be useful.Changelog
No
CHANGELOG.mdedit in this contributor PR.Review Conversations
closedByPullRequestsReferencesand no exact open PR for64030.codex review --base upstream/mainfound no concrete regression in the touched runtime or gateway paths.Risks
The main risk is that accepting separators in
sessionTargetcould be mistaken for a path traversal relaxation. The actual filename boundary remainsjob.id, with separate run-log and Gateway schema validation.Behavior Tradeoffs
Cron now accepts any non-empty, non-NUL custom session key for
session:<id>, matching the routing contract for channel-native session keys.Scope Boundaries
This PR does not migrate existing jobs, encode/decode stored session targets, change cron job ids, relax run-log job-id validation, change live channel delivery, or alter model execution behavior.
Validation