Repository navigation
Conversation
…ions, audit log, kill switch Add a SafetyGate FastMCP middleware (src/windows_mcp/safety/) that runs before the desktop-control gate on every tool call. All protections are enabled by default and configured under [safety.*] in config.toml: - App/process allowlist for input tools (window under each point or foreground window), App launch/switch/resize and Process kill; unknown targets fail closed. - PowerShell disabled by default; "allowlist" mode accepts a single listed cmdlet and rejects chaining, substitution, redirection, quoting and encoded/nested commands. - Native MessageBoxTimeoutW confirmation (default No, timeout = deny) before process kill, closing/deleting shortcuts, FileSystem delete/move/overwrite, Registry set/delete, installer launches, UAC targets and risky cmdlets. - JSONL audit log of every call and decision, with redaction and optional screenshot. - Kill switch via flag file or latching global hotkey. - HTTP/SSE transports require a bearer token (server.require_auth) and refuse non-loopback binds unless server.allow_remote_bind is set. write_config now round-trips the [safety] section. Windows calls are isolated in safety/win32.py; unit tests use a fake platform and run on Linux. Docs: docs/safety.md.
…uniform audit rows - App launch: resolve the fuzzy Start Menu match to its real executable (exe path, .lnk target or packaged app manifest) and check that against the allowlist; deny when unresolvable. After launch, re-check the returned pid and terminate only that process if it is not allowed. Fixes "notepad" starting notepad++.exe on Italian Windows (Notepad is listed as "Blocco note"). - launch_executable: resolve bare names through absolute PATH entries only, never the current directory, and apply the allowlist to the resolved path. - Audit: every row has the same keys (reason/result/error null when not applicable); duration_ms is measured for refusals too and includes confirmation wait. - Docs and tests updated.
…ches, check .lnk targets - Start Menu launch refusals (pre-launch target check and post-launch kill) now raise LaunchDenied; SafetyGate returns a safety_denied tool error and audits decision=denied instead of a successful result. - Start Menu matching prefers an exact display name, then an entry whose executable stem equals the request (so "notepad" picks localized "Blocco note"), then fuzzy. - launch_executable on a .lnk is checked on the shortcut's target executable. - Update test_app_tool for the new missing-executable message; docs and tests.
launch_executable on a .lnk no longer passes the shortcut to CreateProcess. It reads the shortcut's target, arguments and working directory and starts the target with them (caller args appended, explicit cwd wins). The target must be an existing .exe or .com; it is re-checked against the allowlist right before start and the started pid is verified afterwards (only that pid is terminated if not allowed). Docs and tests.
The default popen argument bound subprocess.Popen at definition time, so tests that monkeypatch app.subprocess.Popen had no effect (WinError 193 on Windows).
…s without traceback
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The App launch check now resolves what will really run before matching it against the allowlist: PATH-only lookup for bare names, exact executable matches preferred over Start Menu names, and
.lnkshortcuts resolved to their target (and launched through that target). Refusals are reported uniformly assafety_deniedwith consistent audit rows. Absolute.exe/.lnkpaths are resolved directly; bare.lnk/.exe/.comnames are rejected. Path errors returnis_error=trueand are audited withresult=error. Denials and path errors are logged as a single warning line without a traceback.subprocess.Popenis looked up at call time so it can be patched in tests.Motivation
Matching only the name the agent typed could be bypassed (a shortcut or a same-named file in the working directory pointing at something else). Checking the resolved executable closes that gap.
Dependencies
Depends on #528 (stacked: this branch contains its commits). Please merge #528 first; the diff here will shrink to only this PR's commits once it is merged.
Testing
Testing: Linux run with Windows-only modules stubbed (pytest, Python 3.14). tests/test_safety_launch.py and the updated gate/policy tests pass (+29 tests vs A1). No new failures or collection errors compared with upstream main 7fd39b4 (on main the Linux harness has 6 known failures and 75 modules that cannot be collected without Windows). Also tested on a real Windows 11 desktop (LegionVins) with the Windows-only test modules and manual end-to-end runs.