Skip to content

Commit 54b084b

Browse files
author
Algis Dumbris
committed
Merge remote-tracking branch 'origin/main' into HEAD
2 parents 36da939 + e8d98a7 commit 54b084b

8 files changed

Lines changed: 583 additions & 66 deletions

CLAUDE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ All server responses include a unified `health` field: `level` (healthy|degraded
121121

122122
- **Localhost-only by default** (`127.0.0.1:8080`); **API key always required** (auto-generated and persisted if not provided).
123123
- **Agent tokens**: scoped credentials for AI agents (`mcp_agt_` prefix, HMAC-SHA256 hashed). See [docs/features/agent-tokens.md](docs/features/agent-tokens.md).
124-
- **Quarantine**: new servers quarantined until approved; Tool Poisoning Attack (TPA) detection on descriptions. **Tool-level quarantine (Spec 032)**: SHA-256 hashes detect new ("pending") and changed ("changed", rug-pull) tools. Config: `quarantine_enabled` (global), `skip_quarantine` (per-server; successor `auto_approve_tool_changes` plumbed but not yet enforced — MCP-2930/2931). See [docs/features/security-quarantine.md](docs/features/security-quarantine.md).
124+
- **Quarantine**: new servers quarantined until approved; Tool Poisoning Attack (TPA) detection on descriptions. **Tool-level quarantine (Spec 032)**: SHA-256 hashes detect new ("pending") and changed ("changed", rug-pull) tools. Trusted (non-quarantined) servers auto-approve their current toolset as a baseline; post-baseline changes/additions are reviewed unless per-server `auto_approve_tool_changes:true` (MCP-2931, deprecates `skip_quarantine`). Config: `quarantine_enabled` (global), `auto_approve_tool_changes` (per-server). See [docs/features/security-quarantine.md](docs/features/security-quarantine.md).
125125
- **`require_mcp_auth`**: when enabled, `/mcp` rejects unauthenticated requests (default off, for back-compat).
126126
- **Sensitive-data detection** (`internal/security/`): scans tool args/responses for secrets (cloud creds, private keys, API tokens, DB strings, Luhn-validated cards, sensitive file paths, high-entropy strings). On by default; integrates with the activity log. Config under `sensitive_data_detection`. See [docs/features/sensitive-data-detection.md](docs/features/sensitive-data-detection.md).
127127

docs/configuration.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -839,8 +839,8 @@ Per-server tool-change auto-approval is configured on the server entry:
839839

840840
| Field | Type | Default | Description |
841841
|-------|------|---------|-------------|
842-
| `skip_quarantine` | boolean | `false` | Skip tool-level quarantine for this server (auto-approve new tools). The current active per-server control. |
843-
| `auto_approve_tool_changes` | boolean (tri-state) | unset | Successor to `skip_quarantine`. Accepted by config now; a legacy `skip_quarantine: true` is migrated onto it on load **only when it is unset** (an explicit `false` overrides the legacy flag). **Enforcement is not yet wired**`skip_quarantine` remains the active control until an upcoming release. |
842+
| `auto_approve_tool_changes` | boolean (tri-state) | unset (= `false`) | Auto-approve **all** post-baseline tool changes AND additions for this server (disables per-server rug-pull protection). The active per-server control. A trusted server's *baseline* is auto-approved regardless of this flag. |
843+
| `skip_quarantine` | boolean | `false` | **Deprecated** — superseded by `auto_approve_tool_changes`. A legacy `skip_quarantine: true` is migrated onto `auto_approve_tool_changes` on load **only when it is unset** (an explicit `false` overrides the legacy flag). |
844844

845845
See [Tool Quarantine](features/tool-quarantine.md) for complete details.
846846

docs/features/security-quarantine.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ In addition to server-level quarantine, MCPProxy provides **tool-level quarantin
175175
See [Tool Quarantine](./tool-quarantine.md) for complete documentation on:
176176
- SHA256 hash-based tool approval
177177
- CLI commands: `mcpproxy upstream inspect` and `mcpproxy upstream approve`
178-
- Configuration: `quarantine_enabled` and `skip_quarantine` (successor key `auto_approve_tool_changes` is accepted but not yet enforced)
178+
- Configuration: `quarantine_enabled` (global) and `auto_approve_tool_changes` (per-server; deprecates `skip_quarantine`)
179179
- REST API endpoints for tool approval management
180180

181181
### Block (approve + disable)
@@ -215,7 +215,7 @@ When `quarantine_enabled` is `false`:
215215

216216
An explicit `quarantined` field in an add-server request still wins over
217217
the default, so client code can always override on a per-server basis.
218-
Per-server `skip_quarantine: true` continues to apply at the tool level (its successor `auto_approve_tool_changes` becomes the active control in an upcoming release).
218+
Per-server `auto_approve_tool_changes: true` auto-approves all post-baseline tool changes and additions for that server (the deprecated `skip_quarantine: true` is migrated onto it automatically).
219219

220220
Warning: Disabling quarantine exposes your system to Tool Poisoning
221221
Attacks. Only do this on machines where every MCP server you connect to

docs/features/tool-quarantine.md

Lines changed: 56 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -29,20 +29,45 @@ This hash is compared against previously approved hashes to detect changes.
2929
| `pending` | New tool, never approved | No | No |
3030
| `changed` | Hash differs from approved hash | No | No |
3131

32+
### Trust-baseline model
33+
34+
A **trusted** server is one that is *not* under server-level quarantine
35+
(`quarantined: false`) — whether you added it that way, loaded it from config,
36+
or approved it out of quarantine. When a trusted server is discovered and it has
37+
**no prior tool-approval baseline**, its current toolset is treated as that
38+
baseline: every current tool auto-approves (status `approved`,
39+
`approved_by: "auto-baseline"`) rather than stranding as `pending`. Approving a
40+
server *is* trusting the tools it ships with.
41+
42+
Once the baseline exists, tool-level quarantine guards against later changes:
43+
44+
- An existing approved tool whose hash later changes → `changed` (rug pull) → blocked.
45+
- A genuinely-new tool that appears *after* the baseline → `pending` → blocked.
46+
47+
A **quarantined** server (`quarantined: true`) is the exception: none of its
48+
tools auto-approve — they all stay `pending` until you approve the server, which
49+
then promotes them to the baseline.
50+
3251
### Detection Flow
3352

3453
```
3554
Server connects → Tools discovered → For each tool:
36-
├─ No existing record → Status: "pending" (new tool)
37-
├─ Hash matches approved hash → Status: "approved" (unchanged)
38-
└─ Hash differs from approved hash → Status: "changed" (rug pull detected)
55+
├─ Quarantine disabled / per-server auto-approve → Status: "approved" (auto)
56+
├─ Trusted server, no baseline yet (this pass IS the baseline)
57+
│ → Status: "approved" (auto-baseline)
58+
├─ No existing record, baseline already exists → Status: "pending" (new tool)
59+
├─ Hash matches approved hash → Status: "approved" (unchanged)
60+
└─ Hash differs from approved hash → Status: "changed" (rug pull detected)
3961
```
4062

4163
When a tool is `pending` or `changed`, it is:
4264
- **Blocked from the search index** (not returned by `retrieve_tools`)
4365
- **Blocked from execution** (tool calls return an error)
4466
- **Visible in the management UI** for review
4567

68+
Index visibility and callability are driven by the **same stored status**, so a
69+
tool is never indexed/visible while being uncallable (or vice versa).
70+
4671
## Configuration
4772

4873
### Global Setting
@@ -61,37 +86,52 @@ Tool-level quarantine is enabled by default. To disable:
6186

6287
### Per-Server Auto-Approve
6388

64-
Trust specific servers by skipping per-server tool-change review:
89+
By default a trusted server's baseline auto-approves, but **post-baseline
90+
changes and additions are still reviewed** (`changed` / `pending`). To opt a
91+
server out of that review entirely — auto-approving every change and addition,
92+
including rug-pulls — set `auto_approve_tool_changes: true`:
6593

6694
```json
6795
{
6896
"mcpServers": [
6997
{
7098
"name": "trusted-internal-server",
7199
"command": "my-mcp-server",
72-
"skip_quarantine": true
100+
"auto_approve_tool_changes": true
73101
}
74102
]
75103
}
76104
```
77105

78106
| Field | Type | Default | Description |
79107
|-------|------|---------|-------------|
80-
| `skip_quarantine` | boolean | `false` | Skip tool-level quarantine for this server (auto-approve new tools). The current active per-server control. |
81-
| `auto_approve_tool_changes` | boolean (tri-state) | unset | Successor to `skip_quarantine`. Accepted by config now; a legacy `skip_quarantine: true` is migrated onto it on load **only when it is unset**, so an explicit `auto_approve_tool_changes: false` overrides a legacy `skip_quarantine: true`. |
108+
| `auto_approve_tool_changes` | boolean (tri-state) | unset (= `false`) | Auto-approve **all** post-baseline tool changes AND additions for this server, disabling per-server rug-pull protection. The active per-server control. |
109+
| `skip_quarantine` | boolean | `false` | **Deprecated** — superseded by `auto_approve_tool_changes`. A legacy `skip_quarantine: true` is migrated onto `auto_approve_tool_changes` on load **only when the latter is unset**, so an explicit `auto_approve_tool_changes: false` overrides a legacy `skip_quarantine: true`. |
82110

83-
> **Note — rollout:** `auto_approve_tool_changes` is config-plumbed but its **enforcement is not yet wired** — runtime auto-approval is still governed by `skip_quarantine`. The new flag becomes the active control (and gains the richer rug-pull / trust-baseline behavior) in an upcoming release. Existing `skip_quarantine` configs are unaffected and are migrated onto the new key automatically. To auto-approve a server today, set `skip_quarantine: true`.
111+
> **Security:** `auto_approve_tool_changes: true` turns off rug-pull detection for
112+
> that server — a later malicious description/schema change is silently approved.
113+
> Only enable it for servers you fully control.
84114
85115
> **REST API:** `auto_approve_tool_changes` round-trips through the server REST API. `GET /api/v1/servers` includes it on each server object (omitted when unset — the tri-state nil is preserved so the Web UI can tell "never set" from an explicit `false`), and `POST`/`PATCH /api/v1/servers/{id}` accept it. As a tri-state `*bool`, omitting it on `PATCH` leaves the stored value unchanged; sending an explicit `false` clears a prior `true`. The value is persisted to BBolt so it survives a save/restart.
86116
87-
When the active control is enabled for a server, new tools from it are automatically approved.
88-
89117
### Auto-Approve Behavior
90118

91119
Tools are automatically approved (no manual review needed) when:
92-
- `quarantine_enabled` is `false` globally
93-
- The server has `skip_quarantine: true` (the active per-server control; `auto_approve_tool_changes` becomes active in an upcoming release)
94-
- The auto-approval is recorded with `approved_by: "auto"` in the approval record
120+
- `quarantine_enabled` is `false` globally, or the server still carries the
121+
deprecated `skip_quarantine: true` — recorded with `approved_by: "auto"`.
122+
- A **trusted server establishes its baseline** (first discovery with no prior
123+
baseline, or migrating already-stranded `pending` tools whose hash is
124+
unchanged) — recorded with `approved_by: "auto-baseline"`.
125+
- The server has `auto_approve_tool_changes: true` and a post-baseline change or
126+
addition occurs — recorded with `approved_by: "auto-approve-changes"`.
127+
128+
#### Migrating existing installs
129+
130+
Earlier releases stranded trusted-server tools as `pending`. On upgrade, the
131+
next discovery pass on a trusted server with no approved baseline promotes those
132+
stranded `pending` records (whose stored hash matches the live tool) to
133+
`approved` automatically — no user action required. A `changed` (rug-pull)
134+
record is **never** cleared by this migration.
95135

96136
## Managing Tool Approvals
97137

@@ -293,7 +333,7 @@ Tool quarantine events are recorded in the activity log:
293333
| Event | Description |
294334
|-------|-------------|
295335
| `tool_discovered` | New tool found, pending approval |
296-
| `tool_auto_approved` | New tool automatically approved (trusted server) |
336+
| `tool_auto_approved` | Tool automatically approved (quarantine off, baseline trust, or `auto_approve_tool_changes`) |
297337
| `tool_approved` | Tool manually approved by user |
298338
| `tool_description_changed` | Tool description/schema changed since approval |
299339

@@ -323,15 +363,15 @@ Tool-level quarantine is a separate system from [server-level quarantine](./secu
323363
| **Scope** | Entire server | Individual tools |
324364
| **Trigger** | Server added via AI client | Tool description/schema changes |
325365
| **Detection** | Manual review | SHA256 hash comparison |
326-
| **Config** | `quarantined: true/false` on server | `quarantine_enabled` global + `skip_quarantine` per-server (successor `auto_approve_tool_changes` not yet enforced) |
366+
| **Config** | `quarantined: true/false` on server | `quarantine_enabled` global + `auto_approve_tool_changes` per-server (deprecates `skip_quarantine`) |
327367
| **Approval** | `POST /servers/{name}/unquarantine` | `POST /servers/{name}/tools/approve` |
328368

329369
Both systems work together: a quarantined server's tools are never indexed regardless of tool approval status.
330370

331371
## Best Practices
332372

333373
1. **Review changed tools carefully**: A `changed` status may indicate a rug pull attack where a malicious server silently modifies tool descriptions
334-
2. **Use `skip_quarantine` for internal servers**: If you control the MCP server and trust it, skip quarantine to avoid manual approval on every update (the successor key `auto_approve_tool_changes` becomes the active control in an upcoming release)
374+
2. **Use `auto_approve_tool_changes` sparingly**: A trusted server's baseline is already auto-approved; only set `auto_approve_tool_changes: true` for servers you fully control where you also want post-baseline changes/additions approved without review (this disables rug-pull protection for that server). The deprecated `skip_quarantine: true` is migrated onto this key automatically.
335375
3. **Monitor the doctor output**: Run `mcpproxy doctor` regularly to check for pending tools
336376
4. **Export descriptions for audit**: Use the export API to keep records of approved tool descriptions
337377
5. **Check activity logs**: Monitor `tool_description_changed` events for unexpected changes

0 commit comments

Comments
 (0)