MCP v2 PR-4: add_host + delete_host + extraArgs sanitiser + third SSH safeguard

Final v2 PR. All 11 planned write tools live. add_host/delete_host let
Claude mutate the saved-hosts list; both gated by a new allowAddHost
switch (default off) — symmetric with the allowOpenSsh gate from PR-3.5.

add_host's extraArgs are sanitised against CVE-2023-51385-class
local-RCE primitives: ProxyCommand, LocalCommand, KnownHostsCommand,
PermitLocalCommand=yes are refused server-side. Recognises both -o KEY=VAL
and -oKEY=VAL, case-insensitive on the key. The manual host manager UI
stays unrestricted (user has full agency over their own hosts).

Also fixes a pre-existing compile bug: mcp_policy.rs's policy_with test
helper was missing the ssh_safeguards field added in PR-3.5, silently
breaking the entire policy test module since then. Re-enabling those
tests is the prereq for the hard-deny rework that follows in the next
commit.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
megaproxy 2026-05-26 16:04:14 +01:00
parent 71f330e934
commit 9ebb3e4d2e
8 changed files with 513 additions and 5 deletions

View file

@ -127,7 +127,7 @@ export default function PolicyTab() {
}
function setSshSafeguard(
key: "allowOpenSsh" | "autoAllowSpawnedSsh",
key: "allowOpenSsh" | "autoAllowSpawnedSsh" | "allowAddHost",
value: boolean,
) {
mutate((p) => ({
@ -208,6 +208,24 @@ export default function PolicyTab() {
keystrokes. Only meaningful when the switch above is on.
</div>
</label>
<label className="policy-toggle-row">
<input
type="checkbox"
checked={policy.sshSafeguards.allowAddHost}
onChange={(e) =>
setSshSafeguard("allowAddHost", e.target.checked)
}
/>
<div className="policy-toggle-text">
<strong>Allow Claude to save or delete SSH hosts.</strong> When
off, the <code>add_host</code> and <code>delete_host</code> tools
refuse with a clear error only you manage the saved-hosts list
via the titlebar 🔑 picker. Extra ssh args (<code>-o ...</code>)
on saved hosts are still sanitised to reject command-execution
primitives (<code>ProxyCommand</code>, <code>LocalCommand</code>,
etc.) regardless of this switch.
</div>
</label>
</div>
<div className="policy-buckets">