#196·Agent-S

Permission dialogs execute unescaped model-generated text via os.system on macOS/Linux

Author: MackDingCreated May 22, 2026Updated May 22, 2026

Summary

The CLI permission dialog interpolates model-generated code and action_description directly into shell commands passed to os.system(...) on macOS and Linux.

This means a malicious or simply malformed action string can break quoting and execute arbitrary shell commands before the user approves the action.

Affected code

Examples:

  • gui_agents/s3/cli_app.py
  • gui_agents/s2_5/cli_app.py
  • gui_agents/s2/cli_app.py
  • gui_agents/s1/cli_app.py

Current pattern:

python
result = os.system(
    f'osascript -e \'display dialog "Do you want to execute this action?\n\n{code} which will try to {action_description}" ...\''
)

and on Linux:

python
result = os.system(
    f'zenity --question --title="Action Permission" --text="Do you want to execute this action?\n\n{code}" ...'
)

Impact

Because code originates from the agent/model, an attacker who can influence the generated action text may inject quotes / shell metacharacters and achieve command execution in the host shell that launches the permission prompt.

That defeats the purpose of the confirmation barrier.

Expected behavior

Permission dialogs should treat the action text as data, not shell syntax.

Suggested fix

  • Replace os.system(...) with subprocess.run([...], check=False).
  • Pass dialog arguments as argv items instead of shell strings.
  • Escape/encode the displayed action text safely for osascript / zenity.
  • Add regression tests covering quotes, backticks, $(), semicolons, and newlines in code / action_description.

Extra note

There are other intentionally dangerous execution paths in this repo (for example explicit exec(...) of approved GUI code, and the optional local code environment). Those are documented features. This issue is narrower: the permission prompt itself is currently shell-injection-prone.