Skip to content

Add --allow-system-keys to ui send-keys#603

Open
yeelam-gordon wants to merge 1 commit into
mainfrom
yeelam/ui-allow-system-keys
Open

Add --allow-system-keys to ui send-keys#603
yeelam-gordon wants to merge 1 commit into
mainfrom
yeelam/ui-allow-system-keys

Conversation

@yeelam-gordon

Copy link
Copy Markdown

Summary

  • add --allow-system-keys to winapp ui send-keys
  • keep the default safety posture (system-/shell-reserved combos are still blocked) and require an explicit opt-in for OS-wide hotkeys via --via send-input
  • preserve the existing no-target, foreground, and secure-desktop safeguards

Why

This enables intentional global hotkey automation (for example, PowerToys-style Win-key shortcuts) without weakening the default behavior.

By default, send-keys --via send-input refuses system-/shell-reserved combos
(win+<key>, alt+f4, alt+tab, ctrl+esc, ...) via SystemKeyGuard because they act
on the OS/shell beyond the target app when injected OS-wide. --allow-system-keys
is an explicit opt-in that bypasses that one guard so a caller can drive a
global hotkey (e.g. PowerToys' win+shift+v) - the low-level global hook watches
the OS-wide input stream, so the injected combo fires it.

- Default is unchanged (flag absent = still rejected); the bypass path logs an
  audit warning listing only the combo names (never the raw keys), consistent
  with the existing no-echo policy.
- No other boundary is relaxed: the no-target guard, foreground/locked-desktop
  guard (no_interactive_desktop), UIPI, and post-message path are untouched.
  Windows still blocks secure sequences like ctrl+alt+del (SAS) regardless.
- 4 new unit tests (flag sends, non-system combo unaffected, default still
  rejects, description discoverable); 55/55 send-keys + guard tests green.
- Docs + cli-schema + SKILL.md mirrors regenerated at 0.4.1.

Proven end-to-end: default rejects win+r; --allow-system-keys makes win+r open
the Run dialog (a Win-modified shell hotkey firing off the injected stream).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings July 6, 2026 03:00

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds an opt-in --allow-system-keys flag to winapp ui send-keys. By default, --via send-input refuses to synthesize system-/shell-reserved combos (e.g. win+l, alt+f4, alt+tab) because those act OS-wide beyond the target app. The new flag lets a caller explicitly opt in to fire global hotkeys (e.g. PowerToys' win+shift+v) while preserving the default safety posture and all existing guards (no-target, foreground, secure-desktop). It fits into the ui automation surface of the CLI, extending the existing SystemKeyGuard gate rather than removing it.

Changes:

  • Adds AllowSystemKeysOption to UiSendKeysCommand; when a system combo is detected under send-input, the guard now blocks by default but falls through (with a warning) when the flag is set.
  • Adds four unit tests covering opt-in send, non-system no-op, default rejection, and option-description discoverability.
  • Updates all documentation surfaces (ui-automation.md, skill fragment, cli-schema.json, and both generated SKILL.md mirrors) to describe the flag.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
src/winapp-CLI/WinApp.Cli/Commands/UiSendKeysCommand.cs Adds --allow-system-keys option and the conditional guard-bypass path with an audit warning
src/winapp-CLI/WinApp.Cli.Tests/UiCommandTests.SendKeys.cs Four new tests for the opt-in, unaffected non-system path, default rejection, and help-text content
docs/ui-automation.md Documents the flag and updates the system-reserved-combos guidance
docs/fragments/skills/winapp-cli/ui-automation.md Hand-written skill fragment updated with the opt-in example and behavior
docs/cli-schema.json Regenerated schema entry for the new boolean option
.github/plugin/skills/winapp-cli/ui-automation/SKILL.md Auto-generated skill mirror (example + options-table row)
.claude/skills/winapp-ui-automation/SKILL.md Auto-generated Claude skill mirror (example + options-table row)

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +231 to +237
// Caller explicitly opted in with --allow-system-keys (e.g. to fire a global hotkey such as
// PowerToys' win+shift+v). Record the bypass so it's auditable in persisted logs, then fall
// through and inject. (Windows still blocks secure sequences like ctrl+alt+del regardless.)
logger.LogWarning(
"{Symbol} Injecting system-reserved key(s) via --via send-input because --allow-system-keys was set: {Combos}. " +
"These act on the OS/shell beyond the target app.",
UiSymbols.Warning, string.Join(", ", systemCombos));
@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Build Metrics Report

Binary Sizes

Artifact Baseline Current Delta
CLI (ARM64) 31.71 MB 31.71 MB 📈 +1.5 KB (+0.00%)
CLI (x64) 32.04 MB 32.04 MB 📈 +2.0 KB (+0.01%)
MSIX (ARM64) 13.30 MB 13.30 MB 📈 +1.6 KB (+0.01%)
MSIX (x64) 14.15 MB 14.15 MB 📉 -1.2 KB (-0.01%)
NPM Package 27.77 MB 27.77 MB 📈 +0.2 KB (+0.00%)
NuGet Package 27.79 MB 27.79 MB 📈 +1.4 KB (+0.01%)
VS Code Extension 20.60 MB 20.60 MB 📈 +0.1 KB (+0.00%)

Test Results

1549 passed, 1 skipped out of 1550 tests in 465.4s (+4 tests, -12.6s vs. baseline)

Test Coverage

18.1% line coverage, 37.3% branch coverage · ✅ no change vs. baseline

CLI Startup Time

35ms median (x64, winapp --version) · ✅ -8ms vs. baseline


Updated 2026-07-06 03:17:34 UTC · commit 557dc36 · workflow run

@nmetulev nmetulev left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 AI-generated review — produced by GitHub Copilot CLI at a maintainer's request. Every finding comes from an automated, multi-dimensional review plus a hands-on build-and-test of this branch in an isolated worktree. Treat file:line references as pointers to verify, not gospel. Nothing was pushed. Posting as a comment (no approve / request-changes).

Verdict: 🟡 SHIP-WITH-CHANGES — The double opt-in design is sound and the existing guards stay intact, but win+l should remain blocked and the silent no-op path needs a warning.

What I actually ran

Built (~33s, 0 warnings); 55/55 SendKeys + SystemKeyGuard tests pass. Against Notepad:

  • Normal text send-keys ✅.
  • win+l via --via send-input without the flag → BLOCKED, exit 1, with a clear, actionable error naming the combo and "Pass --allow-system-keys to opt in." ✅
  • win+up with --allow-system-keys --via send-input → fired OS-wide (Notepad maximized); win+down restored it — self-reversing ✅. (Injection works here when the target is foregrounded first.)
  • win+l with --allow-system-keys but no --via send-input → exit 0, via":"post-message", no warning, hotkey never fires (SEC-02).
  • No-target guard still fires with the flag ✅.

Must-fix

  • SEC-01 (High) — win+l is unblocked by the flag with no per-combo granularity (SystemKeyGuard.cs:56-59 collapses everything to a generic win+<key>; bypass at UiSendKeysCommand.cs:244). win+l is not a SAS — a user-mode SendInput of VK_LWIN+L reaches explorer's low-level hook and calls LockWorkStation(). A mistyped win+l vs win+left in automation locks the (remote) desktop. Consider keeping win+l (and alt+f4 / ctrl+shift+esc) blocked even with the opt-in; the cited use case is registered hotkeys like win+shift+v, not lock control.
  • SEC-02 (Medium) — silent no-op. --allow-system-keys without --via send-input is silently accepted (exit 0, no effect). Emit a LogWarning so this isn't a silent footgun.
  • COR-01 add a test for the --allow-system-keys + post-message path. DOCS-02 the docs name only ctrl+alt+del as "still blocked," implying other combos are safe — call out win+l / alt+f4 explicitly.

Fit & recommendation

Real, unmet use case (global hotkeys are unreachable via post-message), default posture unchanged, guards preserved, an actionable agent-readable error, and a LogWarning audit trail on every bypass. The tension is the security surface: a CLI/agent can now fire OS-wide hotkeys. The blanket on/off is acceptable to start if the docs and the win+l gap are addressed; a per-combo allowlist (e.g. --allow-system-keys win+shift+v) would be a cleaner long-term design and would keep the blast radius to what the caller actually needs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants