Skip to content
Back to blog

We Pointed StackGrit at Omarchy After Its Root Exploit. The Code Is Solid. No Automated Check Gates a Change.

Priit Kallas

Omarchy scored 80 out of 100. Security came out at B+, with zero critical and zero high-severity findings.

That is not the result I expected when I started.

On 28 August, a security researcher published a clean write-up showing that Omarchy put its default user in the docker group. Because the Docker daemon runs as root and listens on a socket that group can reach, any process in that user’s desktop session could read /etc/shadow, mount the host filesystem, and run code as root. No password, no prompt. The write-up reached the front page of Hacker News with 505 points and nearly 500 comments.

Omarchy is David Heinemeier Hansson’s opinionated Arch Linux distribution. It is fifteen months old, has 35,000 stars, and was the single most-starred repository on GitHub this month. A lot of developers install it as their daily driver.

So I pointed our AI code analysis at the whole thing: 121,949 lines across 1,412 files, the quattro development branch, 43 minutes, $15.14 in tokens. The full report is public if you want to read along.

StackGrit report header for Omarchy: B overall, 80 out of 100, 1,412 files, 121,949 lines of code, 20 findings, and grades across seven dimensions

I went looking for whatever had let a root exploit through. It is not in the security work.

What a disciplined shell codebase looks like

The docker issue is fixed. Group membership came out of the default configuration in 4.0.1, and the capability now lives in a separate opt-in command that prints an explicit root-equivalence warning and waits for you to confirm before it does anything.

That much you would expect after a public disclosure. What I did not expect was the file at test/acceptance.d/security-test.sh. Its header reads:

Verifies the security posture of an installed system: the unprivileged session-to-root paths closed for 4.0.2 (blanket input-group grant, shipped asdcontrol sudoers authorization)

Two other privilege-escalation paths, closed in a later release, each with a test that fails if it ever comes back. One checks that the user is not in the input group unless a feature needing raw device access is installed. The other checks that a passwordless sudo rule the project used to ship is gone.

That pattern shows up throughout. Variables get escaped with printf '%q' before they are interpolated into a shell string. The SSH hardening script validates its own configuration twice, syntactically and semantically, and rolls the file back if either check fails, so you cannot lock yourself out of your own machine. Installing a theme or a plugin from the internet is guarded end to end: the address is checked before download, unsafe names are refused, symbolic links are not followed, and files that could execute are stripped out.

A scan of every shell file in the repository found no committed passwords, keys, or tokens. The two matches it did surface were a public speed-test token and a deliberate test fixture. It also found zero TODO, FIXME, or HACK comments and zero commented-out code blocks anywhere in the project, which in a 121,000-line codebase is a choice somebody enforces.

StackGrit health summary for Omarchy: Architecture B+, Code Quality C+, Testing C+, Security B+, Technologies B-, Data Model B, each with a plain-language explanation

The most useful signal in any codebase is what happens to a bug after it is fixed. Here, fixed bugs become tests.

269 test files, and no automated check that runs them

The project has 269 test files. There is a bespoke TAP-style harness, isolated fake home directories, stub binaries on PATH, and test names that describe behaviour rather than echoing method names. The repair scripts get repeat-run checks that prove they are safe to run twice. It is a better test suite than most projects this size manage, and it was built without a single third-party testing dependency.

There is no continuous-integration configuration anywhere in the repository.

Our worker checks 22 known locations before the analysis writes a word: GitHub Actions, GitLab, CircleCI, Buildkite, Jenkins, Drone, Woodpecker, Azure Pipelines, and the rest. All 22 came back empty. The .github/ directory holds CODEOWNERS, a SECURITY.md, and issue templates. No workflows.

A clone only tells you what is in the repository, though, and the report was careful to say so. A pipeline can be defined in the CI service rather than in the code, which is how plenty of projects run Buildkite or Jenkins. So I went and checked GitHub itself.

The repository’s Actions tab lists four workflows, and all four are GitHub’s own defaults rather than anything the project wrote: three Copilot integrations and CodeQL code scanning. Automated analysis does run here. It is not the test suite.

The stronger evidence comes from GitHub’s own records. When any CI system runs against a commit, whether that is GitHub Actions or an external service like Buildkite, it reports back through GitHub’s checks or statuses API. I sampled the most recent commits on the default branch and the head of a recent pull request. Every one came back with zero check runs, and the latest commit carries zero statuses.

That is as far as the evidence goes, so let me be precise about what it supports. No automated check gates a change to Omarchy. It does not tell you the tests never run: a two-person core team can run ./test/all on a laptop before merging, and I would guess that happens. The claim is about enforcement, not about diligence.

StackGrit key insights for Omarchy, showing top risks and top strengths side by side, with the key metric: 269 test files exist, no automated build in this repository was found running them

Nor is the test suite the only thing running on trust. The main scripting language has no automated code checking enabled anywhere in the repository, so 121,000 lines of Bash that run as root are reviewed by people and nothing else. And the 207 system packages Omarchy installs are named without versions, which is normal for a rolling distribution but means no tool can tell you whether any of them currently carries a known vulnerability.

Why enforcement matters more for a distribution

Most projects can absorb a missed test. A web app ships a bug, someone notices, you roll back.

Omarchy is the operating system. A bad change breaks the machine you would use to fix it, and it reaches users through a rolling update rather than a version they chose to install. The project moves at roughly 6,300 changes in fifteen months from 479 contributors.

Architecture diagram of Omarchy from the report: a command router dispatching to 444 commands, which drive the installer, the one-time repair scripts and the desktop shell, with the 269-file test suite exercising the commands and the shell logic

The report puts the cost well: what you see is caution rather than firefighting. Output stays high. What suffers is confidence, because every change to a system-modifying script carries more manual verification than it should.

Four findings sharpen the point.

bin/omarchy-upgrade-to-quattro is 2,404 lines long. It runs as root, once, on every existing user machine that upgrades to version 4.0, with individual steps up to 188 lines. Line 345 says “You cannot downgrade from Quattro.” It has one test file. Its own cleanup trap names the failure mode out loud: a machine left “part Omarchy 3 and part Omarchy quattro.”

103 one-time repair scripts run unattended. They execute at login against real user state, and the project’s own authoring guide requires them to be idempotent, meaning safe to run twice. About 18 have a dedicated test proving it. The rest are verified by reading them.

281 of 444 command scripts do not stop when a step fails. There are also 339 explicit || true suppressions and 517 redirections to /dev/null, none of which separate an expected failure from something that just broke. Fifty-nine of those suppressions sit in the upgrade script, so the riskiest file in the project is also the one that silences the most.

Commands call each other by name, with nothing checking those names still exist. Rename one and a machine can break mid-install, quietly.

None of these is exotic. Every one is the kind of regression a suite catches when it runs on every change, and the suite already exists.

StackGrit technical debt view for Omarchy: debt hotspots covering the 4.0 upgrade path, the desktop bar, one-time repair scripts, command error handling, and automated checks

Which brings you to the two people

Missing enforcement is not only a correctness problem. It decides who can contribute.

When nothing automated verifies a change, the only people who can approve one confidently are the people who already hold the design in their heads. The report’s ownership matrix shows how few that is: across eight areas of the system, one person is the primary owner of five and a major contributor to the other three. A second is a major contributor almost everywhere. Every other name on the project is mostly grey.

StackGrit knowledge distribution matrix for Omarchy: eight modules against six contributors, with two people covering nearly every area and the rest showing none

What I liked is that the report does not treat that as a personal failing. Its note on DHH reads: “Nothing in the code suggests a capability gap. The practical growth area is transferable: the areas where he is sole deep owner would benefit most from written design notes or a second reviewer, which is a delegation question rather than a skill one.”

It then names the contributor best placed to become a third owner, and says which part of the codebase to pair them on.

The finding the analysis declined to make

One result convinced me the rest was worth trusting.

The analysis noticed that first-boot provisioning uses a single password for the user account, the root account, and the encrypted disk. Three security boundaries resting on one secret. That is the sort of line that writes its own headline.

It did not write the headline. Instead it checked the claim against Omarchy’s own SECURITY.md, which defines a vulnerability as a bug that lets an untrusted or lower-privileged party cross a meaningful security boundary. Sharing one password does not do that, since nobody gains anything without already having the secret. Several consumer distributions make the same trade for first-boot simplicity.

So it filed the observation as a design decision worth making deliberately, and said in as many words that this is not a confirmed vulnerability.

A report that will not overstate a finding it wants to make is a report you can quote.

Two questions worth stealing

The thing that put Omarchy on the front page was a defaults decision, not a coding error. No scanner finds those. There was no SQL to inject, no dependency manifest to audit, no OWASP surface to walk. The vulnerability lived in one line of an install script that added a user to a group, and in a documentation sentence that described the consequence backwards.

What a whole-codebase read surfaces is the structural version of the same problem. The discipline here is real and visible in the code. It also lives almost entirely in two people’s heads, with no automated check standing between a submitted change and 35,000 machines.

So here are two questions that tell you more about a codebase than a vulnerability count. Both are answerable from the outside in about ten minutes, on a dependency you rely on or on your own repository.

  1. When this project fixed a bug, did the fix become a test?
  2. Does anything automated run those tests before a change is accepted?

The first tells you whether a team learns from its mistakes. Omarchy answers it better than most codebases I have looked at, and the security score reflects that.

The second tells you whether the learning survives the next commit. Omarchy has not answered it yet, and 35,000 machines take the update either way.


Read the full Omarchy report if you want to see all twenty findings, the architecture diagrams, and the per-area detail behind the grades above.

We built StackGrit to answer questions like these about codebases you are responsible for but have not read. It reads the whole repository and its git history, then writes a report in plain language: architecture, security, test coverage, dependency risk, and who on the team knows how the thing works.

Get a free report for your own project.