Merge upstream quattro (PHP via mise, omarchy up, leftover factory/hook guards) - #32
cursor[bot] wants to merge 11 commits into
Conversation
omarchy-hook and omarchy-state set join a name straight into a path. A name with a slash, or a bare . or .., points outside the hooks or state directory. Every caller in the repo passes a fixed label, so this is a footgun guard for future callers, not a fix for anything that ships today. Names with dots in the middle (a..b) stay allowed. omarchy-state clear is untouched: find -name matches basenames only. (cherry picked from commit 0a65b45)
(cherry picked from commit a75924a)
userdel rewrites /etc/subuid and /etc/subgid, and like every shadow-utils database write it leaves the previous contents behind in a dash-suffixed backup. The scrub removed four of the six backups those tools produce, so the retained @factory baseline still named the previous owner in /etc/subuid- and /etc/subgid- along with their subordinate ID range. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> (cherry picked from commit a00be8f)
The runner already rejects a slash, a bare . or .. The installer still joined the type into hooks/<type>.d before mkdir/cp, so a name nothing can run could still land on disk. (cherry picked from commit e522a18)
Offline installs unpack the bundled tarball and pin Node to its exact version, since latest can't be resolved without network. But nothing ever loosened that pin, so Node stayed frozen at the ISO's version and mup skipped it forever, while online installs tracked latest. Rewrite the pin to latest right after registering the bundled version: mise resolves latest to the installed version while offline (verified with no network and an empty cache), and the first mise up with network picks up new releases just like an online install. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017LseZ1jcLaFBnndRnW4yb5 (cherry picked from commit 5db4a40)
(cherry picked from commit 181ad4b)
(cherry picked from commit 456af5c)
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> (cherry picked from commit 486e1ca)
(cherry picked from commit 85da80d)
(cherry picked from commit 5f34ce4)
(cherry picked from commit d174d4a)
|
Important Review skippedBot user detected. To trigger a single review, invoke the ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Advanced Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Agentic security review found one HIGH issue in factory-reset account scrubbing: untrusted passwd login names are interpolated into a privileged rm -rf without path confinement. Other changed paths (hook/state name guards, PHP via mise, omarchy up) did not yield reportable findings.
Sent by Cursor Security Agent: Security Reviewer
| users=$(awk -F: '$3 >= 1000 && $3 < 60000 { print $1 }' "$root/etc/passwd") || return 1 | ||
| for user in $users; do | ||
| userdel --root "$root" "$user" 2>>"$LOG_FILE" || return 1 | ||
| rm -rf "${root:?}/home/$user" || return 1 |
There was a problem hiding this comment.
🔒 Agentic Security Review
Severity: HIGH
scrub_factory_accounts interpolates uid≥1000 login names from the untrusted factory snapshot /etc/passwd into a host rm -rf "${root}/home/$user" after userdel --root. Factory reset runs as root because the previous owner (and @factory) are untrusted. A planted login such as .. or ../../../../../etc is accepted by userdel --root when present in that passwd file, and the following rm is not confined to the snapshot, so it can wipe the snapshot root or delete live host paths during reset.
Impact: A previous owner can sabotage factory reset or delete arbitrary host paths as root when the new owner runs reset.
Reviewed by Cursor Security Reviewer for commit f049e1f. Configure here.
|
Closing as superseded. The leftover from this sync already landed on quattro via #37. |




Merges 4 new first-parent commits (7 cherry-picked non-merge commits) from omacom/omarchy
quattrosince last night's check (9c5482c5/ PR #25), plus the leftover #25 factory-reset / hook-state commits that never landed on quattro. Upstream HEAD is now8675600e(upstream #12141, merged 2026-09-18).PR #25 is still open but now CONFLICTING after today's face-scan PRs (#26–#31). This branch rebases that leftover onto current quattro and adds everything new since the 2026-09-17 cron. Fork-only Cursor work is untouched: official-tarball installer, no mise wrapper, usage collector, Cursor/Grok update steps, and the theme-set fix from #22.
PHP and Laravel now install through mise (upstream omacom#12141)
pacmanpackage. Install usesmise tool-alias set php github:nunomaduro/static-php-buildsandmise use --global php@latest(prebuilt, ~5s, per-project versions like Ruby/Node/Python)$HOME/.local/bin; Laravel installer runs asmise x php -- composer global require laravel/installer~/.local/bin/laraveland the old Composer laravel path (even if PHP is already gone)~/.local/bin/laravelis executable; remove PHP still shows if either mise or pacman PHP is presentomarchy upis an alias foromarchy update# omarchy:alias=omarchy uponomarchy-updateomarchy up --helpresolves to the same help asomarchy updateand lists the alias1Password survives closing the installer terminal (upstream omacom#12402)
omarchy-install-service-1passwordnow launches withsetsid uwsm-app -- 1password, matching Signal/Spotify so closing the installer terminal does not kill the 1Password windowOffline Node pin no longer freezes
mise up(upstream omacom#11656)mise config set tools.node latestrewrites it so the first networkedmise uptracks new releases, same as an online installmisestill resolveslatestto the already-installed version while offlineLeftover from PR #25 (never merged; reapplied here)
Factory reset now actually erases old hashes (upstream omacom#10379, fixes omacom#10378)
passwd --lockleft the previous root hash in@factory/etc/shadowand the dash-suffixed backups, so the next owner could recover itscrub_factory_accountsnow runs on both the staged reset root and the retained@factorybaseline:userdeluid≥1000 accounts, set root's password field to!, then delete the shadow-utils backups includingsubuid-/subgid-@factoryback to read-onlyHook and state names cannot be paths (upstream omacom#8170)
omarchy-hook,omarchy-hook-install, andomarchy-state setrefuse an empty name, a name with/, or a name that is exactly.or..(exit 2)omarchy-hook ../../evilfrom running~/.config/evilandomarchy-state set ../../escapefrom creating~/.local/escapea..b) stay allowed.omarchy-state clearis unchangedTests
Focused suites passed:
./test/cli(newomarchy upalias in metadata/routes),hook-state-name-guard-test.sh(19 cases),factory-reset-accounts-test.sh(both roots, repeat reset, six injected cleanup failures; ran via user namespace),mise-work-path-test.sh(runtime path still only callsmise use -g node@latest; PATH-injection migration unchanged),menu-test.sh,menu-guards-test.sh, andlaunch-1password-test.sh.omarchy up --helpsmoke-checked: routes toomarchy-update, listsomarchy upas an alias.