Uh oh!
There was an error while loading. Please reload this page.
Improve security across containerization - #898
Merged
Merged
Conversation
- Validates every OCI descriptor digest as `sha256:<64 lowercase hex characters>`, rejecting path-traversal payloads like `sha256:../../etc/hosts`. - Adds a `ParsedDigest` type (`Content/Digest.swift`) as the one safe way to turn a digest into a path component; `path(in:)` also enforces the result stays under the intended root. - Validates at two independent points: `Descriptor.init(from:)` rejects a malformed digest the moment a manifest/index is decoded, and `LocalContentStore.get`/`delete` validate again at the sink, so a bad digest can't reach the filesystem through either route. - Deprecates `String.trimmingDigestPrefix` since it never validated despite its name; call sites migrate to `validatedDigestEncoding()`. - Bounds `LocalContent.data()`/`.decode()` to 4 MiB (`maxDecodedSize`), matching `RegistryClient`'s existing HTTP response cap, and closing a potential unbounded-read memory-exhaustion path. - Hardens the `ImageStore+Import.swift` cache-hit `copyItem` destination path too, as defense in depth - Rejects negative `Descriptor.size` values at decode time. - Makes digest lookups spelling-agnostic (`sha256:<hex>` or bare `<hex>`) so existing keep-sets and comparisons aren't broken by the new validation. - `Image.referencedDigests()`/`getContent(digest:)`: a malformed root digest now fails loudly (a broken image record shouldn't silently look like "nothing referenced" to a caller garbage-collecting against this list). A malformed *child* entry is skipped instead, so one invalid manifest entry doesn't brick the whole image. - `ImageStore` reference-manager `load()`: tolerates one unreadable `state.json` record instead of failing the entire store load — every other image stays listable/pullable/deletable.
- Rejects a container/exec `id` that is empty, `.`, `..`, or contains `/`, closing a path-traversal write/delete primitive in `vminitd`. - Validates at the two points where an id first becomes a path — `ManagedContainer.init` (container id) and `ManagedContainer.createExecSpec`/exec creation (exec id) — so every downstream use (bundle create/delete, exec spec create/delete) inherits the check for free.
- Original author: Aditya Ramani <a_ramani@apple.com>
Signed-off-by: Kathryn Baldauf <k_baldauf@apple.com>
Signed-off-by: Kathryn Baldauf <k_baldauf@apple.com>
Signed-off-by: Kathryn Baldauf <k_baldauf@apple.com>
jglogan
approved these changes
Aug 28, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for freeto join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
See commit details for more information about each individual change.
This PR fixes a number of issues: