Skip to content

Keep update/runtime/diagnostics out of world-writable /tmp - #12109

Closed
Chessing234 wants to merge 15 commits into
omacom:quattrofrom
Chessing234:fold/tmp-out-of-shared
Closed

Chessing234 wants to merge 15 commits into
omacom:quattrofrom
Chessing234:fold/tmp-out-of-shared

Conversation

@Chessing234

@Chessing234 Chessing234 commented Sep 16, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Fixes #11595
Fixes #11596
Fixes #11597

Test plan

  • bash test/shell.d/capture-region-marker-path-test.sh
  • bash test/shell.d/brightness-display-ddc-cache-path-test.sh
  • bash test/shell.d/update-stay-awake-path-test.sh
  • bash test/shell.d/update-log-path-test.sh

@moss4u

moss4u commented Sep 16, 2026

Copy link
Copy Markdown

Take a look at #11401 which relocates $TMPDIR into ~/.local/tmp while maintaining tmp cleanup semantics.

@Chessing234 Chessing234 changed the title Keep update/runtime state out of world-writable /tmp Keep update/runtime/diagnostics state out of world-writable /tmp Sep 17, 2026
@Chessing234 Chessing234 changed the title Keep update/runtime/diagnostics state out of world-writable /tmp Keep update/runtime/diagnostics out of /tmp; skip orphan prompt with -y Sep 21, 2026
@Chessing234
Chessing234 force-pushed the fold/tmp-out-of-shared branch from 5e166a4 to 1ed103b Compare September 25, 2026 10:42
@Chessing234 Chessing234 changed the title Keep update/runtime/diagnostics out of /tmp; skip orphan prompt with -y Keep update/runtime/diagnostics out of world-writable /tmp Sep 25, 2026
A pre-created /tmp/omarchy-update.log symlink let another local user
redirect script(1) into the victim's files. Stage the log under
XDG_RUNTIME_DIR (or a 0700 cache under \$HOME).
XDG_RUNTIME_DIR falling back to /tmp let another local user race the
lock path. Use ~/.local/state/omarchy instead and chmod the directory.
Falling back to /tmp/omarchy-reminders left reminder bodies world-readable
on multi-user hosts. Prefer XDG_RUNTIME_DIR, else ~/.local/state, and
chmod the directory 0700.
Clipboard mode wrote wl-paste into a world-readable mktemp under /tmp
and left it forever. Stage under XDG_RUNTIME_DIR (else ~/.local/state),
chmod 0600, wait for LocalSend, then remove the temp file.
@Chessing234

Copy link
Copy Markdown
Contributor Author

rebased onto tip; dropped the stay-awake and sudo-probe commits tip already covers

@Chessing234
Chessing234 force-pushed the fold/tmp-out-of-shared branch from 26d0fbf to 17515d8 Compare September 25, 2026 16:08
@omarchybot

Copy link
Copy Markdown
Collaborator

Reviewed at 17515d8 against quattro. I read the change and the scripts around it and compared it with the open pull requests that touch the same files. Codex Medium reviewed it separately and found the defects below on its own, and I checked each one against the source. Nothing ran on a worker, because the overlap below has to be settled before a test run would decide anything.

Overlap with other pull requests. Most of this diff already has a competing fix. #7995 covers omarchy-debug, omarchy-upload-log, the update transcript, the docs and the /tmp cleanup migration, and it is already verified. #8429 and #12957 also move the update transcript. On those parts, Codex preferred #7995 for omarchy-debug (mktemp plus a cleanup trap, rather than a fixed per-user log) and #8429 for the transcript (it creates the log mode 0600 and doesn't chmod shared state). It preferred this pull request's mktemp -d staging in omarchy-upload-log over #7995's. Choosing between them is the maintainer's call.

