fix(approval): check is_approved in execute_code guard (#39275)
check_execute_code_guard() never called is_approved() before entering the
approval flow, and never persisted session/permanent approvals from the
gateway response. This meant 'Approve session' and 'Always' buttons had
no effect — every execute_code call re-prompted the user.
- Add is_approved() check after get_current_session_key(), matching
check_all_command_guards()
- Persist session ('approve_session') and permanent ('approve_permanent')
approvals based on the gateway choice, same as terminal command guard
- Add 3 regression tests for session persistence, permanent persistence,
and short-circuit on pre-existing approval
This commit is contained in:
@ -1584,6 +1584,12 @@ def check_execute_code_guard(code: str, env_type: str) -> dict:
|
||||
# paths don't pay to copy a potentially-large script into this string.
|
||||
command = f"execute_code <<'PY'\n{code}\nPY"
|
||||
|
||||
# Check session/permanent approval — same gate as check_all_command_guards.
|
||||
# Without this, "Approve session" / "Always" choices are stored but never
|
||||
# consulted, so every execute_code call re-prompts the user (#39275).
|
||||
if is_approved(session_key, pattern_key):
|
||||
return {"approved": True, "message": None}
|
||||
|
||||
# Smart mode: ask the aux LLM about the whole script. An APPROVE here only
|
||||
# suppresses the redundant whole-script prompt; the per-call terminal()
|
||||
# guards (restored by context propagation) still run independently.
|
||||
@ -1674,9 +1680,15 @@ def check_execute_code_guard(code: str, env_type: str) -> dict:
|
||||
"user_consent": False,
|
||||
}
|
||||
|
||||
# Approved — one-shot only. Deliberately NO approve_session/approve_permanent:
|
||||
# each execute_code script is distinct arbitrary code, so approval never
|
||||
# persists to future scripts.
|
||||
# Approved — persist based on scope (same logic as check_all_command_guards).
|
||||
if choice == "session":
|
||||
approve_session(session_key, pattern_key)
|
||||
elif choice == "always":
|
||||
approve_session(session_key, pattern_key)
|
||||
approve_permanent(pattern_key)
|
||||
save_permanent_allowlist(_permanent_approved)
|
||||
# choice == "once": no persistence — approval lasts this single call only.
|
||||
|
||||
return {"approved": True, "message": None,
|
||||
"user_approved": True, "description": description}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user