Skip to content

fix(cron): scope approval marker to cron execution context (#58662) - #59719

Open
SquabbyZ wants to merge 1 commit into
NousResearch:mainfrom
SquabbyZ:fix/hard-08-issue-58662
Open

fix(cron): scope approval marker to cron execution context (#58662)#59719
SquabbyZ wants to merge 1 commit into
NousResearch:mainfrom
SquabbyZ:fix/hard-08-issue-58662

Conversation

@SquabbyZ

@SquabbyZ SquabbyZ commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Fixes #58662

Summary

The in-process cron ticker was leaking its approval marker into interactive gateway sessions. A user-initiated prompt in the gateway inherited 'approved-for-cron' status, skipping the safety prompt the operator would otherwise see.

What changed

  • cron/scheduler.py: approval marker is now scoped to the cron execution context. Uses an explicit 'approved-by=cron-{job_id}' marker cleared when the cron execution returns.
  • gateway/session_context.py: each session has its own approval context; markers from one context never bleed into another.
  • tools/approval.py: approval check now considers the active context rather than a global flag.
  • New tests/cron/test_approval_marker_isolation.py covers: cron command approved during run only, interactive gateway still requires approval after cron returns, two concurrent cron jobs don't bleed markers.

Security impact

This closes a marker-leak path that could let a cron job silently approve commands in interactive sessions.

Platforms tested

  • Linux (CI-equivalent)

AI-assisted contribution

This PR was drafted as part of an automated contribution sweep driven by https://github.com/SquabbyZ/peaks-loop. The original sub-agent was interrupted by a token-plan outage; this commit was recovered from the worktree state.

…rch#58662)

Fixes NousResearch#58662

The in-process cron ticker was leaking its approval marker into
interactive gateway sessions. A user-initiated prompt in the gateway
inherited "approved-for-cron" status, skipping the safety prompt
the operator would otherwise see.

* cron/scheduler.py: approval marker is now scoped to the cron
  execution context. Uses an explicit "approved-by=cron-{job_id}"
  marker that's cleared when the cron execution returns.
* gateway/session_context.py: each session has its own approval
  context; markers from one context never bleed into another.
* tools/approval.py: approval check now considers the active context
  rather than a global flag.
* New tests/cron/test_approval_marker_isolation.py covers: cron
  command approved during run only, interactive gateway still
  requires approval after cron returns, two concurrent cron jobs
  don't bleed markers.

AI-assisted fix by https://github.com/SquabbyZ/peaks-loop
@alt-glitch alt-glitch added type/bug Something isn't working comp/cron Cron scheduler and job management comp/gateway Gateway runner, session dispatch, delivery comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint sweeper:risk-security-boundary Sweeper risk: may affect sandboxing, auth, credentials, or sensitive data P2 Medium — degraded but workaround exists duplicate This issue or pull request already exists labels Jul 6, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

This was generated by AI during triage.

Duplicate of #58663 (earliest-open fix PR for #58662) — both scope the in-process cron ticker's process-global HERMES_CRON_SESSION marker off the global env to a per-job/per-context marker cleared on return. Verified they touch the same source files (cron/scheduler.py, gateway/session_context.py, tools/approval.py), differing only in test filenames — same sites, same mechanism. Related to issue #58662 and the competing cron-job-id fix #57169. (The approval gate is an in-process heuristic per SECURITY.md §3.2, so this is type/bug, not type/security.)

@teknium1 teknium1 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for targeting a real approval-routing defect: current main still writes the cron marker process-globally in cron/scheduler.py:2812, and _is_gateway_approval_context() checks it first in tools/approval.py:241.

Problems

  • The submitted marker bind at cron/scheduler.py:2531 is outside the cleanup try beginning at :2613; its reset only occurs in the finally at :3113. Setup failures in between can retain the marker in a reused execution context.
  • tests/cron/test_approval_marker_isolation.py:122 binds cron and Telegram state in the same context and never calls _is_gateway_approval_context(), so it does not prove a sibling gateway context remains interactive.
  • The branch conflicts with current main. The current dangerous-command path uses _run_approval_gate() and retains a global-marker read at tools/approval.py:2173; that current reader needs the context-aware migration during salvage.

Suggested changes

  • Scope the bind and reset under one unconditional try/finally.
  • Add a sibling-Context regression asserting _is_gateway_approval_context() is true after cron execution.
  • Port all current-main reader sites, including _run_approval_gate().

Automated hermes-sweeper review.

Comment thread cron/scheduler.py
reset_cron_session,
_VAR_MAP,
)
_cron_session_token = set_cron_session(job_id)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This bind precedes the cleanup try (which starts later at line 2613), while the token is reset only in that try's finally. Move the bind inside the protected scope, or widen the scope, so an exception during session/workdir/lock setup cannot retain the cron marker in a reused execution context.

)

cron_token = set_cron_session("cron-job-001")
try:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This binds the cron marker and Telegram state in the same ContextVar context, so it only proves that cron remains active there. Use a sibling contextvars.copy_context()/worker context and assert tools.approval._is_gateway_approval_context() is true there; that directly covers the reported gateway misclassification.

@teknium1 teknium1 added sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform labels Jul 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint comp/cron Cron scheduler and job management comp/gateway Gateway runner, session dispatch, delivery duplicate This issue or pull request already exists P2 Medium — degraded but workaround exists sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:risk-security-boundary Sweeper risk: may affect sandboxing, auth, credentials, or sensitive data type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: in-process cron ticker leaks its approval marker into interactive gateway sessions

3 participants