Security

moo: host file deletion via OCI whiteout path traversal

moo - path traversal in OCI layer whiteout handling deletes files and empties directories on the host during base-image build (moo new) (GHSA-5gx7-h8vj-4x8f)

PUBLISHED SEVERITY HIGHSTATUS UnpatchedGHSA-5gx7-h8vj-4x8f
Unpatched

Unpatched. Reported privately via GitHub Security Advisory on 2026-07-16; the 90-day coordinated-disclosure window passed, and the final 2026-11-03 deadline set in our 2026-10-20 notice expired with no response from the maintainer.

Product
moo (moo-core image builder) in heyito/moo
Affected versions
moo through v0.4.0 and main (checked at HEAD 487b7d6).
Severity
HIGH
Status
Unpatched
Weaknesses
  • CWE-22Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')
CWE-22 as filed on GHSA-5gx7-h8vj-4x8f.
GitHub advisory
GHSA-5gx7-h8vj-4x8f
Private; in triage, not yet published by the maintainer
CVE
Pending (requested via MITRE CNA-LR)
Published
Credit
Finder: Aaron Elijah Mars of Aeon. Tool: Aeon (https://www.aeon.fun).

What users should do now

No upstream patch is available yet. Until an official fix is released, treat the base image as code that runs on your machine.

  1. Before running moo new in a repository you did not write, read its moo.toml and check that [project] base points at an image and registry you trust. Pin the base image by digest where you can.
  2. Run moo new for untrusted repositories as a separate low-privilege user, or inside a throwaway VM or container, so a malicious image cannot reach your home directory, SSH keys or source trees.
  3. Keep backups of important files on any machine where agents or scripts run moo new on their own.
  4. If building moo from source, apply the small patch from our report: in apply_layer in crates/moo-core/src/image.rs, skip any layer entry whose path has a .. (ParentDir) or absolute (RootDir or Prefix) component before the whiteout handling, and confirm the computed whiteout target is still inside the root filesystem directory before removing anything.

Impact and reach

moo's main promise is that each machine is hardware-isolated. This bug acts on the host instead, at image-build time, with the permissions of the user who ran moo new. A single-path whiteout entry deletes an arbitrary file or directory tree; an opaque-directory whiteout entry deletes every child of an arbitrary directory. Integrity and availability of the developer's files are at risk, including source code, SSH keys and configuration.

The trigger is the first moo new for a recipe whose base image is not cached yet. The base image reference comes from the repository's moo.toml and can name any registry, so a repository that points at an attacker-published image is enough, with no further prompt. A compromised registry or a poisoned public base image reaches the same code. A working exploit is withheld.

How whiteout paths escape the root filesystem

Normal entries are extracted with the tar crate's unpack_in, which rejects paths that leave the destination. Whiteout entries never reach unpack_in: apply_layer joins the raw relative path onto rootfs and calls read_dir, remove_dir_all or remove_file on it directly, so .. components are resolved by the operating system against real host directories:

Disclosure timeline

  1. Vulnerability reported privately via GitHub Security Advisory (GHSA-5gx7-h8vj-4x8f).
  2. First follow-up comment posted on the advisory (33 days in triage).
  3. Second follow-up comment posted on the advisory (63 days in triage).
  4. Coordinated-disclosure notice posted on the advisory after the 90-day window passed, setting a deadline of 2026-11-03.
  5. Coordinated-disclosure deadline expired with no response from the maintainer; sink verified still present at HEAD 487b7d6 and in release v0.4.0.
  6. Public advisory published; CVE requested via MITRE CNA-LR.

References

  • Affected repository: heyito/moo
  • GitHub Security Advisory: GHSA-5gx7-h8vj-4x8f (private; in triage)