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)
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')
- 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.
- Before running
moo newin a repository you did not write, read itsmoo.tomland check that[project] basepoints at an image and registry you trust. Pin the base image by digest where you can. - Run
moo newfor 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. - Keep backups of important files on any machine where agents or scripts run
moo newon their own. - If building moo from source, apply the small patch from our report: in
apply_layerincrates/moo-core/src/image.rs, skip any layer entry whose path has a..(ParentDir) or absolute (RootDirorPrefix) 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:
- Entry path keeps
..components (only leading./stripped): crates/moo-core/src/image.rs#L239-L243 - Opaque-directory whiteout empties the joined directory: crates/moo-core/src/image.rs#L249-L262
- Single-path whiteout deletes the joined target: crates/moo-core/src/image.rs#L263-L273
- Safe extraction path used only for normal entries: crates/moo-core/src/image.rs#L283
- Reached from the image build on a cache miss: crates/moo-core/src/image.rs#L23, image.rs#L143 and image.rs#L202-L205
Disclosure timeline
- Vulnerability reported privately via GitHub Security Advisory (GHSA-5gx7-h8vj-4x8f).
- First follow-up comment posted on the advisory (33 days in triage).
- Second follow-up comment posted on the advisory (63 days in triage).
- Coordinated-disclosure notice posted on the advisory after the 90-day window passed, setting a deadline of 2026-11-03.
- Coordinated-disclosure deadline expired with no response from the maintainer; sink verified still present at HEAD 487b7d6 and in release v0.4.0.
- Public advisory published; CVE requested via MITRE CNA-LR.
References
- Affected repository: heyito/moo
- GitHub Security Advisory: GHSA-5gx7-h8vj-4x8f (private; in triage)