## Impact An attacker who can choose a container or exec id may be able to...
HighPublished Aug 30, 2026
## Impact An attacker who can choose a container or exec id may be able to delete directories and files anywhere in the guest VM, with no privileges beyond requesting a container. The id reaches `vminitd` through `LinuxContainer.init`, `LinuxPod.addContainer`, or `LinuxContainer.exec`, whether it came from a container name a user supplied, a CI job that names its own workloads, or a direct RPC. The deletion runs as `vminitd`, which is PID 1 in the guest, so it reaches paths the container itself could never touch. One id drives both halves of the attack: `vminitd` creates a directory at the escaped path when the process is created, and recursively removes that same escaped path when the process is deleted or the container stops. Nothing on the host side stops this. `LinuxContainer` and `LinuxPod` check only that an id is at most 64 characters long, so an application built on `Containerization`, such as apple/container, passes a crafted id through unchanged. The only information an attacker needs up front is the path they want removed. This is most severe where the guest runs operator-owned components beside the container: deleting the sockets and metadata of a co-located security...
Affected versions
| Package | Affected | Fixed in |
|---|---|---|
| apple/containerization Product | < 0.41.0 | 0.41.0 |
Details and references
## Impact An attacker who can choose a container or exec id may be able to delete directories and files anywhere in the guest VM, with no privileges beyond requesting a container. The id reaches `vminitd` through `LinuxContainer.init`, `LinuxPod.addContainer`, or `LinuxContainer.exec`, whether it came from a container name a user supplied, a CI job that names its own workloads, or a direct RPC. The deletion runs as `vminitd`, which is PID 1 in the guest, so it reaches paths the container itself could never touch. One id drives both halves of the attack: `vminitd` creates a directory at the escaped path when the process is created, and recursively removes that same escaped path when the process is deleted or the container stops. Nothing on the host side stops this. `LinuxContainer` and `LinuxPod` check only that an id is at most 64 characters long, so an application built on `Containerization`, such as apple/container, passes a crafted id through unchanged. The only information an attacker needs up front is the path they want removed. This is most severe where the guest runs operator-owned components beside the container: deleting the sockets and metadata of a co-located security agent cripples sandbox telemetry, logging, and enforcement, and the tenant supplying the id is not the party harmed. The `vminit` image this project ships contains no such components, so this applies only to deployments that add them. In a pod, where several containers share one VM, the deletion can also reach a sibling container's state. ## Details In the `vminitd` guest agent, container and exec ids become guest filesystem path components with no validation of any kind. The bundle sits at `/run/container/<id>`, and an exec spec at `<bundle>/execs/<id>`. `URL.appending(path:)` keeps a `..` segment in the string rather than resolving it, and nothing downstream compares the result against its intended parent, so the escaped path is used unchanged. `FileManager.createDirectory` builds the directory tree at the location the kernel resolves, and `FileManager.removeItem` later removes it recursively. The deletion is only reachable for an id that `vminitd` already accepted. `deleteExec` looks the id up in the container's live exec table, so the id must have been accepted when the exec was created, and that one acceptance both creates the directory outside the bundle and later authorizes its recursive removal. The container id behaves the same way at the bundle level: the bundle path is fixed when the container is created, and `Bundle.delete()` removes whatever that path resolves to at teardown. ## Affected code - `ManagedContainer.init` and `ManagedContainer.craftBundlePath(id:)` (`vminitd`) — the container id, which fixes the bundle path for the container's lifetime. Fixed by rejecting the id before the bundle is created. - `Bundle.createExecSpec(id:)` and `Bundle.deleteExecSpec(id:)` (`vminitd`) — the exec id. Fixed by rejecting the id before the exec spec is written. - `ContainerizationOCI.Bundle.create` and `Bundle.delete()` — these act on the path that container creation already fixed, and are unchanged. The fix rejects the id at the two points where it first becomes a path, so every later use, including both recursive deletes, is downstream of the check and needs none of its own. Both paths date to the project's initial commit, `3407cc3`, and both the `vmexec` and `runc` process paths are affected because they share one bundle. Not affected: an id that is a single path component, which covers every ordinary id, and `ContainerizationOCI`, `ContainerizationEXT4`, or `ContainerizationArchive` consumed on their own, since the id interpolation lives in `vminitd`. The delete executes inside the guest VM against guest paths. ## Mitigations 1. Upgrade to the version of `apple/containerization` containing the fix. 2. Validate ids in your own code before passing them to `LinuxContainer.init`, `LinuxPod.addContainer`, or `Li
- Severity from
- GitHub (reviewed advisory)
More Apple advisories
All Apple| Date | Advisory | Severity | Fixed in |
|---|---|---|---|
| Aug 30 | Unpacking a crafted image layer with an invalid length extended-attribute name crashes the unpacking process | Medium | 0.41.0+1 more |
| Aug 30 | Unpacking a crafted image layer with a long(invalid) file name crashes the unpacking process | Medium | 0.41.0+1 more |
| Aug 30 | Loading an OCI image layout can read host files through a symlink | Medium | 0.41.0+1 more |
| Aug 30 | `RegistryClient` follows the `WWW-Authenticate` realm without validating its host or scheme | Medium | 0.41.0 |
| Aug 30 | Apple: path traversal | High | 0.41.0+1 more |
| Aug 25 | Apple iOS and iPadOS: buffer overflow | Medium5.5 | 26.6+2 more |