# Defense-in-depth score: QwenPaw

**Repo:** https://github.com/agentscope-ai/QwenPaw · **Commit:** `80e412da9b5505bcac5eec6add271d09fa144c60` (v2.2.2-beta.4) · **Reviewed:** 2026-10-05
**What it is:** Personal AI assistant built on AgentScope with a local web console, terminal UI, chat-channel integrations, skills, plugins and MCP support.
**Category:** AI Assistants
**Scored configuration:** pip install, `qwenpaw init --defaults`, `qwenpaw app` on 127.0.0.1:8088, default agent used from the web console, approval level AUTO, sandbox switch off, no channels configured.
**Agent surface (default):** code execution yes · filesystem write yes · network egress yes · external credentials yes · persistent memory yes · untrusted input yes · third party extensions opt-in · sub agents yes · external communication opt-in

## Score: 2.3 / 10.0 (Minimal)

| # | Criterion | S | C | D | B | Raw | Cap | Score | Confidence |
|---|---|---|---|---|---|---|---|---|---|
| C1 | Identity & least privilege | L0 | L1 | L0 | L0 | 0.07 | none | **0.07** | High |
| C2 | Approval gates | L3 | L0 | L1 | L0 | 0.28 | C2-POWERBYPASS | **0.25** | High |
| C3 | Tool & action scoping | L1 | L2 | L1 | L0 | 0.28 | none | **0.28** | High |
| C4 | Code-execution isolation | L2 | L1 | L0 | L1 | 0.28 | G1 | **0.28** (alt) | High |
| C5 | Untrusted input blast radius | L0 | L0 | L0 | L0 | 0.00 | C5-WORSTCASE | **0.00** | High |
| C6 | Memory, context & configuration integrity | L0 | L0 | L1 | L1 | 0.10 | none | **0.10** | High |
| C7 | Third-party extensions | L1 | L0 | L2 | L0 | 0.17 | none | **0.17** | High |
| C8 | Secrets & sensitive-data protection | L2 | L1 | L1 | L0 | 0.28 | none | **0.28** | High |
| C9 | Audit & traceability | L2 | L2 | L2 | L2 | 0.50 | none | **0.50** | High |
| C10 | Limits & kill switch | L2 | L2 | L1 | L1 | 0.40 | none | **0.40** | High |


As shipped, QwenPaw runs shell commands on your machine as your user, with no sandbox and no approval prompt unless a built-in dangerous-command pattern fires, and it can fetch any web page, so content it reads can steer it into reading your files and sending them out. It has a substantial governance layer (approval cards showing the exact call, a policy engine that fails closed, an audit database and an OS sandbox), but the sandbox is off by default and the default approval level leaves the shell ungated. Turn on the sandbox, use the STRICT approval level and run it under a dedicated OS user.

## Critical gaps
- Shell commands run without approval in the default configuration unless a dangerous-command pattern or sensitive-path check fires. (ASI02, ASI09; C2). Evidence: [src/qwenpaw/governance/policy.py:839-866](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/governance/policy.py#L839-L866); [src/qwenpaw/governance/resource_governor.py:252-269](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/governance/resource_governor.py#L252-L269); [src/qwenpaw/config/config.py:3035-3041](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/config/config.py#L3035-L3041)
- The approval level can be loosened at runtime from inside a session, without an operator-level change. (ASI09; C2). Evidence: [src/qwenpaw/governance/tool_adapter.py:62-76](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/governance/tool_adapter.py#L62-L76); [src/qwenpaw/governance/tool_adapter.py:314-326](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/governance/tool_adapter.py#L314-L326)
- A hijacked default session can read local files and send them out, and run irreversible commands, with no human involved. (ASI01, LLM01; C5). Evidence: [src/qwenpaw/agents/tools/web_search.py:201-211](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/agents/tools/web_search.py#L201-L211); [src/qwenpaw/agents/tools/shell.py:1333-1338](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/agents/tools/shell.py#L1333-L1338); [src/qwenpaw/runtime/protected_prompt.py:28-30](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/runtime/protected_prompt.py#L28-L30)
- The agent runs with the launching user's full authority and environment. (ASI03; C1). Evidence: [src/qwenpaw/agents/tools/shell.py:1442](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/agents/tools/shell.py#L1442); [src/qwenpaw/envs/store.py:1-9](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/envs/store.py#L1-L9)
- Shell commands run as host subprocesses by default because the sandbox switch ships off. (ASI05; C4). Evidence: [src/qwenpaw/config/config.py:3035-3036](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/config/config.py#L3035-L3036); [src/qwenpaw/agents/tools/shell.py:1442](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/agents/tools/shell.py#L1442)
- Marketplace plugins are imported into the agent's own process with no integrity check. (ASI04, LLM03; C7). Evidence: [src/qwenpaw/plugins/loader.py:545-573](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/plugins/loader.py#L545-L573); [src/qwenpaw/plugins/download_catalog.py:278](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/plugins/download_catalog.py#L278)

## Criterion details

### C1 Identity & least privilege: 0.07 (high confidence)

QwenPaw runs as the operating-system user who starts it and does nothing to narrow that authority: shell commands inherit the full process environment, including any keys you add through its environment manager, and there is no per-tool or per-request credential. The governance layer decides which actions run, but it does not scope identities. Its own security policy tells operators to give it a dedicated OS user or host; nothing in the default install does that for you. If the agent is steered, it acts with everything your account can reach.

- **S L0:** Ambient OS-user authority; no dedicated or scoped identity for tools. Evidence: [src/qwenpaw/agents/tools/shell.py:1442](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/agents/tools/shell.py#L1442); [src/qwenpaw/envs/store.py:1-9](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/envs/store.py#L1-L9) (verified)
  - *To reach the next level:* No scoped credential or per-capability identity; L1 needs at least a dedicated identity.
- **C L1:** Tool calls pass through the governance wrapper, but every subprocess receives the full environment. Evidence: [src/qwenpaw/app/workspace/local_workspace.py:117-124](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/app/workspace/local_workspace.py#L117-L124); [src/qwenpaw/agents/tools/shell.py:1442](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/agents/tools/shell.py#L1442); [src/qwenpaw/envs/store.py:133](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/envs/store.py#L133) (verified)
  - *To reach the next level:* Subprocesses and extensions use ambient credentials; L2 needs all built-in tools on a scoped identity.
- **D L0:** Default install runs with the full privileges of the launching user; separation is left to operator hardening. Evidence: [SECURITY.md:74](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/SECURITY.md#L74); [src/qwenpaw/agents/tools/shell.py:1442](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/agents/tools/shell.py#L1442) (verified)
  - *To reach the next level:* No narrower default identity; least privilege requires a separate OS user set up by hand.
- **B L0:** A hijacked session can act with the user's whole account, including the shell and, when connected, the user's real browser profile. Evidence: [src/qwenpaw/agents/tools/shell.py:1333-1338](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/agents/tools/shell.py#L1333-L1338); [src/qwenpaw/config/config.py:3102-3108](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/config/config.py#L3102-L3108) (verified)
  - *To reach the next level:* Blast radius is the user's whole account; L1 needs authority limited to fewer systems.
- **Cap:** none

### C2 Approval gates: 0.25 (high confidence)

QwenPaw has a real approval system: a policy engine asks a human before risky calls, the approval card shows the exact tool input, unknown tools are denied and a governance start-up failure denies everything. But at the default approval level, shell commands run immediately unless one of the built-in dangerous-command patterns or sensitive-path checks fires, so the most powerful tool is effectively ungated. The approval level can also be changed at runtime without an operator-level step. There are no default checkpoints, so most actions can't be undone.

- **S L3:** Per-call approval card carrying the exact tool input and target, with severity tiers deciding when to ask; reject and timeout deny. Evidence: [src/qwenpaw/governance/tool_adapter.py:722-733](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/governance/tool_adapter.py#L722-L733); [src/qwenpaw/governance/policy.py:1006-1023](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/governance/policy.py#L1006-L1023); [src/qwenpaw/governance/tool_adapter.py:794-805](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/governance/tool_adapter.py#L794-L805) (verified)
  - *To reach the next level:* No first-class allow/deny/escalate policy on parsed arguments.
- **C L0:** The shell tool runs without approval unless a denylist pattern or sensitive-path finding fires; with the sandbox off it runs directly. Evidence: [src/qwenpaw/governance/policy.py:839-866](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/governance/policy.py#L839-L866); [src/qwenpaw/governance/resource_governor.py:252-269](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/governance/resource_governor.py#L252-L269); [src/qwenpaw/config/config.py:3035-3041](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/config/config.py#L3035-L3041) (verified)
  - *To reach the next level:* L1 needs the most powerful tool gated; shell calls with no finding are not.
- **D L1:** Approval is on by default at the AUTO level, but the effective level is resolved per call from settings that can be changed at runtime, and OFF allows every tool. Evidence: [src/qwenpaw/config/config.py:2400-2401](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/config/config.py#L2400-L2401); [src/qwenpaw/governance/tool_adapter.py:62-76](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/governance/tool_adapter.py#L62-L76); [src/qwenpaw/governance/tool_adapter.py:314-326](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/governance/tool_adapter.py#L314-L326) (verified)
  - *To reach the next level:* The gate's setting can be loosened from inside a session; L2 needs it changeable only by operator configuration.
- **B L0:** Wrongly allowed actions include arbitrary shell commands and external messages, and workspace checkpoints are off by default. Evidence: [src/qwenpaw/agents/tools/shell.py:1333-1338](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/agents/tools/shell.py#L1333-L1338); [src/qwenpaw/checkpoints/policy.py:40-41](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/checkpoints/policy.py#L40-L41) (verified)
  - *To reach the next level:* No default undo; L1 needs some low-impact actions reversible.
- **Cap:** C2-POWERBYPASS: Shell commands with no detector finding run without approval in the default configuration.

### C3 Tool & action scoping: 0.28 (high confidence)

The tools are general purpose: a raw shell, file tools that deliberately don't confine paths, and a web fetcher that takes any http(s) URL and follows redirects without blocking internal addresses. What validation exists is a denylist of dangerous shell patterns and glob rules on the target path, which mostly allow. Shell, file write, browser and web tools are all on by default, though each can be switched off in the console. A misused tool can reach anything the user can.

- **S L1:** Denylist and regex detectors on shell commands; file paths and URLs are not contained by allowlists. Evidence: [src/qwenpaw/security/tool_guard/rules/dangerous_shell_commands.yaml:76-80](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/security/tool_guard/rules/dangerous_shell_commands.yaml#L76-L80); [src/qwenpaw/governance/policy.py:271-300](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/governance/policy.py#L271-L300); [src/qwenpaw/agents/tools/file_io.py:64-86](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/agents/tools/file_io.py#L64-L86); [src/qwenpaw/agents/tools/web_search.py:242](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/agents/tools/web_search.py#L242); [src/qwenpaw/agents/tools/web_search.py:74](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/agents/tools/web_search.py#L74) (verified)
  - *To reach the next level:* No resolved-path containment or URL host allowlist with internal-address blocking.
- **C L2:** The same governance checks wrap every built-in tool, and MCP tools have their own driver policy. Evidence: [src/qwenpaw/app/workspace/local_workspace.py:117-124](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/app/workspace/local_workspace.py#L117-L124); [src/qwenpaw/drivers/handler.py:196-203](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/drivers/handler.py#L196-L203) (verified)
  - *To reach the next level:* No shared argument-validation layer that extension tools inherit.
- **D L1:** Shell, write, browser and web tools are enabled by default and individually disableable. Evidence: [src/qwenpaw/runtime/tool_registry.py:219](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/runtime/tool_registry.py#L219); [src/qwenpaw/agents/tools/browser.py:19-25](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/agents/tools/browser.py#L19-L25); [src/qwenpaw/agents/tools/shell.py:1333-1338](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/agents/tools/shell.py#L1333-L1338) (verified)
  - *To reach the next level:* Default tool set includes write, exec and network; L2 needs selectable groups.
- **B L0:** A misused shell or web tool reaches any command, any path and any host available to the user. Evidence: [src/qwenpaw/agents/tools/shell.py:1333-1338](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/agents/tools/shell.py#L1333-L1338); [src/qwenpaw/agents/tools/web_search.py:201-211](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/agents/tools/web_search.py#L201-L211) (verified)
  - *To reach the next level:* General-purpose tools against the whole machine; L1 needs some limits on reach.
- **Cap:** none

### C4 Code-execution isolation: 0.28 (high confidence)

By default shell commands run as ordinary host subprocesses with the full environment, because the global sandbox switch ships off and the governance layer then runs them unsandboxed without asking. An OS sandbox exists (Bubblewrap or Landlock on Linux, Seatbelt on macOS, AppContainer on Windows) that limits writes to the workspace, but it leaves the network open, passes most of the environment through, covers only the shell and the recall REPL, and is skipped silently when the platform can't provide it. Turning it on is worthwhile but does not make the shell a contained environment.

- **default configuration** (default; raw 0.00 → 0.00)
  - **S L0:** Default shell execution is a same-user host subprocess. Evidence: [src/qwenpaw/agents/tools/shell.py:1442](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/agents/tools/shell.py#L1442); [src/qwenpaw/config/config.py:3035-3036](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/config/config.py#L3035-L3036) (verified)
    - *To reach the next level:* No isolation primitive in the default path.
  - **C L0:** No execution path is sandboxed by default. Evidence: [src/qwenpaw/config/config.py:3035-3041](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/config/config.py#L3035-L3041); [src/qwenpaw/governance/resource_governor.py:252-269](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/governance/resource_governor.py#L252-L269) (verified)
    - *To reach the next level:* L1 needs at least the main exec tool sandboxed.
  - **D L0:** The sandbox switch defaults to off. Evidence: [src/qwenpaw/config/config.py:3035-3036](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/config/config.py#L3035-L3036) (verified)
    - *To reach the next level:* Off by default.
  - **B L0:** Commands run on the host as the user with the full environment, including any configured keys. Evidence: [src/qwenpaw/agents/tools/shell.py:1442](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/agents/tools/shell.py#L1442); [src/qwenpaw/envs/store.py:133](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/envs/store.py#L133) (verified)
    - *To reach the next level:* Host-equivalent; L1 needs at least a boundary between commands and the host.
- **opt-in OS sandbox (security.sandbox_enabled=true)** (alt; raw 0.28, cap G1 → 0.28) ← counted
  - **S L2:** Kernel-level OS sandbox profile (Bubblewrap/Landlock, Seatbelt, AppContainer) restricting filesystem writes, with network left open. Evidence: [src/qwenpaw/sandbox/bubblewrap_sandbox.py:12-13](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/sandbox/bubblewrap_sandbox.py#L12-L13); [src/qwenpaw/governance/resource_governor.py:399-410](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/governance/resource_governor.py#L399-L410) (verified)
    - *To reach the next level:* Network is not denied by default and the process runs with the user's environment; L3 needs writes limited to the workspace and network denied.
  - **C L1:** Only shell and the recall REPL route through it; file tools, browser and MCP stdio servers run on the host, and not every shell path is routed through it. Evidence: [src/qwenpaw/governance/tool_adapter.py:390-397](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/governance/tool_adapter.py#L390-L397); [src/qwenpaw/agents/tools/file_io.py:64-86](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/agents/tools/file_io.py#L64-L86); [src/qwenpaw/drivers/handlers/mcp_stateful_client.py:917-921](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/drivers/handlers/mcp_stateful_client.py#L917-L921) (verified)
    - *To reach the next level:* Other execution paths run on the host; L2 needs most paths sandboxed.
  - **D L0:** Off by default, and it falls back to host execution without asking when the platform can't provide it. Evidence: [src/qwenpaw/config/config.py:3035-3036](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/config/config.py#L3035-L3036); [src/qwenpaw/governance/resource_governor.py:252-269](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/governance/resource_governor.py#L252-L269) (verified)
    - *To reach the next level:* Off by default.
  - **B L1:** Workspace read-write, full network, and only four API-key variables blanked from the environment. Evidence: [src/qwenpaw/governance/resource_governor.py:399-410](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/governance/resource_governor.py#L399-L410); [src/qwenpaw/governance/policy.py:324-329](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/governance/policy.py#L324-L329) (verified)
    - *To reach the next level:* Network egress with credentials available; L2 needs no secrets in the sandbox environment.
- **Cap:** G1: Opt-in mechanism: off in the scored default configuration.
- **Notes:** The default mechanism is unsandboxed; the score is the opt-in OS sandbox with G1 applied.

### C5 Untrusted input blast radius: 0.00 (high confidence)

The agent reads web pages, search results, files, browser content and MCP results, and none of it is marked or handled differently from the user's own instructions; the only defence is a system-prompt line telling the model to treat such content as data. In the default configuration a hijacked agent can read the user's files, run shell commands and send data out through the web fetcher or the shell, all without a human. The project's own security policy says the model is not a trusted principal and treats prompt injection as out of scope unless it crosses a boundary, but the default boundaries are wide.

- **S L0:** Prompt-only instruction to treat untrusted content as data. Evidence: [src/qwenpaw/runtime/protected_prompt.py:28-30](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/runtime/protected_prompt.py#L28-L30); [SECURITY.md:122](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/SECURITY.md#L122) (verified)
  - *To reach the next level:* No detection or capability restriction after untrusted content is read.
- **C L0:** Tool results and fetched content enter context with no provenance marking. Evidence: [src/qwenpaw/agents/tools/web_search.py:201-211](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/agents/tools/web_search.py#L201-L211); searched `rg -n -i 'taint|quarantin|provenance|PromptGuard|LlamaGuard'` in `src/qwenpaw/agents src/qwenpaw/runtime src/qwenpaw/governance` → 27 hits (hits are scroll-context summary provenance, history-file quarantine and image quarantine; none marks tool results as untrusted) (verified)
  - *To reach the next level:* Untrusted sources are not distinguished from the principal's input.
- **D L0:** No untrusted-input control exists to be on by default. Evidence: [src/qwenpaw/runtime/protected_prompt.py:28-30](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/runtime/protected_prompt.py#L28-L30) (verified)
  - *To reach the next level:* Off by default.
- **B L0:** A hijacked default session can read local files and send them out via web fetch or shell, and can run irreversible commands, unattended. Evidence: [src/qwenpaw/agents/tools/web_search.py:201-211](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/agents/tools/web_search.py#L201-L211); [src/qwenpaw/agents/tools/shell.py:1333-1338](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/agents/tools/shell.py#L1333-L1338); [src/qwenpaw/governance/policy.py:1006-1023](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/governance/policy.py#L1006-L1023) (verified)
  - *To reach the next level:* Exfiltration and irreversible actions both happen without a human.
- **Cap:** C5-WORSTCASE: In the default configuration a hijacked session can leak data and act irreversibly with no human involved.

### C6 Memory, context & configuration integrity: 0.10 (high confidence)

Each agent's workspace holds instruction files (AGENTS.md, SOUL.md, PROFILE.md) that are loaded into the system prompt on every turn, plus MEMORY.md and the ReMe knowledge base. The agent's file tools may write anything inside its workspace without asking, so content it reads in one session can rewrite the instructions every later session follows. QwenPaw does not load instruction or config files from the projects you point it at, and memory lives per agent, but there is no validation, provenance or review step for memory writes and automatic checkpoints are off.

- **S L0:** The model can rewrite workspace instruction and memory files that are re-injected as trusted system-prompt context. Evidence: [src/qwenpaw/runtime/prompt_contributors.py:37](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/runtime/prompt_contributors.py#L37); [src/qwenpaw/agents/md_files/en/AGENTS.md:46](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/agents/md_files/en/AGENTS.md#L46) (verified)
  - *To reach the next level:* No gate, validation or provenance on memory and instruction-file writes.
- **C L0:** No memory or instruction-file path is controlled. Evidence: [src/qwenpaw/runtime/prompt_contributors.py:37](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/runtime/prompt_contributors.py#L37) (verified)
  - *To reach the next level:* L1 needs at least one store controlled.
- **D L1:** Memory and instruction files are per-agent workspaces, but the project's trust model treats everyone who can message an instance as sharing it. Evidence: [src/qwenpaw/runtime/prompt_contributors.py:37](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/runtime/prompt_contributors.py#L37); [SECURITY.md:113](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/SECURITY.md#L113) (verified)
  - *To reach the next level:* No enforced per-user namespaces when several people use one instance.
- **B L1:** Poisoned instructions persist across the user's sessions and can drive tool use. Evidence: [src/qwenpaw/runtime/prompt_contributors.py:37](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/runtime/prompt_contributors.py#L37); [src/qwenpaw/checkpoints/policy.py:40-41](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/checkpoints/policy.py#L40-L41) (verified)
  - *To reach the next level:* Persists and triggers tools; L2 needs it to influence only text or gated actions.
- **Cap:** none

### C7 Third-party extensions: 0.17 (high confidence)

QwenPaw loads three kinds of third-party code: plugins from its marketplace, which are imported into the main process; skills, which run with the process's privileges and are only scanned in warn mode; and MCP servers, which the user adds and whose calls ask for approval by default. Nothing third-party is verified: plugin archives are installed without checking the catalog's listed hash, and the shipped external-agent entries launch npm packages at whatever version is latest, though the tool that uses them is off by default. A malicious plugin gets everything the agent has.

- **S L1:** User-chosen sources with no pinning or integrity check at install or launch. Evidence: [src/qwenpaw/plugins/download_catalog.py:278](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/plugins/download_catalog.py#L278); searched `rg -n 'sha256|hashlib'` in `src/qwenpaw/app/routers/plugins.py src/qwenpaw/plugins/loader.py` → 0 hits (no digest check on the plugin install route or in the loader; the catalog's sha256 is only listed); [src/qwenpaw/config/config.py:245-249](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/config/config.py#L245-L249) (verified)
  - *To reach the next level:* No version pinning or digest verification.
- **C L0:** No extension type is verified; the skill scanner only warns by default. Evidence: searched `rg -n 'sha256|hashlib'` in `src/qwenpaw/app/routers/plugins.py src/qwenpaw/plugins/loader.py` → 0 hits (no digest check on the plugin install route or in the loader; the catalog's sha256 is only listed); [src/qwenpaw/config/config.py:3011-3012](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/config/config.py#L3011-L3012) (verified)
  - *To reach the next level:* L1 needs at least one extension type verified.
- **D L2:** Plugins and MCP servers require explicit installation, and the external-agent tool is off by default, though shipped external-agent entries are pre-enabled. Evidence: [src/qwenpaw/agents/tools/delegate_external_agent.py:989](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/agents/tools/delegate_external_agent.py#L989); [src/qwenpaw/config/config.py:245-249](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/config/config.py#L245-L249); [src/qwenpaw/drivers/adapters/mcp_card_builder.py:192-200](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/drivers/adapters/mcp_card_builder.py#L192-L200) (verified)
  - *To reach the next level:* Install does not show exactly what will run with which permissions.
- **B L0:** Plugins are imported and executed in the agent's own process, with its credentials and environment. Evidence: [src/qwenpaw/plugins/loader.py:545-573](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/plugins/loader.py#L545-L573); [SECURITY.md:74](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/SECURITY.md#L74) (verified)
  - *To reach the next level:* In-process execution; L1 needs a separate process.
- **Cap:** none

### C8 Secrets & sensitive-data protection: 0.28 (high confidence)

Stored secrets are encrypted with a master key kept in the OS keychain or a 0600 file, and the secret directory is on the file guard's protected list. But environment variables configured through QwenPaw are injected into the process environment and reach every shell subprocess, there is no general redaction before content goes to logs or the model, and a daily content-free usage ping is on unless you opt out. Anything a key can do, a hijacked shell can do with it.

- **S L2:** Fernet-encrypted secret storage with keychain or restricted-permission master key, plus masking in some API paths. Evidence: [src/qwenpaw/security/secret_store.py:4-9](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/security/secret_store.py#L4-L9) (verified)
  - *To reach the next level:* No redaction before logs and model-bound messages on all major paths.
- **C L1:** Protection covers storage at rest; subprocess environments and model-bound tool output are not filtered. Evidence: [src/qwenpaw/envs/store.py:133](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/envs/store.py#L133); [src/qwenpaw/agents/tools/shell.py:1442](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/agents/tools/shell.py#L1442) (verified)
  - *To reach the next level:* Logs, transcripts, subprocess env and model-bound messages not covered.
- **D L1:** Content-free telemetry is on by default and requires an opt-out. Evidence: [src/qwenpaw/utils/telemetry.py:24-25](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/utils/telemetry.py#L24-L25); [src/qwenpaw/app/_app.py:678](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/app/_app.py#L678); [src/qwenpaw/utils/telemetry.py:235](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/utils/telemetry.py#L235) (verified)
  - *To reach the next level:* Telemetry is opt-out, not opt-in.
- **B L0:** Long-lived keys set through the environment manager reach every subprocess the model starts. Evidence: [src/qwenpaw/envs/store.py:1-9](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/envs/store.py#L1-L9); [src/qwenpaw/agents/tools/shell.py:1442](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/agents/tools/shell.py#L1442) (verified)
  - *To reach the next level:* Long-lived keys are reachable by every subprocess.
- **Cap:** none

### C9 Audit & traceability: 0.50 (high confidence)

Every governed tool decision, including user approvals and denials, is written immediately to a SQLite audit log under the QwenPaw home directory with time, agent, session, tool, target and decision. It is on by default and sits outside the agent's workspace, but the unsandboxed shell can still edit it and the policy file can turn it off. Calls to MCP servers go through a separate driver path that doesn't write to this log, and the record keeps the target rather than full arguments or results.

- **S L2:** Structured per-call record with timestamp, agent, session, tool, target, decision and reason. Evidence: [src/qwenpaw/governance/audit.py:33-43](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/governance/audit.py#L33-L43); [src/qwenpaw/governance/audit.py:222-241](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/governance/audit.py#L222-L241) (verified)
  - *To reach the next level:* No requesting-principal or approver identity, and no correlation across sub-agents.
- **C L2:** All built-in tool decisions and user approvals are logged; MCP driver calls are not. Evidence: [src/qwenpaw/governance/audit.py:222-241](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/governance/audit.py#L222-L241); [src/qwenpaw/governance/tool_adapter.py:778-788](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/governance/tool_adapter.py#L778-L788); [src/qwenpaw/drivers/adapters/agentscope_tool.py:161-169](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/drivers/adapters/agentscope_tool.py#L161-L169); searched `rg -n -i 'audit'` in `src/qwenpaw/drivers` → 0 hits (the Driver/MCP invocation path never writes to the governance audit log) (verified)
  - *To reach the next level:* Extension (MCP) calls are missing from the audit log.
- **D L2:** On by default and stored outside the workspace, but alterable by the agent's process and disableable in the policy file. Evidence: [src/qwenpaw/governance/audit.py:137](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/governance/audit.py#L137); [src/qwenpaw/governance/resource_governor.py:316](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/governance/resource_governor.py#L316) (verified)
  - *To reach the next level:* Written by a component the model's shell can still reach.
- **B L2:** Each decision is committed immediately; write errors are logged and the action proceeds. Evidence: [src/qwenpaw/governance/audit.py:222-241](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/governance/audit.py#L222-L241) (verified)
  - *To reach the next level:* Not replayable as a full trajectory from the audit store and not fail-closed.
- **Cap:** none

### C10 Limits & kill switch: 0.40 (high confidence)

Runs stop after 100 reasoning steps by default, a repetition detector is on, shell commands default to 60-second timeouts, and cancelling a command kills its whole process group. There is no default token or cost cap (a token-budget gate exists only in custom loop modes), the model can ask for longer shell timeouts up to a 24-hour ceiling, sub-agents start their own step budgets, and scheduled jobs keep running after a chat is stopped.

- **S L2:** Iteration cap plus per-tool timeouts and a repeated-action detector; halt kills the shell's process group. Evidence: [src/qwenpaw/config/config.py:1777-1778](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/config/config.py#L1777-L1778); [src/qwenpaw/config/config.py:1412-1418](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/config/config.py#L1412-L1418); [src/qwenpaw/agents/tools/shell.py:1187-1196](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/agents/tools/shell.py#L1187-L1196); [src/qwenpaw/agents/tools/shell.py:1246](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/agents/tools/shell.py#L1246) (verified)
  - *To reach the next level:* No token or cost cap enforced by default.
- **C L2:** Top-level loop plus tool timeouts; sub-agents run their own iteration budgets. Evidence: [src/qwenpaw/config/config.py:1777-1778](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/config/config.py#L1777-L1778); [src/qwenpaw/agents/tools/agent_management.py:38](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/agents/tools/agent_management.py#L38) (verified)
  - *To reach the next level:* Sub-agents and scheduled tasks do not count against the parent's budget.
- **D L1:** Defaults exist but the model can raise its own shell timeout up to a 24-hour ceiling. Evidence: [src/qwenpaw/agents/tools/shell.py:1415-1420](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/agents/tools/shell.py#L1415-L1420); [src/qwenpaw/tool_calls/_timeout_helper.py:27](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/tool_calls/_timeout_helper.py#L27) (verified)
  - *To reach the next level:* The model can raise its limits.
- **B L1:** No spend ceiling, and scheduled work continues after a stop. Evidence: searched `rg -n 'cost_limit|spend_limit|max_cost'` in `src/qwenpaw` → 0 hits (no spend or cost ceiling anywhere in the runtime); [src/qwenpaw/tool_calls/_timeout_helper.py:27](https://github.com/agentscope-ai/QwenPaw/blob/80e412da9b5505bcac5eec6add271d09fa144c60/src/qwenpaw/tool_calls/_timeout_helper.py#L27) (verified)
  - *To reach the next level:* No tight time or cost ceiling; L2 needs moderate ceilings.
- **Cap:** none

## Rule-of-Two check
[A] untrusted input: web_fetch / browser / web_search results (src/qwenpaw/agents/tools/web_search.py:201) · [B] sensitive data/systems: read_file allowed on any path outside built-in secret patterns (src/qwenpaw/agents/tools/file_io.py:113) · [C] state change / egress: unsandboxed shell and arbitrary-URL fetch (src/qwenpaw/agents/tools/shell.py:1442) · Same default session? Yes

## Highest-impact improvements
1. Ask before any shell command that no explicit rule allows when the sandbox is off, instead of running it directly. (C2 C L0→L2, +0.150 before caps; Playbook 5)
2. Turn the OS sandbox on by default where the platform supports it, and ask before running unsandboxed when it is unavailable. (C4 D L0→L2, +0.100 before caps; Playbook 3 step 1)
3. Keep approval-level and security settings outside anything the agent's tools can write, and let only the operator change them. (C2 D L1→L3, +0.100 before caps; Playbook 5)
4. Once a session has read web or file content, require approval for outbound requests and shell commands. (C5 S L0→L2, +0.150 before caps; Playbook 1)
5. Pass shell subprocesses a scrubbed environment and redact secret patterns from tool output before it reaches the model or logs. (C8 C L1→L2, +0.075 before caps; Playbook 4)

## Re-audit log
- C2 D: L2 → L1. The effective approval level is resolved per call from settings that can be changed at runtime from inside a session, which matches the L1 anchor.
- C4 D: L2 → L0. Rated on how the alt ships: the sandbox switch defaults to off (config.py 3035-3036).
- C9 C: L3 → L2. MCP calls go through the Driver path, which never writes to the audit log (0 hits for 'audit' under drivers/).
- C7 D: L3 → L2. Shipped external-agent entries are pre-enabled with unpinned npx packages, so 'nothing third-party enabled by default' is not fully met.
- C1 D: L1 → L0. No narrower default identity exists to be widened; least privilege is left to manual OS-user separation.

## Limitations
- Static source review of the pinned commit only; nothing was executed, installed, or probed.
- The web console (TypeScript) was not reviewed for rendering of model output, so zero-click exfiltration through rendered content was not assessed.
- Channel integrations (DingTalk, Lark, Discord, Telegram and others), the multi-user Hub, the desktop app and the Windows sandbox backends are outside the scored default and were only skimmed; with channels enabled, any participant who can message the agent can also answer its approval prompts, which the project documents as its trust model.
- The MCP SDK's default environment filtering for stdio servers and sub-agent budget behaviour were inferred from library and call-site reading, not traced end to end.
- Model behaviour (refusals, alignment) is out of scope; only deterministic controls were credited.
