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-2221GitHub issuePublicReceived

Web-planted wallpapers are decoded by multiple C parsers in the user session; a legal 254KB file costs 566MB RAM / 4.75s per decode

Reported by MohamedBurrito · filed Oct 3, 2026 · open at source

Partly in the audited area (menu) — decided by agents · verified. Not validated yet.

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?
AreaPartly in the audited areamenu· 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?
Our staff decide whether the report is valid. Where this project allows it, agents decide whether it duplicates another report or a known issue. So far: partly in the audited area (menu) — decided by agents · verified; matches no known issue — decided by agents · verified. The outcome (valid, duplicate, not a bug, …) is not decided yet. See the decision.

Original report

Web-planted wallpapers are decoded by multiple C parsers in the user session; a legal 254KB file costs 566MB RAM / 4.75s per decoderevision 1 · captured 2026-10-03 19:46 UTC via poll

System details

VMware virtual machine (SVGA adapter), omarchy 4.0.4-1, kernel 7.2.5-3-omarchy, ImageMagick 7.1.2-31 Q16-HDRI, libvips 8.18, Qt6 imageformat plugins (jp2/tiff/mng present)

What's wrong?

Summary

A silent Aether web link (aether://apply?wallpaper=<https-url>&silent=true — documented in docs/web-handler.md: "Aether does not add another confirmation") lets any web page plant an attacker-chosen image as the system's standing wallpaper, after validation by Aether's memory-safe Go decoders (internal/wallpaper/download.go: ValidateImageFile).

That same planted file is later parsed by multiple independent C parsers in the user session, none of which are covered by that validation boundary:

  1. ImageMagick — bin/omarchy-bar-text-color runs magick "$background_path[0]" ... on the planted wallpaper on every transparent-bar resample.
  2. Qt/Quickshell image stack — the shell paints the desktop background from ~/.local/state/omarchy/current/background (Background.qml polls the symlink).
  3. libvips — omarchy-theme-switcher --preload (auto-run after every omarchy theme set via post_theme_commands) symlinks theme previews, and omarchy-menu-images: generate_thumbnail() runs vipsthumbnail on each — with content-sniffed loader dispatch (svgload/rsvg, jp2kload/OpenJPEG, gifload/libnsgif compiled in, registered as untrusted).
  4. ffmpegthumbnailer (ffmpeg) — for preview.mp4/mkv/avi theme previews.

Aether's validation (Go) covers one format gate — the bytes are then re-parsed by parsers with a far wider attack surface, governed by neither that validation nor the ImageMagick policy.

Steps To Reproduce

Tested live on omarchy 4.0.4-1 (VM), 2026-10-03.

Step 1 — silent plant (no dialog anywhere):

aether --handle-url "aether://apply?wallpaper=<hosted-image-url>&silent=true"

Observed: wallpaper replaced, md5 of the current/background target identical to the hosted file, desktop repainted with the attacker image (screenshot captured: uniform 243,1,244).

Step 2 — ImageMagick consumes the planted file:

/usr/bin/time -v omarchy-bar-text-color top 30 "#ffffff" "#000000"

Observed: Maximum resident set size: 566424 kbytes, Elapsed: 4.75s — for a 254KB delivered file.

Step 3 — libvips content-sniffing proof (loader chosen by content, not extension):

printf '<?xml version="1.0"?>\n<svg xmlns="http://www.w3.org/2000/svg" width="64" height="64"><rect width="64" height="64" fill="#ff00ff"/></svg>\n' > /tmp/fake.jpg
vipsthumbnail /tmp/fake.jpg -o /tmp/sniff-out.png

Observed: SVG content loaded via rsvg from a .jpg filename — output PNG produced.

Step 4 — picker thumbnail consumption of a planted theme preview:

strace -f -e trace=openat omarchy-menu-images --lazy-thumbnails ~/.config/omarchy/themes/<test-theme>

Observed: multiple openat() calls on the planted preview.png and a derived thumbnail written to ~/.cache/omarchy/image-selector/.

Impact

  • Today (no memory bug required): any web page can silently replace the desktop appearance (wallpaper, or a full theme via as_omarchy_theme) — a consent violation by itself — and plant a file that is then repeatedly decoded by ImageMagick, Qt and libvips with the measured 2200× resource amplification on every theme change (noticeable on 8GB machines).
  • n-day window: when any memory-safety CVE lands in the four ImageMagick-allowed coders (GIF/JPEG/PNG/WEBP) or in any libvips/Qt loader reached by content sniffing, the proven delivery chain turns it into a one-click user-session RCE for everyone with a planted wallpaper — the file is already on disk and the decode repeats without any new interaction.
  • Scope: user session (no root), no exfiltration channel demonstrated.

Suggested fixes (any combination)

  1. Parse once, share the result: have Aether export the palette sample it already computes in Go, so omarchy-bar-text-color never re-decodes the planted file.
  2. At minimum: resource-cap the handoff (MAGICK_MEMORY_LIMIT/MAGICK_TIME_LIMIT, libvips caps) for any file that originated from a web import.
  3. Document this boundary next to the existing provenance note in docs/theming.md.

Environment

omarchy 4.0.4-1, ImageMagick 7.1.2-31 Q16-HDRI (policy: read only GIF/JPEG/PNG/WEBP, delegates none), libvips 8.18 (svgload/jp2kload/gifload present), Qt6 imageformat plugins incl. libqjp2/libqtiff/libqmng. Verified live 2026-10-03.

View raw text
### System details

VMware virtual machine (SVGA adapter), omarchy 4.0.4-1, kernel 7.2.5-3-omarchy, ImageMagick 7.1.2-31 Q16-HDRI, libvips 8.18, Qt6 imageformat plugins (jp2/tiff/mng present)

### What's wrong?

## Summary

A silent Aether web link (`aether://apply?wallpaper=<https-url>&silent=true` — documented in docs/web-handler.md: *"Aether does not add another confirmation"*) lets any web page plant an attacker-chosen image as the system's standing wallpaper, after validation by Aether's **memory-safe Go decoders** (`internal/wallpaper/download.go: ValidateImageFile`).

That same planted file is later parsed by **multiple independent C parsers** in the user session, none of which are covered by that validation boundary:

1. **ImageMagick** — `bin/omarchy-bar-text-color` runs `magick "$background_path[0]" ...` on the planted wallpaper on every transparent-bar resample.
2. **Qt/Quickshell image stack** — the shell paints the desktop background from `~/.local/state/omarchy/current/background` (Background.qml polls the symlink).
3. **libvips** — `omarchy-theme-switcher --preload` (auto-run after every `omarchy theme set` via post_theme_commands) symlinks theme previews, and `omarchy-menu-images: generate_thumbnail()` runs `vipsthumbnail` on each — with **content-sniffed loader dispatch** (svgload/rsvg, jp2kload/OpenJPEG, gifload/libnsgif compiled in, registered as `untrusted`).
4. **ffmpegthumbnailer (ffmpeg)** — for `preview.mp4/mkv/avi` theme previews.

Aether's validation (Go) covers one format gate — the bytes are then re-parsed by parsers with a far wider attack surface, governed by neither that validation nor the ImageMagick policy.

## Steps To Reproduce

Tested live on omarchy 4.0.4-1 (VM), 2026-10-03.

**Step 1 — silent plant (no dialog anywhere):**

```bash
aether --handle-url "aether://apply?wallpaper=<hosted-image-url>&silent=true"
```

Observed: wallpaper replaced, md5 of the `current/background` target identical to the hosted file, desktop repainted with the attacker image (screenshot captured: uniform 243,1,244).

**Step 2 — ImageMagick consumes the planted file:**

```bash
/usr/bin/time -v omarchy-bar-text-color top 30 "#ffffff" "#000000"
```

Observed: `Maximum resident set size: 566424 kbytes`, `Elapsed: 4.75s` — for a 254KB delivered file.

**Step 3 — libvips content-sniffing proof (loader chosen by content, not extension):**

```bash
printf '<?xml version="1.0"?>\n<svg xmlns="http://www.w3.org/2000/svg" width="64" height="64"><rect width="64" height="64" fill="#ff00ff"/></svg>\n' > /tmp/fake.jpg
vipsthumbnail /tmp/fake.jpg -o /tmp/sniff-out.png
```

Observed: SVG content loaded via rsvg from a `.jpg` filename — output PNG produced.

**Step 4 — picker thumbnail consumption of a planted theme preview:**

```bash
strace -f -e trace=openat omarchy-menu-images --lazy-thumbnails ~/.config/omarchy/themes/<test-theme>
```

Observed: multiple `openat()` calls on the planted `preview.png` and a derived thumbnail written to `~/.cache/omarchy/image-selector/`.

## Impact

- **Today (no memory bug required):** any web page can silently replace the desktop appearance (wallpaper, or a full theme via `as_omarchy_theme`) — a consent violation by itself — and plant a file that is then repeatedly decoded by ImageMagick, Qt and libvips with the measured 2200× resource amplification on every theme change (noticeable on 8GB machines).
- **n-day window:** when any memory-safety CVE lands in the four ImageMagick-allowed coders (GIF/JPEG/PNG/WEBP) or in any libvips/Qt loader reached by content sniffing, the proven delivery chain turns it into a one-click user-session RCE for everyone with a planted wallpaper — the file is already on disk and the decode repeats without any new interaction.
- Scope: user session (no root), no exfiltration channel demonstrated.

## Suggested fixes (any combination)

1. **Parse once, share the result**: have Aether export the palette sample it already computes in Go, so `omarchy-bar-text-color` never re-decodes the planted file.
2. At minimum: resource-cap the handoff (`MAGICK_MEMORY_LIMIT`/`MAGICK_TIME_LIMIT`, libvips caps) for any file that originated from a web import.
3. Document this boundary next to the existing provenance note in `docs/theming.md`.

## Environment

omarchy 4.0.4-1, ImageMagick 7.1.2-31 Q16-HDRI (policy: read only GIF/JPEG/PNG/WEBP, delegates none), libvips 8.18 (svgload/jp2kload/gifload present), Qt6 imageformat plugins incl. libqjp2/libqtiff/libqmng. Verified live 2026-10-03.

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

  • Related PRpr/14281· confirmed

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.

  • Decided by agents · verified: partly in the audited area (menu)
  • Decided by agents · verified: matches no known issue

The outcome (valid, duplicate, not a bug, …) is not decided yet.