Skip to content

Merge upstream quattro (PHP via mise, omarchy up, leftover factory/hook guards) - #32

Closed
cursor[bot] wants to merge 11 commits into
quattrofrom
cursor/upstream-changes-pr-24af
Closed

cursor[bot] wants to merge 11 commits into
quattrofrom
cursor/upstream-changes-pr-24af

Conversation

@cursor

@cursor cursor Bot commented Sep 18, 2026

Copy link
Copy Markdown

Merges 4 new first-parent commits (7 cherry-picked non-merge commits) from omacom/omarchy quattro since last night's check (9c5482c5 / PR #25), plus the leftover #25 factory-reset / hook-state commits that never landed on quattro. Upstream HEAD is now 8675600e (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)

  • PHP is no longer a system pacman package. Install uses mise tool-alias set php github:nunomaduro/static-php-builds and mise use --global php@latest (prebuilt, ~5s, per-project versions like Ruby/Node/Python)
  • Composer global bin-dir is $HOME/.local/bin; Laravel installer runs as mise x php -- composer global require laravel/installer
  • Remove still drops the old pacman PHP packages for machines that installed before the switch, uninstalls the mise PHP tool/alias, and deletes both ~/.local/bin/laravel and the old Composer laravel path (even if PHP is already gone)
  • Menu install/remove guards follow the new locations: PHP is "installed" when the mise php dir exists; Laravel when ~/.local/bin/laravel is executable; remove PHP still shows if either mise or pacman PHP is present

omarchy up is an alias for omarchy update

  • New # omarchy:alias=omarchy up on omarchy-update
  • omarchy up --help resolves to the same help as omarchy update and lists the alias

1Password survives closing the installer terminal (upstream omacom#12402)

  • omarchy-install-service-1password now launches with setsid uwsm-app -- 1password, matching Signal/Spotify so closing the installer terminal does not kill the 1Password window

Offline Node pin no longer freezes mise up (upstream omacom#11656)

  • ISO/provision-owner installs unpack the bundled Node tarball and pin the exact version (required while offline)
  • Right after that pin, mise config set tools.node latest rewrites it so the first networked mise up tracks new releases, same as an online install
  • mise still resolves latest to the already-installed version while offline

Leftover from PR #25 (never merged; reapplied here)

Factory reset now actually erases old hashes (upstream omacom#10379, fixes omacom#10378)

  • passwd --lock left the previous root hash in @factory/etc/shadow and the dash-suffixed backups, so the next owner could recover it
  • Shared scrub_factory_accounts now runs on both the staged reset root and the retained @factory baseline: userdel uid≥1000 accounts, set root's password field to !, then delete the shadow-utils backups including subuid- / subgid-
  • Cleanup failures abort before boot rebuild or activation; a failed baseline scrub puts @factory back to read-only

Hook and state names cannot be paths (upstream omacom#8170)

  • omarchy-hook, omarchy-hook-install, and omarchy-state set refuse an empty name, a name with /, or a name that is exactly . or .. (exit 2)
  • Stops omarchy-hook ../../evil from running ~/.config/evil and omarchy-state set ../../escape from creating ~/.local/escape
  • Names with dots in the middle (a..b) stay allowed. omarchy-state clear is unchanged

Tests

Focused suites passed: ./test/cli (new omarchy up alias 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 calls mise use -g node@latest; PATH-injection migration unchanged), menu-test.sh, menu-guards-test.sh, and launch-1password-test.sh.

omarchy up --help smoke-checked: routes to omarchy-update, lists omarchy up as an alias.

Open in Web View Automation 

Adolanium and others added 11 commits September 18, 2026 23:05
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)
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 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 d174d4a)
@coderabbitai

coderabbitai Bot commented Sep 18, 2026 •

Copy link
Copy Markdown

Important

Review skipped

Bot user detected.

To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Advanced

Run ID: b2408cd3-ee1c-412f-b152-a28b77db65a0

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@cursor
cursor Bot marked this pull request as ready for review September 18, 2026 23:08

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Open in Web View Automation 

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

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 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.

Fix in Cursor Fix in Web

Reviewed by Cursor Security Reviewer for commit f049e1f. Configure here.

@mark-groves

Copy link
Copy Markdown
Owner

Closing as superseded. The leftover from this sync already landed on quattro via #37.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Factory reset retains the previous owner's password hash

6 participants