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)

Open
#137 0 comments 0 reactions 0 assignees View on GitHub

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-dev 1.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

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.