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-5274GitHub issuePublicDecided· Out of scope

shell.json can be created 0644 and keeps that mode, exposing plugin secrets to other local users

Reported by rmcdavid · filed Oct 9, 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

shell.json can be created 0644 and keeps that mode, exposing plugin secrets to other local usersrevision 1 · captured 2026-10-09 16:21 UTC via poll

Reporting this as a courtesy rather than as a complaint: shell.json holds
plugin settings, those settings can contain secrets, and the file can arrive
world-readable and stay that way.

Measured on Omarchy 4.0.4-1, Quickshell shell at /usr/share/omarchy/shell.

1. The packaged default is 0644.

$ stat -c '%a %n' /usr/share/omarchy/config/omarchy/shell.json
644 /usr/share/omarchy/config/omarchy/shell.json

2. `omarchy-refresh-config` copies it with `cp -f`, so a file that does not
yet exist is created under the caller's umask. Reproduced against the real
source into a scratch directory:

cp under umask 022 -> 644
cp under umask 077 -> 600

A copy onto an existing file keeps that file's mode, which is why a machine
that once had 0600 keeps it.

3. The shell's own writer preserves whatever mode the file already has.
shell.qml:138 uses FileView { atomicWrites: true }. A purpose-built probe,
one FileView writing one scratch file, run twice:

mode before the writeafter
06440644
06000600

The content changed both times, so the write happened. The atomic rename
neither resets the mode to the writer's umask nor tightens it.

Why it matters. ~/.config and ~/.config/omarchy are 0755 by default, so
only the home directory's mode stands between the file and other local users,
and 0755 homes are common. Plugin settings in that file routinely include URLs,
and for IPTV-style plugins a playlist URL carries the provider username and
password, either as userinfo or as query parameters. On a machine where
shell.json landed at 0644, those are readable by any other local account.

What would fix it upstream, either one:

  • ship config/omarchy/shell.json as 0600, and have omarchy-refresh-config

create the user copy with that mode rather than inheriting the umask; or
- have the shell's writer enforce 0600 on the user config when it saves, since
it already owns that file's lifecycle.

The first is a one-line packaging change and covers fresh installs; the second
also repairs machines that already have 0644.

Heads-up, so it is not a surprise. The IPTV plugin
(io.github.rmcdavid.iptv) will tighten ~/.config/omarchy/shell.json to 0600
before it writes a provider URL into it, and refuse to save the source if it
cannot. It changes nothing else: not the directories, not the contents, not any
other file. If upstream adopts either fix above, that behaviour becomes a
no-op, which is the outcome we would prefer.

Happy to send a patch for whichever approach you favour.

View raw text
Reporting this as a courtesy rather than as a complaint: `shell.json` holds
plugin settings, those settings can contain secrets, and the file can arrive
world-readable and stay that way.

Measured on Omarchy 4.0.4-1, Quickshell shell at `/usr/share/omarchy/shell`.

**1. The packaged default is 0644.**

```
$ stat -c '%a %n' /usr/share/omarchy/config/omarchy/shell.json
644 /usr/share/omarchy/config/omarchy/shell.json
```

**2. `omarchy-refresh-config` copies it with `cp -f`**, so a file that does not
yet exist is created under the caller's umask. Reproduced against the real
source into a scratch directory:

```
cp under umask 022 -> 644
cp under umask 077 -> 600
```

A copy onto an *existing* file keeps that file's mode, which is why a machine
that once had 0600 keeps it.

**3. The shell's own writer preserves whatever mode the file already has.**
`shell.qml:138` uses `FileView { atomicWrites: true }`. A purpose-built probe,
one `FileView` writing one scratch file, run twice:

| mode before the write | after |
|---|---|
| 0644 | 0644 |
| 0600 | 0600 |

The content changed both times, so the write happened. The atomic rename
neither resets the mode to the writer's umask nor tightens it.

**Why it matters.** `~/.config` and `~/.config/omarchy` are 0755 by default, so
only the home directory's mode stands between the file and other local users,
and 0755 homes are common. Plugin settings in that file routinely include URLs,
and for IPTV-style plugins a playlist URL carries the provider username and
password, either as userinfo or as query parameters. On a machine where
`shell.json` landed at 0644, those are readable by any other local account.

**What would fix it upstream**, either one:

- ship `config/omarchy/shell.json` as 0600, and have `omarchy-refresh-config`
  create the user copy with that mode rather than inheriting the umask; or
- have the shell's writer enforce 0600 on the user config when it saves, since
  it already owns that file's lifecycle.

The first is a one-line packaging change and covers fresh installs; the second
also repairs machines that already have 0644.

**Heads-up, so it is not a surprise.** The IPTV plugin
(`io.github.rmcdavid.iptv`) will tighten `~/.config/omarchy/shell.json` to 0600
before it writes a provider URL into it, and refuse to save the source if it
cannot. It changes nothing else: not the directories, not the contents, not any
other file. If upstream adopts either fix above, that behaviour becomes a
no-op, which is the outcome we would prefer.

Happy to send a patch for whichever approach you favour.

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 23:51 UTC