Fix lock_device: refuse when elicitation unavailable

lock_device shared the confirm_write() fallback which returns True
when the client doesn't support elicitation. This meant lock could
proceed silently without user consent — confirmed by accidentally
locking a real device.

Now lock_device has its own strict path that returns an error when
elicitation fails, rather than falling through.
This commit is contained in:
Ryan Malloy 2026-01-30 12:01:17 -07:00
parent acec4b29ba
commit ef80f9eab0

View File

@ -325,15 +325,24 @@ async def lock_device(device_index: int = 0, ctx: Context = None) -> dict:
f"will be frozen forever." f"will be frozen forever."
) )
if ctx: if not ctx:
confirmed = await confirm_write(ctx, info)
else:
# No context = no way to confirm, refuse
return { return {
"error": "Lock requires interactive confirmation", "error": "Lock requires interactive confirmation",
"message": "This operation is too dangerous without user confirmation.", "message": "This operation is too dangerous without user confirmation.",
} }
# Strict confirmation — do NOT fall back to True on failure.
# Unlike regular writes, an irreversible lock must get explicit consent.
try:
result = await ctx.elicit(info, ["Confirm", "Cancel"])
confirmed = isinstance(result, AcceptedElicitation) and result.data == "Confirm"
except Exception:
return {
"error": "Lock requires elicitation support",
"message": "Your MCP client does not support elicitation. "
"Lock is too dangerous to proceed without explicit confirmation.",
}
if not confirmed: if not confirmed:
return {"cancelled": True, "message": "Lock cancelled by user"} return {"cancelled": True, "message": "Lock cancelled by user"}