From 1568d8b3a58fa1645910c5a78726026d4cab1157 Mon Sep 17 00:00:00 2001 From: Cash Williams Date: Thu, 29 Jan 2026 11:19:29 -0600 Subject: [PATCH] docs: add security comments for cron event trust assumptions Addresses reviewer feedback from SynthWork.io: - Document that opts.reason is internally controlled (not user input) - Document that system events come from admin-only cron configs - Clarifies enqueueSystemEvent() is only called by cron scheduler --- src/infra/heartbeat-runner.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/infra/heartbeat-runner.ts b/src/infra/heartbeat-runner.ts index 5e5f82715..0f87a6078 100644 --- a/src/infra/heartbeat-runner.ts +++ b/src/infra/heartbeat-runner.ts @@ -498,6 +498,8 @@ export async function runHeartbeatOnce(opts: { const isExecEvent = opts.reason === "exec-event"; // Check if this is a cron job system event (not a periodic heartbeat). // Cron jobs enqueue system events before calling runHeartbeatOnce. + // SECURITY: opts.reason is set internally by the heartbeat scheduler and cron runner. + // It is NOT user-controlled. Cron jobs are defined in admin-only gateway config. const isCronEvent = typeof opts.reason === "string" && opts.reason.startsWith("cron:"); // Always peek system events for cron and exec events to determine prompt type. const pendingEvents = isExecEvent || isCronEvent ? peekSystemEvents(sessionKey) : []; @@ -508,6 +510,8 @@ export async function runHeartbeatOnce(opts: { // For cron events with pending system events, use the system event text directly // (without appending the heartbeat prompt). The system event IS the prompt. + // SECURITY: System events originate from admin-controlled cron job configs (payload.text). + // User input cannot reach enqueueSystemEvent() - only the cron scheduler calls it. const cronEventBody = hasCronSystemEvents ? pendingEvents.join("\n\n") : null; const prompt = hasExecCompletion ? EXEC_EVENT_PROMPT