Scope. The three issues it closes are about two fallbacks: the DDC cache (#11596) and the capture-region markers (#11597). #11595 was already fixed on quattro by 6af052f, which validates the /tmp/omarchy-$UID fallback in omarchy-update-stay-awake. The smallest fix for those issues is those two scripts and their tests. The rest of the diff deserves separate pull requests: menu IPC, theme-set, monitor-watch, system-lock, dev-link, reminders, the update lock and menu-share. The change to omarchy-update-orphan-pkgs (honouring -y) is unrelated to /tmp and looks fine on its own.

Defects in the new fallbacks. Each of these only matters when XDG_RUNTIME_DIR is unset, which in a normal session it is not:

  • bin/omarchy-dev-link:96-98 and the other new /tmp/omarchy-$UID fallbacks use mkdir -m 700 -p without checking who owns the directory. -m only applies when the directory is created, so another local account that creates /tmp/omarchy-$UID first owns every entry inside it. In dev-link, that account can replace the staged sudoers file after visudo -cf accepts it and before sudo install puts it in /etc/sudoers.d (line 118). The old mktemp in sticky /tmp did not allow that swap. The same pre-creation lets that account hold the locks in omarchy-system-lock:20-25 (1Password is then never locked), omarchy-theme-set:18-20 and omarchy-hyprland-monitor-watch:6-9, and rewrite selections in omarchy-menu-input, omarchy-menu-select and omarchy-menu-images. This is the hazard [Security] omarchy-update-stay-awake stages inhibit state under predictable /tmp/omarchy-$UID #11595 describes, and the fallback in omarchy-update-stay-awake on quattro already checks for it.
  • bin/omarchy-update-lock:35-36 chmods the whole ~/.local/state/omarchy directory to 0700 in its fallback. bin/omarchy-migrate-notify:8 still looks only in $XDG_RUNTIME_DIR for the lock, and docs/update-process.md:24 still documents the /tmp fallback.
  • bin/omarchy-menu-share:57: --wait waits for the localsend process it launches, not for the transfer. If LocalSend is already running, that process hands the path to the running instance and exits. The exit trap can then delete the clipboard file before it is sent. This conclusion comes from reading LocalSend's source; it was not reproduced. The old mktemp file was already mode 0600, so it was not readable by other users.
  • Several tests check source strings instead of behaviour: theme-set-lock-test.sh, capture-region-marker-path-test.sh, and update-log-path-test.sh, which defines its own copy of the path helper. They would pass with the pre-creation problem above still present.

Next step. This waits on the maintainer to choose between this and #7995, #8429 and #12957. A version limited to the DDC cache and capture markers, with a fallback that checks ownership the way stay-awake does, would be straightforward to review on its own.

@dhh

dhh commented Oct 4, 2026

Copy link
Copy Markdown
Contributor

Closing after maintainer review. We are not accepting this as a security vulnerability that warrants these changes for Omarchy's intended single-user desktop setup.

The cross-account disclosure scenario requires an additional untrusted local account, or a separately compromised service account, plus a run of the relevant command. The report has not demonstrated a sensitive credential disclosure or a consequential exploit in the default setup. Root can already read this information, and malicious programs running as the desktop user can still read it after a move to a private file or directory. Hostname, hardware details, and package inventory alone do not establish a security vulnerability.

The default systemd protections (fs.protected_symlinks and fs.protected_regular) block the described cross-user symlink redirect and writes into another user's pre-created regular file in sticky /tmp. World-writable /tmp by itself is not evidence of arbitrary file overwrite or privilege escalation. These protections do not prevent reading an existing 0644 file; that narrow cross-account exposure is acknowledged.

The default /tmp is tmpfs-backed and is cleared on reboot. These logs are not permanently retained: the exposure, where an untrusted second account exists, lasts only while the files remain during that boot. Reboot limits the exposure; it does not make cross-account reads impossible before then.

Private staging and explicit cleanup can be reasonable housekeeping, but we do not consider the demonstrated behavior a security priority for the default Omarchy threat model. We are declining this family of security-motivated changes on that basis.

References: systemd default protections, kernel documentation, default tmpfs mount.

This PR also bundles capture markers, DDC caches, inhibitor state, and locks. Those are distinct consumers with distinct failure modes; they do not gain a demonstrated security impact from the diagnostics argument. Closing this combined proposal. This decision does not close #11595, #11596, or #11597 or claim that every runtime-state concern is equivalent to readable diagnostic logs.

Omabot on behalf of DHH

@dhh dhh closed this Oct 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

4 participants