Skip to content

Windows JSON-hook command line is not cmd.exe-safe - #956

Open
vecsop wants to merge 1 commit into
iOfficeAI:mainfrom
vecsop:fix/windows-permission-bridge-cmd-quoting
Open

Windows JSON-hook command line is not cmd.exe-safe#956
vecsop wants to merge 1 commit into
iOfficeAI:mainfrom
vecsop:fix/windows-permission-bridge-cmd-quoting

Conversation

@vecsop

@vecsop vecsop commented Aug 31, 2026

Copy link
Copy Markdown

Windows JSON-hook command line is not cmd.exe-safe

Summary

The PreToolUse permission bridge (aionui-permission-bridge) writes a command line (not a bare path) into <workspace>/.agents/hooks.json. Unix/agy word-splits that string and honours double quotes. On Windows the same string is executed through cmd.exe by the JSON-hook runner (jsonhook__aionui-permission-bridge_PreToolUse_0_0).

A command that starts with a quote is treated as the program name including the quote characters:

JSON hook "jsonhook__aionui-permission-bridge_PreToolUse_0_0" failed: command failed: exit status 1, stderr: "C:/Program Files/AionUi/resources/bundled-aioncore/win32-x64/aioncore.exe" is not recognized as an internal or external command

(Quote characters included in the reported program name; path uses forward slashes.)

This is the leftover of iOfficeAI/AionUi#4095 after #887 stripped the \\?\ verbatim prefix with dunce::canonicalize. The reporter’s follow-up on #4095 is the same class of failure without \\?\:

'"C:\Users\<user>\AppData\Local\Programs\AionUi\resources\bundled-aioncore\win32-x64\aioncore.exe"' is not recognized as an internal or external command

Root cause

File: crates/aionui-ai-agent/src/antigravity_hook.rs
Function: hooks_json_body / former one-liner

format!("\"{}\" {HOOK_SUBCOMMAND}", hook_binary.to_string_lossy())

Always produced "<path>" antigravity-hook. Combined with:

  1. cmd.exe quote-eating when the JSON-hook runner does cmd /c <command>
  2. Electron/current_exe() sometimes yielding forward slashes (C:/Program Files/...), which cmd then treats as switches

…the quoted path is looked up as a literal filename.

Hook command strings are generated at session start (factory/antigravity.rspermission_hook_body) and persisted on the session. After an AionCore/AionUi server restart, live sessions restore that body via sync_permission_hook (crates/aionui-session/src/backend/antigravity/conn.rs) without rebuilding argv. New sessions generate the command and spawn in one flow. This PR does not invent a second generator — if the stored string is cmd-hostile, restore-after-restart is the path that re-applies it to an already-running agent whose JSON-hook runner uses cmd.exe. New sessions after restart working is consistent with backends that do not install this hook (factory/acp.rs sets permission_hook_body: None) or with a freshly spawned process that word-splits the command itself. If a new Windows Claude/agy session still hits jsonhook+cmd, it would fail the same way until this command-line encoding is fixed.

Fix

Build the command with an explicit Windows encoding:

  • normalize /\
  • strip a wrapping quote pair if the path already came quoted
  • prefix with the call builtin so quotes wrap an argument, not argv[0]
  • keep the antigravity-hook subcommand (bare exe would start the resident backend)

Unix encoding is unchanged.

Tests

Assertions on the generated command string (no Electron build):

  • Unix: "/opt/..." antigravity-hook (quoted path, subcommand present)
  • Windows Program Files + forward slashes → call "C:\Program Files\...\aioncore.exe" antigravity-hook
  • Windows command must not start with "
  • Windows command must not contain / or \\?\

Reproduce (pre-fix)

  1. Windows install under C:\Program Files\AionUi\ (space in path).
  2. Start a session that installs the permission-bridge PreToolUse hook.
  3. Restart the AionUi/AionCore server while that session is still running.
  4. Invoke any tool. JSON hook fails with the quoted aioncore.exe path as an unknown command.
  5. Open a new session after the restart: hook injection / tool permission may succeed (ACP path, or a fresh spawn).

JSON-hook runners on Windows execute the hooks.json command through
cmd.exe. A line that starts with a quoted exe path is looked up as a
file whose name includes the quote characters:

  "C:/Program Files/.../aioncore.exe" is not recognized as an internal
  or external command

Prefix with `call`, normalize slashes to backslashes, and keep the
antigravity-hook subcommand. Unix quoting is unchanged.

Fixes the leftover of AionUi#4095 after AionCore#887 stripped \\?\ .
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant