@@ -88,8 +88,13 @@ Use this to whitelist specific functions you trust the LLM to use freely."
8888 :type 'integer
8989 :group 'mcp-server )
9090
91- (defcustom mcp-server-security-prompt-for-permissions t
92- " Whether to prompt user for dangerous operations."
91+ (defcustom mcp-server-security-prompt-for-permissions nil
92+ " Whether to prompt user in Emacs for dangerous operations.
93+ When nil (the default), dangerous operations are blocked without prompting.
94+ The MCP client uses tool annotations to determine whether to prompt for
95+ tool-level permission, but the blocklist is always enforced.
96+ Set to t to prompt in the Emacs minibuffer instead of blocking, allowing
97+ users to approve dangerous operations on a case-by-case basis."
9398 :type 'boolean
9499 :group 'mcp-server )
95100
@@ -148,7 +153,7 @@ Returns t if permitted, nil otherwise."
148153 ('no
149154 (mcp-server-security--log-audit operation data nil )
150155 nil )))
151- ; ; If not prompting, deny dangerous operations by default
156+ ; ; When not prompting, still block dangerous operations
152157 (let ((granted (not (mcp-server-security--is-dangerous-operation operation))))
153158 (puthash cache-key granted mcp-server-security--permission-cache)
154159 (mcp-server-security--log-audit operation data granted)
@@ -213,20 +218,20 @@ Returns the input if safe, signals an error otherwise."
213218 ; ; Check for shell command injection
214219 (when (string-match-p " [;&|`$]" input)
215220 (error " Input contains potentially dangerous shell characters " ))
216-
221+
217222 ; ; Check for path traversal
218223 (when (string-match-p " \\ .\\ ./\\ |~/" input)
219224 (error " Input contains potentially dangerous path patterns " ))
220-
225+
221226 ; ; Check for excessive length
222227 (when (> (length input) 10000 )
223228 (error " Input exceeds maximum length " )))
224-
229+
225230 ; ; Check for suspicious elisp code patterns in strings
226231 (when (and (stringp input)
227232 (string-match-p " (\\ s-*\\ (?:eval\\ |load\\ |shell-command\\ )" input))
228233 (error " Input contains potentially dangerous elisp patterns " ))
229-
234+
230235 input)
231236
232237(defun mcp-server-security-sanitize-string (str )
@@ -245,7 +250,7 @@ Returns the input if safe, signals an error otherwise."
245250 " Safely evaluate FORM with security restrictions."
246251 ; ; Check if form contains dangerous functions
247252 (mcp-server-security--check-form-safety form)
248-
253+
249254 ; ; Execute with timeout and memory limits
250255 (mcp-server-security--execute-with-limits
251256 (lambda () (eval form))))
@@ -258,8 +263,9 @@ Returns the input if safe, signals an error otherwise."
258263 (when (and (member form mcp-server-security-dangerous-functions)
259264 (not (member form mcp-server-security-allowed-dangerous-functions)))
260265 (unless (mcp-server-security-check-permission form)
261- (error " Permission denied for function: %s " form))))
262-
266+ (error " Security: `%s' is blocked. Add it to `mcp-server-security-allowed-dangerous-functions' \
267+ to allow, or set `mcp-server-security-prompt-for-permissions' to t to prompt " form))))
268+
263269 ; ; Check lists (function calls)
264270 ((listp form)
265271 (when form
@@ -270,26 +276,27 @@ Returns the input if safe, signals an error otherwise."
270276 (when (and (member func mcp-server-security-dangerous-functions)
271277 (not (member func mcp-server-security-allowed-dangerous-functions)))
272278 (unless (mcp-server-security-check-permission func args)
273- (error " Permission denied for function: %s " func)))
274-
279+ (error " Security: `%s' is blocked. Add it to `mcp-server-security-allowed-dangerous-functions' \
280+ to allow, or set `mcp-server-security-prompt-for-permissions' to t to prompt " func)))
281+
275282 ; ; Special checks for file access functions
276283 (when (memq func '(find-file find-file-noselect view-file insert-file-contents))
277284 (let ((file-path (car args)))
278285 (when (and file-path (stringp file-path))
279286 (when (mcp-server-security--is-sensitive-file file-path)
280- (unless (mcp-server-security-check-permission
287+ (unless (mcp-server-security-check-permission
281288 (format " access-sensitive-file:%s " func) file-path)
282289 (error " Permission denied for sensitive file access: %s " file-path))))))
283-
290+
284291 ; ; Special checks for buffer access functions
285292 (when (memq func '(switch-to-buffer set-buffer with-current-buffer))
286- (let ((buffer-name (if (eq func 'with-current-buffer )
293+ (let ((buffer-name (if (eq func 'with-current-buffer )
287294 (car args)
288295 (car args))))
289296 (when (and buffer-name (stringp buffer-name))
290297 (when (mcp-server-security--is-sensitive-buffer buffer-name)
291298 (error " Access denied to sensitive buffer: %s " buffer-name))))))
292-
299+
293300 ; ; Recursively check arguments
294301 (dolist (arg args)
295302 (mcp-server-security--check-form-safety arg)))))))
@@ -298,18 +305,18 @@ Returns the input if safe, signals an error otherwise."
298305 " Execute FUNC with time and memory limits."
299306 (let ((start-time (current-time ))
300307 (start-gc-cons-threshold gc-cons-threshold))
301-
308+
302309 ; ; Set conservative GC threshold for memory monitoring
303310 (setq gc-cons-threshold 1000000 )
304-
311+
305312 (unwind-protect
306313 (with-timeout (mcp-server-security-max-execution-time
307314 (error " Execution timeout exceeded " ))
308315 (funcall func))
309-
316+
310317 ; ; Restore GC threshold
311318 (setq gc-cons-threshold start-gc-cons-threshold)
312-
319+
313320 ; ; Log execution time
314321 (let ((elapsed (float-time (time-subtract (current-time ) start-time))))
315322 (when (> elapsed 5.0 )
@@ -324,7 +331,7 @@ Returns the input if safe, signals an error otherwise."
324331 (data . , data )
325332 (granted . , granted ))))
326333 (push entry mcp-server-security--audit-log)
327-
334+
328335 ; ; Keep only last 1000 entries
329336 (when (> (length mcp-server-security--audit-log) 1000 )
330337 (setq mcp-server-security--audit-log
0 commit comments