Proof Portal
Omarchy
ProbeLabs65 findings · 95 requirementsA 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.
windows-vm: chmod 0700 preserves directory setgid bit, causing launch to fail safety check
Reported by VillainRU · filed Aug 31, 2026Closed upstream on 2026-09-20 by bjarneo via an automated message, as a duplicate of #9334 (R-1173). GitHub close reason: completed.
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?
- Not yet mapped to any requirement or component.
- 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?
- Our staff decide whether the report is valid. Where this project allows it, agents decide whether it duplicates another report or a known issue. No decision has been recorded yet.
Original report
System details
- CPU: AMD Ryzen 7 5700X3D
- GPU: AMD Radeon RX 9070/9070 XT/9070 GRE (Navi 48)
- Omarchy: 4.0.2-1
- Kernel: 7.1.9-arch1-2
- GNU coreutils: 9.11
What's wrong?
The Windows VM launcher exits immediately after successful polkit authorization and shows the critical notification:
Windows VM — Failed to start Windows VM
This happens when either VM source directory has a set-ID bit in addition to the expected private permissions. In my case, ~/Windows had mode 2700 (drwx--S---). The VM data itself and Docker were healthy.
Steps to reproduce
- Install/configure the Omarchy Windows VM.
- Add the set-group-ID bit to the shared directory:
chmod g+s ~/Windows
stat -c '%a' ~/Windows # 2700- Launch the VM from the menu or run
omarchy-windows-vm launch. - Approve the polkit prompt.
The launcher fails before starting the Docker container.
The underlying chmod behavior can also be reproduced without the VM:
dir=$(mktemp -d)
chmod 2700 "$dir"
chmod 0700 "$dir"
stat -c '%a' "$dir" # still 2700
chmod a-s,u=rwx,go= "$dir"
stat -c '%a' "$dir" # 700
rmdir "$dir"Root cause
prepare_caller_mounts() attempts to normalize both directories and then requires their modes to equal exactly 700:
chmod 0700 -- "/proc/$BASHPID/fd/$storage_fd" "/proc/$BASHPID/fd/$shared_fd"
storage_mode=$(stat -Lc '%a' "/proc/$BASHPID/fd/$storage_fd")
shared_mode=$(stat -Lc '%a' "/proc/$BASHPID/fd/$shared_fd")
if [[ $storage_mode != 700 || $shared_mode != 700 ]]; then
return 1
fiGNU chmod deliberately preserves set-user-ID and set-group-ID bits on directories when a plain numeric mode such as 0700 is used. Therefore the normalization reports success but leaves 2700 unchanged, and the exact-mode check immediately rejects it.
Reference: https://www.gnu.org/software/coreutils/manual/html_node/Operator-Numeric-Modes.html
Expected behavior
The privacy normalization should explicitly clear special bits so that the following exact-mode safety check can succeed.
Suggested fix
Use a symbolic mode that clears set-ID bits explicitly:
- chmod 0700 -- "/proc/$BASHPID/fd/$storage_fd" "/proc/$BASHPID/fd/$shared_fd" || {
+ chmod a-s,u=rwx,go= -- "/proc/$BASHPID/fd/$storage_fd" "/proc/$BASHPID/fd/$shared_fd" || {chmod =700 also clears them with GNU coreutils, but the symbolic form makes the security intent explicit. I verified locally that it changes both 2700 and 700 inputs to exactly 700, after which the protected bind-mount checks pass.
View raw text
### System details
- CPU: AMD Ryzen 7 5700X3D
- GPU: AMD Radeon RX 9070/9070 XT/9070 GRE (Navi 48)
- Omarchy: 4.0.2-1
- Kernel: 7.1.9-arch1-2
- GNU coreutils: 9.11
### What's wrong?
The Windows VM launcher exits immediately after successful polkit authorization and shows the critical notification:
> Windows VM — Failed to start Windows VM
This happens when either VM source directory has a set-ID bit in addition to the expected private permissions. In my case, `~/Windows` had mode `2700` (`drwx--S---`). The VM data itself and Docker were healthy.
### Steps to reproduce
1. Install/configure the Omarchy Windows VM.
2. Add the set-group-ID bit to the shared directory:
```bash
chmod g+s ~/Windows
stat -c '%a' ~/Windows # 2700
```
3. Launch the VM from the menu or run `omarchy-windows-vm launch`.
4. Approve the polkit prompt.
The launcher fails before starting the Docker container.
The underlying `chmod` behavior can also be reproduced without the VM:
```bash
dir=$(mktemp -d)
chmod 2700 "$dir"
chmod 0700 "$dir"
stat -c '%a' "$dir" # still 2700
chmod a-s,u=rwx,go= "$dir"
stat -c '%a' "$dir" # 700
rmdir "$dir"
```
### Root cause
`prepare_caller_mounts()` attempts to normalize both directories and then requires their modes to equal exactly `700`:
```bash
chmod 0700 -- "/proc/$BASHPID/fd/$storage_fd" "/proc/$BASHPID/fd/$shared_fd"
storage_mode=$(stat -Lc '%a' "/proc/$BASHPID/fd/$storage_fd")
shared_mode=$(stat -Lc '%a' "/proc/$BASHPID/fd/$shared_fd")
if [[ $storage_mode != 700 || $shared_mode != 700 ]]; then
return 1
fi
```
GNU `chmod` deliberately preserves set-user-ID and set-group-ID bits on directories when a plain numeric mode such as `0700` is used. Therefore the normalization reports success but leaves `2700` unchanged, and the exact-mode check immediately rejects it.
Reference: https://www.gnu.org/software/coreutils/manual/html_node/Operator-Numeric-Modes.html
### Expected behavior
The privacy normalization should explicitly clear special bits so that the following exact-mode safety check can succeed.
### Suggested fix
Use a symbolic mode that clears set-ID bits explicitly:
```diff
- chmod 0700 -- "/proc/$BASHPID/fd/$storage_fd" "/proc/$BASHPID/fd/$shared_fd" || {
+ chmod a-s,u=rwx,go= -- "/proc/$BASHPID/fd/$storage_fd" "/proc/$BASHPID/fd/$shared_fd" || {
```
`chmod =700` also clears them with GNU coreutils, but the symbolic form makes the security intent explicit. I verified locally that it changes both `2700` and `700` inputs to exactly `700`, after which the protected bind-mount checks pass.
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.
No decision has been recorded yet.