SafetyCard Request a review

MS-Agent

ModelScope's Python agent framework with CLI, TUI and WebUI for tool-using, multi-agent and long-running tasks.

github.com/modelscope/ms-agent · 2026-10-04 · a56afcc

Defense-in-depth score

3.0 / 10

MS-Agent ships shell, Python and notebook execution on the host, and its Python tool runs model code inside the agent process itself, with no sandbox by default. The WebUI and TUI ask before most actions, but any project directory can switch that off through its own .ms_agent/config.yaml, permission_memory.json or hooks.json, with no workspace-trust prompt. The SDK and `ms-agent run` default to auto-approve. Treat opening an untrusted repository as running its code.

Safest setup

MS-Agent's TUI and WebUI ask before most tool calls, give spawned shells, MCP servers and hooks an environment without API keys, and keep a session log outside the project. Model-written Python runs inside the agent process with no sandbox by default, and a project's own .ms_agent files can change approval and settings, so the safest setup turns on the Docker sandbox, opens only folders you trust and adds containment around the process.

SetupHowWhat it gives you
Scoped, low-limit keysGive the process only the model and tool keys this task needs, each scoped where the provider allows and with a spending limit set at the providerWhatever the agent runs reaches only the systems and spend you chose, not every credential in your shell C1
Per-call approvalKeep the default --permission_mode of restricted in the TUI and WebUI, and set mode: restricted under permission: in the config for ms-agent run and the SDKA person decides on every shell, Python, write and other non-read tool call before it runs C2
A reviewed project folderOpen only project directories whose .ms_agent/ folder, AGENTS.md and .env you wrote or have readApproval settings, hooks, MCP servers and instructions come only from you C6
Only the tools neededList only the tools the task needs in the include lists under file_system and code_executor in the agent configThe model sees write and code execution tools only when the task calls for them C3
The Docker sandboxSet implementation: sandbox under code_executor, with network_enabled: false in its sandbox blockShell, Python and notebook code run in a container away from the agent's keys and your home directory, with no network C4
Pre-task snapshotsenable_snapshots: true in the agent configA snapshot of the work directory before each task, to roll back to C2
Its own container or VMRun MS-Agent in a container or VM with outbound access limited to the model provider and the hosts the task needsAn outer boundary around hooks, MCP servers and in-process code, and one place to stop everything the agent started C4

Approving with confidence

  • Read each prompt and approve calls one at a time; the TUI and CLI prompts shorten long arguments, so see a long script or command in full before approving it.
  • Prefer allow once over always: an always answer is saved as a rule for that project and covers every later matching call.

Handling data

  • Session logs under ~/.ms_agent/projects hold every message and tool result unredacted; store them like the data the agent read.
  • Project memory in .ms_agent/memory is written without a prompt and loaded into later sessions, so read MEMORY.md before relying on it.

Key gaps (4)

  1. Model-generated Python executes in-process via exec() by default, with the agent's credentials and the user's full filesystem in reach. C4 · Code-execution isolation
  2. Workspace files the agent opens (.ms_agent/config.yaml, permission_memory.json, hooks.json) can switch off or bypass the approval gate with no trust decision. C2 · Approval gates
  3. The same repo-controlled config defeats the only limit on a prompt-injected agent, and the SDK/`ms-agent run` default (auto) leaves exfiltration and irreversible actions unattended. C5 · Untrusted input blast radius
  4. Repo-controlled .ms_agent/hooks.json, config.yaml and ./.env are loaded with no workspace-trust prompt, enabling shell hooks, MCP servers and auto-approval. C6 · Memory, context & configuration integrity

Criteria

C1 Identity & least privilege

0.25 / 1.00

MS-Agent runs as the operating-system user and adds no identity or credential scoping of its own. It does narrow what spawned processes inherit: shell commands, MCP stdio servers and hooks get a scrubbed environment without API keys. But the default python_executor tool runs model code inside the agent process itself, where every environment variable, the provider API keys and the user's home-directory credentials are reachable. A repo config file can also add variables back into the shell environment.

C2 Approval gates

0.25 / 1.00

