Require approval for new USB devices by default - #11874
Open
acrogenesis wants to merge 14 commits into
Open
acrogenesis wants to merge 14 commits into
acrogenesis wants to merge 14 commits into
Conversation
acrogenesis
force-pushed
the
feature/usb-device-authorization
branch
6 times, most recently
from
September 15, 2026 02:53
a07e064 to
0fa3e29
Compare
acrogenesis
marked this pull request as ready for review
September 15, 2026 03:34
Co-authored-by: Outfoxxed <outfoxxed@outfoxxed.me>
acrogenesis
force-pushed
the
feature/usb-device-authorization
branch
from
September 15, 2026 04:13
0fa3e29 to
44f68f4
Compare
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.
Unknown USB accessories can reach matching kernel drivers as soon as they are connected. A malicious gadget can spoof a supported device identity and reach a vulnerable driver, as in the public Pegasus USB Ethernet report.
This enables USBGuard authorization by default for fresh installs and existing installations through a migration. Devices connected during enrollment are trusted. Deferred installs leave USBGuard disabled until owner provisioning finishes, then enroll the owner’s connected hardware before enabling enforcement. Factory reset also disables inherited USBGuard enforcement in the staged root before handing it to the new owner. New devices remain blocked until the user chooses Allow once, Always allow this device, or Keep blocked from a persistent notification. Remove > Security > USB Device Authorization disables protection; re-enabling preserves the saved policy.
Authorization and notification behavior
Optional boot protection
The default policy starts with USBGuard. Setup > Security > USB at Boot additionally captures currently connected devices into the trusted policy and applies
usbcore.authorized_default=0to current and Limine snapshot boot entries. The helper verifies effective command lines, image hashes, and embedded UKI command lines. It updates snapshot manifests and recovery copies under Limine's shared lock so later synchronization preserves the selected policy. Removal verifies permissive boot entries before full protection can be disabled; boot-only removal keeps USBGuard running.Under Secure Boot, conflicting historical UKIs are prepared before changing boot settings: verify the original hash and signature, re-sign a copy with the requested USB parameter, and update archived image names, menu hashes, and primary/backup/cache manifest references under Limine’s lock. Other embedded boot arguments and executable code are preserved. Signing failures stop the transition before settings change. Custom multi-profile or signed-PCR-policy images require their original builder; the command explains this before changing policy.
Secure Boot transitions checkpoint the boot files, snapshot cache, and USB boot settings before changes, while holding Limine’s shared lock. Nested rebuild/enrollment tools use a private mount namespace and lock inode. The helper independently verifies the configured EFI bootloader’s signature and enrolled menu hash after enrollment and before accepting the transition. If signing or verification fails, it restores the previous signed executable together with its matching menu, kernels, metadata, and settings without re-signing. This requires temporary free space on the system drive; an incomplete recovery retains its checkpoint and reports its location.
Boot protection requires disk unlock and recovery without any USB devices. Even trusted USB input is unavailable at an encrypted-disk prompt before USBGuard starts. Older snapshots predating USBGuard keep all USB disabled after startup, including keyboards, networking, and storage. The confirmation, command help, and manual disclose this limitation. Trusting current devices does not make them available in those old roots.
This is defense in depth. An approved device can still reach its driver, and device descriptors are forgeable. The Pegasus driver fix remains an upstream kernel responsibility.
Validation
Focused USB regressions and the CLI suite pass. Coverage includes enrollment and enumeration failures, policy preservation, notification readiness and retries across multiple devices, reconnect scans, identity changes during review, and boot-policy regeneration. Bash syntax and whitespace checks pass.
Live Omarchy Lab checks:
Historical UKI validation for de72b648: the new archive suite covers both transitions, cached/structured/nested references, unchanged current-image hashes, argument/code preservation, signing and enrollment failures, unsigned/corrupt originals, retries, and optional-tool lock ordering. Real sbctl/sbattach tests with ephemeral keys passed locally and in Lab, including root-only main-path success and preflight failure. In a private Lab mount namespace, the shipped helper then enabled and disabled protection using a copied real historical UKI and the real Limine rebuild, synchronization, and enrollment commands. A separate synchronization preserved each result. That initial namespace test validated signing and boot-file transitions; the subsequent firmware boot tests below cover actual enforcement. The original Lab guest’s USB policy was unchanged. Existing USB and CLI suites, syntax, and whitespace checks pass.
Bootloader signing recovery in e12c8ed4: a full Astra xhigh review found that Limine’s wrapper masks bootloader-signing failures. New regressions cover signing failure, stale enrollment, early rebuild failure, false-success hooks, recovery of existing/absent settings and manifests, and success with enrollment enabled or disabled. Real-signature tests pass locally and in Lab. A root Lab test exercises the actual namespace runner and installed Limine enrollment/restore functions. Full main-path tests using copied boot files then inject bootloader-only signing failure for both enable and disable: each rejects the transition and restores every preexisting boot-file hash and the matching signed bootloader/menu. Removing the fault lets both transitions and a separate synchronization succeed with real Limine tools. Those initial copied-filesystem tests did not exercise firmware or power-loss recovery; the subsequent firmware boot tests below cover enforcement and a reboot after signing-failure recovery. The original Lab policy and machine keys were unchanged. USB, archive, CLI, syntax, and whitespace checks pass. No fresh Astra rereview of this fix is claimed.
Earlier Lab boot/lock validation: insertion while locked remained unauthorized with no interface or block device. Normal boot exposed the expected gap before USBGuard starts. With boot protection enabled, an enrolled QEMU tablet remained unauthorized until USBGuard matched it, then appeared as a working HID mouse. An untrusted storage device stayed unauthorized. Enable/disable and policy preservation were exercised through the shipped commands. Booting into a legacy snapshot without USBGuard was not tested; its limitation was confirmed from the policy path and a safe fixture.
Earlier Astra review identified the legacy-snapshot disclosure gap, now covered in the confirmation/help/manual. Subsequent review found the deferred-owner enrollment and false-success approval issues addressed by this revision. A fresh full Astra xhigh review at
afad8530found one additional stale-request lifecycle defect. The fix in90d604f4passed a targeted Astra xhigh rereview with no actionable findings.Latest review fixes: 67d173c9 defers enrollment and enforcement until owner provisioning finishes; 58a9c95b verifies device and policy state after approval. In Lab, a newly attached owner keyboard worked before enforcement, stayed allowed after enrollment and daemon restart, and a later untrusted mouse was blocked. With deliberately conflicting policy rules, real USBGuard returned success without allowing the mouse; the updated graphical dialog reported failure and retained the request. After removing the conflict, retrying that request succeeded, saved the policy, and survived a daemon restart. The full OEM ISO provisioning flow was not rerun; its setup leaf and owner-enrollment helper were exercised directly. Focused USB, CLI, provisioning groups/user, syntax, and whitespace checks pass. Lab’s original trust policy was restored and all temporary devices removed.
Earlier focused menu, config, systemd, provisioning, and unit-file verification checks also passed. The earlier aggregate shell run had unrelated baseline and host temporary-storage failures; it is not claimed as a clean full-suite pass.
Factory-reset follow-up: afad8530 disables the restored USBGuard service in the staged factory root, keeping a new owner's keyboard usable until enrollment. Failure to disable aborts staging before the root is activated. A regression test runs the actual staging functions with real offline
systemctlin temporary roots, covering enabled/disabled/absent USBGuard, disable failure, and later re-enabling. It fails on the previous implementation and passes with the fix. This test and the USB suite pass on the host and in Lab; CLI, syntax, and whitespace checks also pass. No destructive full factory reset was performed.Notification lifecycle validation for 90d604f4: in Lab, dismissed a blocked mouse notification and removed its archived action while leaving the pending request. USBGuard restarted and reused ID
7with the identical rule; the same watcher recovered a fresh request and visible notification. Repeating action loss followed by a watcher-only restart also restored the prompt with the same daemon/device. Unplugging the test mouse removed its request. Expanded regressions cover concurrent reconnect/policy events, new daemon/watcher generations, legacy requests, and delayed removal. USB and CLI suites, syntax, and whitespace checks pass. Both services remain active and the temporary device is removed.Firmware Secure Boot validation on e12c8ed
Tested in a separate cold-cloned Lab VM with its own disk, OVMF Secure Boot NVRAM, virtual TPM, and freshly enrolled test keys. The shipped boot helper matched the PR file hash and ran with real Secure Boot detection and the normal sbctl configuration.
Access Denied -- rejected probably by Secure Boot. Linux also reported Secure Boot enabled and Setup Mode disabled..cmdlinewas rewritten and re-signed by the production helper in both directions, then successfully booted with the requested effective USB parameter.Scope: OVMF/QEMU firmware and an unencrypted virtual disk. Physical firmware, USB input at an encrypted-disk prompt, power-loss recovery, and custom multi-profile/PCR-signed images were not tested. The original Lab firmware and keys were not changed. No additional source fix was needed and no fresh Astra rereview is claimed.
Screenshots
Unknown device blocked
Review and authorization choices
Manual boot-time menu entry
Original USB at Boot confirmation
Updated USB at Boot confirmation, including legacy-snapshot recovery limits