intersystems-community / intersystems-community/iris-agentic-dev
iris_ws_exec bypasses the non-configurable CODE_EDIT_BLOCKED hard-block (present on 1.3.0 and 1.4.1)
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 40
- Forks
- 14
- Avg merge
- 1d 23h
- Merged PRs (30d)
- 7
Description
Summary
The non-configurable code-edit hard-block (dispatch_gate step [0], error CODE_EDIT_BLOCKED) is applied to iris_execute, iris_execute_method and iris_query, but not to iris_ws_exec. A caller who cannot edit compiled code through iris_execute can do the same edit through a WebSocket terminal session, which routes around the guard entirely.
The write gate (085) does cover iris_ws_exec (wr classification), so this is not a write-gate gap — it is specifically the code-edit hard-block, and the spec-087 literal-Kill ^ destructive check, that do not extend to the WebSocket path.
Environment
iris-agentic-dev1.3.0 (measured live) and 1.4.1 (source-verified) — the bug is present on the latest release.- IRIS 2025.3 Community, MCP over stdio.
Evidence — measured live on 1.3.0, write_tools_enabled = true (the normal operating state for any compile/test workflow)
Same code, two tools, opposite outcomes:
iris_execute { code: 'do $System.OBJ.Compile("App.Data.Person","ck")' }
-> { "error_code": "CODE_EDIT_BLOCKED", "matched": "$SYSTEM.OBJ.COMPILE" }
iris_ws_open {} -> session opened
iris_ws_exec { session, code: 'do $System.OBJ.Compile("App.Data.Person","ck")' }
-> EXECUTED: "Compilation started ... Compiling class App.Data.Person ... finished successfully"
The destructive literal-Kill ^ check (spec 087) is also skipped, with destructive_tools_enabled = false:
iris_ws_exec { session, code: 'kill ^zzProbeDoesNotExist write "kill-ran"' }
-> EXECUTED: "kill-ran"
Control confirming this is not a write-gate hole (write_tools_enabled = false):
iris_ws_exec { session, code: 'write 1' } -> { "error_code": "WRITE_TOOLS_DISABLED" }
Source
crates/iris-agentic-dev-core/src/policy/gate.rs, dispatch_gate() step [0], on both v1.3.0 and v1.4.1, only branches on iris_execute, iris_execute_method (added in 1.4.x) and iris_query. iris_ws_exec never reaches check_objectscript_code_edit. Meanwhile tools/write_gate.rs classifies iris_ws_exec as wr and even comments "goes through iris_ws_exec, which is where the gate belongs" — so the write tier was deliberately routed through it, but the code-edit tier was not.
Why it matters
The code-edit hard-block is documented as a non-configurable protection: "Blocks editing class/routine code through arbitrary-execution tools, which otherwise sidestep the system blocklist." Its value is that an agent with write access — which every compile/test session needs — still cannot rewrite %Dictionary, run $system.OBJ, or touch ^rOBJ through ad-hoc execution. iris_ws_exec reopens exactly that path in the normal write_tools_enabled = true state, so the guarantee holds for iris_execute and silently does not for the WebSocket terminal. An agent reaching for a terminal session (a natural fallback when iris_execute refuses) gets the unguarded path.
Existing tracking
Spec 087-execute-gate-bypass explicitly lists iris_ws_exec under Out of scope — "separate analysis needed; same class of problem" — but no issue tracks it, and 1.4.x extended [0] to iris_execute_method without picking it up. This issue is that separate analysis.
Suggested fix
Route iris_ws_exec's code through the same check_objectscript_code_edit before it reaches the session pool — either by adding an iris_ws_exec branch to dispatch_gate step [0], or by calling the guard in the iris_ws_exec handler. The PHI and system-global checks that apply to iris_execute global operations should follow the same reasoning.
Reported from the iris-ai-bootstrap kit, which in the meantime removes iris_ws_open / iris_ws_exec / iris_ws_close from its own tool surface via IRIS_DISABLED_TOOLS.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in crates/iris-agentic-dev-core/src/policy/gate.rs at dispatch_gate() step [0], then trace the iris_ws_exec handler up to the session pool. Compare its path with iris_execute and the classification in tools/write_gate.rs, including the code-edit and destructive checks. Done means WebSocket execution receives the same applicable protections without breaking the existing write gate.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- security
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 72/100