The WebUI and TUI default to a 'restricted' mode that asks a human before any tool outside a small whitelist (read_file, grep, glob, todo, memory, skills), with options to allow once, for the session, always, edit the arguments, or deny. The SDK constructor and `ms-agent run` default to 'auto', which approves everything except a few network commands. The approval prompts in the terminal truncate long arguments, so a long script can be partly hidden. A cloned repository can turn approval off: its .ms_agent/config.yaml can set permission.mode to auto, its .ms_agent/permission_memory.json can pre-seed always-allow rules, and its .ms_agent/hooks.json can register a PreToolUse hook whose 'allow' skips the approval step entirely. No checkpoints are taken by default.

C3 Tool & action scoping

0.33 / 1.00

The file tools check resolved paths against the workspace and a list of sensitive paths, and shell commands go through a parser that extracts paths from known commands and blocks writes outside the workspace. That shell check lets unknown commands through, and inline interpreter code cannot be inspected. The python_executor and notebook tools take arbitrary code with no argument validation at all. The default tool set enables write, shell, Python and notebook execution together.

C4 Code-execution isolation

0.33 / 1.00

The shipped default runs model code with no isolation at all. Shell commands run as the user on the host (with a cleaned environment), and python_executor calls exec() inside the agent's own process, with full access to its memory, environment variables and API keys. A Docker sandbox backend (ms-enclave) exists, but it is opt-in. It is also a stock container with networking on and the workspace mounted read-write, and hooks and MCP servers still run on the host. If the approval step is bypassed, model code effectively has host-level access.

C5 Untrusted input blast radius

0.25 / 1.00

Nothing tracks where content came from: files, shell output, MCP results and the repo's AGENTS.md all enter the model's context on equal footing, and AGENTS.md goes into the system prompt. What limits a hijacked agent in the default WebUI/TUI mode is the general per-call approval. Shell, Python and file writes need a click, but reads and memory writes do not, so injected text can persist itself into project memory without anyone approving it. The same repo-controlled config files that switch approval off also remove this limit, and in the SDK's default auto mode a hijack can both exfiltrate data and take irreversible actions unattended.

C6 Memory, context & configuration integrity

0.17 / 1.00

A project directory controls a lot of the agent's behavior with no workspace-trust prompt. Its .ms_agent/config.yaml can change any setting, including tools, MCP servers and permission mode. Its .ms_agent/hooks.json registers shell-command hooks that run automatically, its permission_memory.json holds always-allow rules, its AGENTS.md is injected into the system prompt, and the CLI loads ./.env from the current directory. Project memory (MEMORY.md under .ms_agent/memory, on by default in the WebUI) is written by an auto-approved memory tool. A regex scanner rejects a few obvious injection phrases, but the memory is then fed back into later sessions.

C7 Third-party extensions

0.25 / 1.00

Extensions come from MCP servers, plugins, hooks and skills. Plugins installed from GitHub are pinned to a resolved commit, but MCP servers launch whatever command the config names with no pinning or integrity check. Project-scope plugins.json and mcp.json inside the workspace are picked up without consent. Loading Python tool plugins named in a config does require trust_remote_code. MCP stdio servers and hook commands run as separate processes with a scrubbed environment.

C8 Secrets & sensitive-data protection

0.30 / 1.00

There is no telemetry (the bundled mem0 telemetry is explicitly switched off), and API keys are masked when the WebUI sends them back to the browser. Spawned shells, MCP servers and hooks get environments without secrets. Provider keys are kept in plaintext settings, and session transcripts are written with no redaction. The in-process python_executor can read every key the agent holds and print it into the conversation.

C9 Audit & traceability

0.45 / 1.00

Each session is written as an append-only JSONL log under ~/.ms_agent/projects, outside the workspace, flushed line by line. It records every message, including tool calls and results, and the WebUI also records each approval or denial with its arguments. Records carry no actor identity beyond role. The agent's own process (and approved shell commands) can still edit the log, and a failed permission write is swallowed silently.

C10 Limits & kill switch

0.40 / 1.00

The agent loop stops after a round cap, but the interfaces raise it to 1000 rounds (9999 in the shipped agent.yaml). Each tool call is bounded by a 120-second default timeout, and the model itself can raise that to 600 seconds. There is no token, cost or wall-clock budget. A python_executor timeout stops waiting but leaves the thread running. Killing a background shell task only marks it killed, because the kill code does not handle asyncio subprocesses.