Skip to content
AppleGHSA-x7pf-2jmj-pgcq

## 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...

GitHub advisory

Affected versions

PackageAffectedFixed in
apple/containerization
Product
< 0.41.00.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

Critical advisories by email

Wednesdays: the week’s critical and high advisories in the AI and data stack, with the fixed versions. Only in weeks that have some.

Double opt-in. Unsubscribe any time.

GHSA-x7pf-2jmj-pgcq: Apple high vulnerability | Advisories
Skip to content
AppleGHSA-x7pf-2jmj-pgcq

## 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...

GitHub advisory

Affected versions

PackageAffectedFixed in
apple/containerization
Product
< 0.41.00.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

Critical advisories by email

Wednesdays: the week’s critical and high advisories in the AI and data stack, with the fixed versions. Only in weeks that have some.

Double opt-in. Unsubscribe any time.

. The host library enforces only `maxIDLength`, so on an unpatched version this is the only gate that exists.\r\n3. Generate ids instead of accepting them — a UUID for the id, with any user-supplied name carried as a separate label, keeps attacker input out of the path entirely.\r\n4. Do not rely on the id length limit or on guest kernel configuration — a path separator costs one character, far short of the 64-character maximum, and while a guest kernel built without `CONFIG_VSOCKETS_LOOPBACK` stops an in-container process from dialing `vminitd` directly, it does nothing about an id the host application relays on the attacker's behalf.\r\n\r\n## Verifying whether you are affected\r\n\r\nOn a release you control, request a container with a path separator in its id and watch the result. An affected release accepts the id and creates the bundle at the location the separator resolves to, outside `/run/container/\u003cid>`; a fixed release rejects the request with an invalid-argument error naming the id. Point the separator at a scratch path, not at anything you need — on an affected release, teardown removes whatever that path resolves to.\r\n\r\nTo check for prior exposure, search retained boot logs for ids that were already accepted:\r\n\r\n```bash\r\ngrep -hoE '\"id\": \"[^\"]*\"' \u003ccontainer-root>/*/bootlog.log | grep -E '\\.\\.|/'\r\n```\r\n\r\nAny hit is an id that resolved outside its bundle. `vminitd` records these at debug level, so an empty result from a deployment running at `info` is not evidence of safety.\r\n\r\n## References\r\n\r\n- Fix: apple/containerization#898, commit [c3ae130bee49def3f47e2cd8d9ba8280d754dddb](https://github.com/apple/containerization/pull/898/commits/c3ae130bee49def3f47e2cd8d9ba8280d754dddb)","vector":"","cvssVersion":"","severitySource":"github","cwes":[],"refs":["https://github.com/apple/containerization/security/advisories/GHSA-x7pf-2jmj-pgcq","https://github.com/apple/containerization"],"affected":[{"product":"apple","ecosystem":"Vendor","package":"apple/containerization","introduced":"","fixed":"0.41.0","lastAffected":""}],"changes":[]},"related":[{"id":"GHSA-g3rx-2m58-rr63","cve":"","aliases":[],"summary":"Unpacking a crafted image layer with an invalid length extended-attribute name crashes the unpacking process","title":"Unpacking a crafted image layer with an invalid length extended-attribute name crashes the unpacking process","severity":"medium","score":null,"product":"apple","productLabel":"","products":["apple"],"fixed":"0.41.0, 1.3.0","fixFirst":"0.41.0","fixedN":2,"published":"2026-08-30","modified":"2026-08-30","withdrawn":"","url":"https://github.com/apple/containerization/security/advisories/GHSA-g3rx-2m58-rr63","foundAt":"2026-09-26 01:32:50"},{"id":"GHSA-697p-8837-37h3","cve":"","aliases":[],"summary":"Unpacking a crafted image layer with a long(invalid) file name crashes the unpacking process","title":"Unpacking a crafted image layer with a long(invalid) file name crashes the unpacking process","severity":"medium","score":null,"product":"apple","productLabel":"","products":["apple"],"fixed":"0.41.0, 1.3.0","fixFirst":"0.41.0","fixedN":2,"published":"2026-08-30","modified":"2026-08-30","withdrawn":"","url":"https://github.com/apple/containerization/security/advisories/GHSA-697p-8837-37h3","foundAt":"2026-09-26 01:32:50"},{"id":"GHSA-r3h2-rgqf-9hv9","cve":"","aliases":[],"summary":"Loading an OCI image layout can read host files through a symlink","title":"Loading an OCI image layout can read host files through a symlink","severity":"medium","score":null,"product":"apple","productLabel":"","products":["apple"],"fixed":"0.41.0, 1.3.0","fixFirst":"0.41.0","fixedN":2,"published":"2026-08-30","modified":"2026-08-30","withdrawn":"","url":"https://github.com/apple/containerization/security/advisories/GHSA-r3h2-rgqf-9hv9","foundAt":"2026-09-26 01:32:50"},{"id":"GHSA-mx96-5vvg-x2mg","cve":"CVE-2026-65388","aliases":[],"summary":"`RegistryClient` follows the `WWW-Authenticate` realm without validating its host or scheme","title":"`RegistryClient` follows the `WWW-Authenticate` realm without validating its host or scheme","severity":"medium","score":null,"product":"apple","productLabel":"","products":["apple"],"fixed":"0.41.0","fixFirst":"0.41.0","fixedN":1,"published":"2026-08-30","modified":"2026-08-30","withdrawn":"","url":"https://github.com/apple/containerization/security/advisories/GHSA-mx96-5vvg-x2mg","foundAt":"2026-09-26 01:32:50"},{"id":"GHSA-f689-h8m7-3jp2","cve":"","aliases":[],"summary":"`ContainerizationOCI` accepts unvalidated OCI descriptor digests, enabling path traversal in the local content store","title":"Apple: path traversal","severity":"high","score":null,"product":"apple","productLabel":"","products":["apple"],"fixed":"0.41.0, 1.3.0","fixFirst":"0.41.0","fixedN":2,"published":"2026-08-30","modified":"2026-08-30","withdrawn":"","url":"https://github.com/apple/containerization/security/advisories/GHSA-f689-h8m7-3jp2","foundAt":"2026-09-26 01:32:50"},{"id":"CVE-2026-64705","cve":"CVE-2026-64705","aliases":[],"summary":"A buffer overflow was addressed with improved bounds checking. This issue is fixed in iOS 26.6 and iPadOS 26.6, macOS Sequoia 15.7.7, macOS Sonoma 14.8.7, macOS Tahoe 26.6.","title":"Apple iOS and iPadOS: buffer overflow","severity":"medium","score":5.5,"product":"apple","productLabel":"iOS and iPadOS","products":["apple"],"fixed":"iOS and iPadOS 26.6, macOS 14.8.7, macOS 15.7.7","fixFirst":"26.6","fixedN":3,"published":"2026-08-25","modified":"2026-09-14","withdrawn":"","url":"https://support.apple.com/en-us/127116","foundAt":"2026-09-26 01:52:08"}]}}