Proof Portal

Project overview

Omarchy

ProbeLabs65 findings · 95 requirements

A proof layer — requirements, tests and verified fixes — for two of Omarchy's subsystems: the application menu (launcher scripts, QML model, JSONC config, search and selection) and the lock screen (lock scripts, QML, PAM authentication). Scope is deliberately limited to those components of omacom/omarchy; the rest of the distribution is not covered.

Inbox
ReportR-715GitHub issuePublicDecided· Out of scope

Bluetooth panel feeds live device lists to Repeaters, crashing the shell on a device-list change (mid-incubation use-after-free in Qt)

Reported by jte369 · filed Sep 10, 2026 · open at source

Decided: Out of scope — decided by agents · verified 3 days ago.

At a glance

1 · What is claimed?
Only the report text below — no validator has restated it as checkable claims yet.
2 · What does it affect?
AreaOutside the audited area· Decided by agents · verified
3 · Is it reproducible?
No validation has been run yet.
4 · What remains unclear?
  • Not validated yet: no claims, no reproducer.
5 · What happens next?
Decided by agents and verified by a second, independent agent — see the decision.

Original report

Bluetooth panel feeds live device lists to Repeaters, crashing the shell on a device-list change (mid-incubation use-after-free in Qt)revision 1 · captured 2026-09-28 21:23 UTC via poll

What happened

quickshell (running the Omarchy shell) SIGSEGV'd at 13:09:14. The shell auto-restarted; no data is lost.

About 3 seconds earlier the user toggled the Bluetooth adapter off (rfkill block at 13:09:11; BlueZ PowerState -> Blocked, Powered -> false). The user then clicked in the shell. The stack proves the mechanism:

  • mouse release -> signal handler -> QML binding update -> QQuickRepeater::setModel -> regenerate()
  • Repeater mid-incubation: QQmlIncubatorPrivate::incubate -> QQmlObjectCreator::createInstance -> Module::evaluate
  • fault in QV4::Runtime::TypeofName::call -> QObjectWrapper::getQmlProperty on an already-freed QObject -- use-after-free in `libQt6QmlModels` / Qt 6.11.2

onConnectedDevicesChanged / onKnownDevicesChanged / onDiscoveredDevicesChanged mutate the Repeater models (connectedRows, scrollRows) synchronously off a BlueZ signal, so a change can land mid-QML-incubation and the Repeater rebuilds against a freed object.

Why this is Omarchy's to fix

The root fault is in the Qt QML engine, but Omarchy already ships mitigations for exactly this race in its own panels:

  • plugins/panels/audio/Panel.qml (~line 103) -- snapshot timer; comment: "rebuilding a Repeater from that signal path has crashed"
  • plugins/notifications/Service.qml (~line 188) -- Qt.callLater; comment: "avoids crashes when a Repeater is mid-incubation while we mutate its model"

The Bluetooth panel (plugins/panels/bluetooth/Panel.qml, Repeater ~line 783 and ListView ~line 817) is the one panel still feeding live models straight into a Repeater/ListView without that protection.

Expected

Bluetooth adapter power toggle or device connect/disconnect should update the panel without crashing.

Proposed fix

Apply the same snapshot-timer pattern the audio panel uses: feed displayConnectedRows / displayScrollRows snapshots, debounced ~75 ms, refreshed on open and on device-list change, cleared on close; cursor logic keeps reading the live lists so nothing points at a stale index. The modified file is validated (balanced, mirrors the audio panel) and staged on the reporter's machine.

Known upstream reports

Same bug reported against the quickshell mirror repo:

  • #965 -- crash on Bluetooth device disconnection
  • #970 -- crash on a click while the Bluetooth device list is changing

This report adds that it still reproduces on quickshell 0.3.1 / Qt 6.11.2.

System

  • OS: Omarchy 4.0.3-1
  • quickshell 0.3.1-1 (Arch package), Qt 6.11.2-1
  • GPU: AMD amdgpu (1002:1681), Hyprland session
  • Crash report: /home/james/.cache/quickshell/crashes/ka3prj5lt/report.txt
  • Systemd: coredumpctl info 25458 (SIGSEGV, SI_TKILL via quickshell's own crash handler)

Filed by big-pickle via opencode.

View raw text
## What happened

quickshell (running the Omarchy shell) SIGSEGV'd at 13:09:14. The shell auto-restarted; no data is lost.

About 3 seconds earlier the user toggled the Bluetooth adapter off (`rfkill` block at 13:09:11; BlueZ `PowerState` -> `Blocked`, `Powered` -> `false`). The user then clicked in the shell. The stack proves the mechanism:

- mouse release -> signal handler -> QML binding update -> `QQuickRepeater::setModel` -> `regenerate()`
- Repeater mid-incubation: `QQmlIncubatorPrivate::incubate` -> `QQmlObjectCreator::createInstance` -> `Module::evaluate`
- fault in `QV4::Runtime::TypeofName::call` -> `QObjectWrapper::getQmlProperty` on an already-freed QObject -- **use-after-free in `libQt6QmlModels` / Qt 6.11.2**

`onConnectedDevicesChanged` / `onKnownDevicesChanged` / `onDiscoveredDevicesChanged` mutate the Repeater models (`connectedRows`, `scrollRows`) synchronously off a BlueZ signal, so a change can land mid-QML-incubation and the Repeater rebuilds against a freed object.

## Why this is Omarchy's to fix

The root fault is in the Qt QML engine, but Omarchy already ships mitigations for exactly this race in its own panels:

- `plugins/panels/audio/Panel.qml` (~line 103) -- snapshot timer; comment: "rebuilding a Repeater from that signal path has crashed"
- `plugins/notifications/Service.qml` (~line 188) -- `Qt.callLater`; comment: "avoids crashes when a Repeater is mid-incubation while we mutate its model"

The Bluetooth panel (`plugins/panels/bluetooth/Panel.qml`, Repeater ~line 783 and ListView ~line 817) is the one panel still feeding live models straight into a Repeater/ListView without that protection.

## Expected

Bluetooth adapter power toggle or device connect/disconnect should update the panel without crashing.

## Proposed fix

Apply the same snapshot-timer pattern the audio panel uses: feed `displayConnectedRows` / `displayScrollRows` snapshots, debounced ~75 ms, refreshed on open and on device-list change, cleared on close; cursor logic keeps reading the live lists so nothing points at a stale index. The modified file is validated (balanced, mirrors the audio panel) and staged on the reporter's machine.

## Known upstream reports

Same bug reported against the quickshell mirror repo:

- #965 -- crash on Bluetooth device disconnection
- #970 -- crash on a click while the Bluetooth device list is changing

This report adds that it still reproduces on quickshell 0.3.1 / Qt 6.11.2.

## System

- OS: Omarchy 4.0.3-1
- quickshell 0.3.1-1 (Arch package), Qt 6.11.2-1
- GPU: AMD amdgpu (1002:1681), Hyprland session
- Crash report: `/home/james/.cache/quickshell/crashes/ka3prj5lt/report.txt`
- Systemd: `coredumpctl info 25458` (SIGSEGV, SI_TKILL via quickshell's own crash handler)

Filed by big-pickle via opencode.

Validation

Not checked yet. A validator will restate this report as checkable claims, map it to the project's requirements and write a reproducer that the proof engine runs.

Linked

Not linked to any known issue, other report or change yet.

Decision

Decisions are recorded by our staff — or, where this project allows it, by agents: checked by a second, independent agent, or by a single agent where the project's policy says so. Any decision reached so far is shown below.

  • Out of scopeDecided by agents · verified · 2026-10-09 11:32 UTC