containerization

GitHub

Containerization is a Swift package for running Linux containers on macOS.

8,843 stars Swift
RAW Doc

Single File Mounts

Single File Mounts

In Containerization, what is analogous to bind mounts goes over virtiofs. virtiofs can only
share directories, not individual files. To support mounting a single file from the host into
a container, Containerization shares the file's parent directory via virtiofs and then bind
mounts the specific file to its final destination inside the container.

How it works

1. Detection: During mount preparation, each virtiofs mount source is stat'd. If it's a
regular file (not a directory), it enters the single-file mount path. Symlinks are
resolved to the real file first.

2. Parent directory share: The file's parent directory is shared via virtiofs into the
guest VM. If multiple single-file mounts reference files in the same parent directory,
only one virtiofs share is created.

3. Guest holding mount: After the VM starts, the parent directory share is mounted to a
holding location in the guest.

4. Bind mount: When the container starts, a bind mount is created from
the holding location to the requested destination path inside the container.

Example

Mounting /Users/dev/config/app.toml to /etc/app.toml in the container:

text
Host:      /Users/dev/config/       (shared via virtiofs)
Guest VM: /temporary/holding/spot/ (virtiofs mount of parent dir)
Container: /etc/app.toml (bind mount of /temporary/holding/spot/app.toml)

Trade-offs

Sharing the parent directory means that sibling files in that directory are visible to the
guest VM at the holding mount point under /run. The bind mount into the container only
exposes the specific file requested, but the full parent directory contents are accessible
from inside the VM itself. This is a deliberate trade-off for reliability. Prior attempts
at supporting single file mounts using temporary directories with hardlinks were fragile
across filesystem boundaries and with certain host filesystem configurations.

Alternatives to single file mounts

If exposing the parent directory to the guest VM is not acceptable for your use case, you
can avoid single-file mounts entirely:

- Mount the whole directory: Instead of mounting a single file, mount the directory that
contains it. This is functionally equivalent (the directory is shared either way) but makes
the behavior explicit and gives the container access to the full directory at the
destination path.

- Stage files into a dedicated directory: Copy the files you need into a dedicated
directory on the host and mount that directory instead. This gives you full control
over what is visible to the guest.

---

X86 64 Build

x86_64 Deployment Build

make dist-x86_64 produces a self-contained x86_64 Linux deployment tarball
at bin/containerization-x86_64-<sha>.tar.gz. The build runs entirely inside
the aarch64 Linux dev container — there is no host tooling requirement beyond
make, container, and the prerequisites the dev image installs.

The tarball ships everything needed to run a Containerization VM on an x86_64
Linux host: the cctl host binary, the cloud-hypervisor VMM, the
virtiofsd filesystem daemon, an x86_64 Linux kernel, and an initfs.ext4
guest rootfs containing vminitd + vmexec.

cctl, cloud-hypervisor, and vminitd/vmexec are statically linked
against musl, so they run on any x86_64 Linux. virtiofsd is dynamically
linked against glibc 2.35+; the deployment host must provide glibc
≥ 2.35 (Ubuntu 22.04 / Debian 12 / RHEL 9 era) plus libseccomp.so.2 and
libcap-ng.so.0. Both are present by default on essentially every server
distro shipped in the last few years.

Prerequisites

Before the first make dist-x86_64:

1. Source checkouts under .local/ — pinned by you, not fetched by the
build. There is no fetch target; clone the revision you want shipped:

sh
git clone -b v52.0 https://github.com/cloud-hypervisor/cloud-hypervisor \
.local/cloud-hypervisor
git clone https://gitlab.com/virtio-fs/virtiofsd .local/virtiofsd

2. An x86_64 kernel at kernel/vmlinuz-x86_64 (preferred) or
kernel/vmlinux-x86_64. Build via make -C kernel TARGET_ARCH=x86_64.
The build fails hard if neither exists — a tarball without a kernel is
not usable.

3. The Linux dev image. dist-x86_64 depends on the linux-image
make target, so the container build cache handles this automatically;
the first run takes a few minutes, subsequent runs are seconds.

The dev image (images/linux-dev/Dockerfile) bundles Swiftly, the Static
Linux SDK, the Rust toolchain (with cargo-zigbuild), a prebuilt
/opt/cross-x86_64-musl/ prefix containing zlib, xz, bzip2, libarchive,
libcap-ng, and libseccomp built static-musl for x86_64, and a sibling
/opt/cross-x86_64-gnu/ prefix containing libcap-ng and libseccomp built
as glibc-dynamic shared libraries for virtiofsd's link step.
scripts/build-musl-x86_64-deps.sh and scripts/build-glibc-x86_64-deps.sh
produce these prefixes at image build time.

Running the build

sh
make dist-x86_64

Drives scripts/build-dist-x86_64.sh inside the dev container via the
linux_run macro. The container bind-mounts the repo at /workspace, so
all build outputs land back on the host under bin/dist-x86_64/.

Pipeline

The script runs five build stages plus a packaging stage. Each build stage
is gated by a freshness check (see Rebuild gating) so
unchanged components are skipped on subsequent runs.

1. cctl cross-compile to x86_64-linux-musl.
swift build --swift-sdk x86_64-swift-linux-musl --product cctl. Always
runs — this is the artifact under iteration, and Swift's incremental
build is a near-no-op when nothing changed.

2. vminitd + vmexec cross-compile to x86_64-linux-musl.
make -C vminitd LIBC=musl MUSL_ARCH=x86_64. The guest agent and
process launcher; both run inside the VM as PID 1's children.

3. cloud-hypervisor cross-compile to x86_64-unknown-linux-musl.
cargo zigbuild --target x86_64-unknown-linux-musl --bin cloud-hypervisor
from .local/cloud-hypervisor.

4. virtiofsd cross-compile to x86_64-unknown-linux-gnu.2.35.
cargo zigbuild --target x86_64-unknown-linux-gnu.2.35 from
.local/virtiofsd, with scripts/patches/virtiofsd-skip-cap-drop-with-sandbox-none.patch
applied first. The patch is idempotent — applied if missing, skipped if
already present, fails hard if it can't be applied cleanly. Unlike the
other three host binaries, virtiofsd is glibc-dynamic: it expects
the deployment host to provide glibc ≥ 2.35, libseccomp.so.2, and
libcap-ng.so.0. Link-time .so files come from
/opt/cross-x86_64-gnu/.

5. initfs.ext4 packaging.
scripts/build-initfs.sh --vminitd … --vmexec … --ext4 … stages the guest
rootfs and writes a ready-to-mount ext4 image with the x86_64 guest binaries
inside (loop mount where available, else mke2fs -d). The x86_64 tarball
ships this raw ext4 and boots it via cctl run --initfs, so — unlike the
arm64 flow — no vminit OCI image is built here.

6. Stage and tar. Always runs. Lays out the staging tree at
bin/dist-x86_64/<dist-name>/:

text
<dist-name>/
├── bin/
│ ├── cctl
│ ├── cloud-hypervisor
│ └── virtiofsd
├── kernel/
│ └── vmlinuz-x86_64 # or vmlinux-x86_64, whichever was found
└── initfs.ext4

Then tar -czf bin/<dist-name>.tar.gz.

Rebuild gating

By default, every stage skips when its output is up-to-date. Each freshness
check has a corresponding REBUILD_*=1 environment variable that forces
the stage to rerun.

| Stage | Skip condition | Force rebuild |
| --- | --- | --- |
| cctl x86 cross | (never skipped — always runs) | n/a |
| vminitd + vmexec | both binaries exist under bin/dist-x86_64/ AND nothing under vminitd/Sources/, vminitd/Package.swift, or Sources/Containerization/SandboxContext/ is newer than them | REBUILD_VMINITD=1 |
| cloud-hypervisor | bin/dist-x86_64/cloud-hypervisor exists | REBUILD_CH=1 |
| virtiofsd | bin/dist-x86_64/virtiofsd exists | REBUILD_VIRTIOFSD=1 |
| initfs.ext4 | exists AND is newer than both staged vminitd and vmexec (also implicitly skipped when vminitd was skipped) | REBUILD_INITFS=1 |
| native aarch64 cctl | only built when initfs.ext4 is being rebuilt | REBUILD_INITFS=1 |
| stage tree + tar | (always runs) | n/a |

The freshness checks intentionally use binary presence and source mtimes
rather than content hashing — fast to evaluate, easy to bypass with touch
or rm. There is no global "rebuild everything" switch by design; force
the specific component you want, or rm -rf bin/dist-x86_64/ for a full
clean rebuild.

cloud-hypervisor and virtiofsd only check binary presence (not source
mtime against .local/). The pinned-source convention assumes you opt
into rebuilds explicitly — the REBUILD_CH=1 / REBUILD_VIRTIOFSD=1
escape hatches exist for exactly that case. Walking the full Rust source
tree on every run was the alternative; not worth the cost.

Common rebuild scenarios

- Iterating on host-side cctl or Containerization Swift code: just
make dist-x86_64. Only the x86 cctl rebuild runs (and tar).
- Touched vminitd source or the proto: REBUILD_VMINITD=1 is
picked up automatically by mtime; make dist-x86_64. vminitd and
initfs.ext4 rebuild.
- Pulled new .local/cloud-hypervisor: REBUILD_CH=1 make dist-x86_64.
- Pulled new .local/virtiofsd: REBUILD_VIRTIOFSD=1 make dist-x86_64.
- Suspect a stale artifact: rm -rf bin/dist-x86_64 && make dist-x86_64
for a full clean rebuild.

Cross-compilation toolchain

Two cross toolchains live side-by-side in the dev image. cctl,
vminitd/vmexec, and cloud-hypervisor target x86_64-linux-musl and
ship statically linked so the artifacts are host-libc independent.
virtiofsd targets x86_64-linux-gnu.2.35 and ships dynamically linked;
the deployment host provides glibc, libseccomp, and libcap-ng.

- Swift uses Apple's Static Linux SDK (x86_64-swift-linux-musl),
installed into the dev image by make linux-image (Dockerfile
SWIFT_SDK_URL/SWIFT_SDK_CHECKSUM build args). The same SDK
is used for both cctl and vminitd cross-builds.
- Rust C cross-compiler is Zig. For musl stages, zig cc -target
x86_64-linux-musl
is wrapped as x86_64-linux-musl-{gcc,g++,ar,ranlib,strip}.
For virtiofsd, parallel x86_64-linux-gnu-* wrappers dispatch to
zig cc -target x86_64-linux-gnu.2.35, plus an x86_64-linux-gnu-ld
wrapper backed by LLVM's ld.lld (apt-installed). The ld wrapper
is needed because libtool's shared-library detection probes the
linker with -m elf_x86_64; the host's aarch64 /usr/bin/ld
rejects that and would silently disable .so emission. The gnu
gcc/g++ wrappers intercept -print-prog-name=ld so libtool
discovers the cross-ld wrapper instead of the host linker. The
pinned .2.35 glibc baseline determines the minimum host glibc;
bumping it requires editing the wrapper scripts under
images/linux-dev/wrappers/. Zig was chosen over musl.cc / gcc
cross prebuilts because aarch64-hosted versions of those aren't
published.
- Rust linker is not set explicitly. cargo-zigbuild installs
its own linker wrapper that strips Rust's self-contained musl crt
files (which would otherwise collide with Zig's musl crt). Setting
CARGO_TARGET_*_LINKER ourselves overrides that and produces
duplicate-symbol link errors.
- pkg-config points at /opt/cross-x86_64-musl/lib/pkgconfig for
the musl stages; the virtiofsd block overrides it in a subshell to
point at /opt/cross-x86_64-gnu/lib/pkgconfig so libseccomp-sys
and libcap-ng's capng-sys resolve against the glibc-dynamic
.so files, not the static-musl .a archives. The musl prefix uses
GNU ld linker scripts at lib{seccomp,cap-ng}.so to redirect
dynamic-link requests into the static archives; the gnu prefix ships
real shared libraries.

The cross C dep prefixes are built by scripts/build-musl-x86_64-deps.sh
and scripts/build-glibc-x86_64-deps.sh during make linux-image.
Modifying either script invalidates that layer of the dev image and
triggers a rebuild on the next make dist-x86_64.

Troubleshooting

- ERROR: missing .local/cloud-hypervisor source checkout — see
Prerequisites. There is no fetch target; clone the revision you want
pinned.
- ERROR: no x86_64 kernel found — run
make -C kernel TARGET_ARCH=x86_64. The build refuses to ship a
tarball without a kernel.
- ERROR: virtiofsd cap-drop patch does not apply cleanly — the
patch only applies to known-good upstream revisions of virtiofsd. If
you bumped .local/virtiofsd past that, refresh
scripts/patches/virtiofsd-skip-cap-drop-with-sandbox-none.patch
against the new revision.
- Stale binary on the deployment host — confirm the tarball SHA in
bin/containerization-x86_64-<sha>.tar.gz matches git rev-parse
--short HEAD
. The script tags the tarball with HEAD at build time;
uncommitted changes ship under the same SHA as their parent commit.
- Linker errors mentioning duplicate crt*.o symbols — something is
setting CARGO_TARGET_*_LINKER. Unset it and let cargo-zigbuild
manage the linker.
- virtiofsd: error while loading shared libraries: libseccomp.so.2
(or libcap-ng.so.0) on the deployment host — install the system
packages (apt install libseccomp2 libcap-ng0 on Debian/Ubuntu,
dnf install libseccomp libcap-ng on Fedora/RHEL). virtiofsd is
glibc-dynamic by design; the libs are not bundled in the tarball.
- virtiofsd: /lib/x86_64-linux-gnu/libc.so.6: version 'GLIBC_2.35'
not found
— the deployment host's glibc is older than the build's
baseline. Either upgrade the host or rebuild with a lower baseline
by editing the -target x86_64-linux-gnu.<ver> arg in
images/linux-dev/wrappers/x86_64-linux-gnu-{gcc,g++} and the
cargo zigbuild --target x86_64-unknown-linux-gnu.<ver> line in
scripts/build-dist-x86_64.sh.

---

CONTRIBUTING

🌈 📦️ Welcome to the Containerization community! 📦️ 🌈

Contributions to Containerization are welcomed and encouraged.

Index

- How you can help
- Submitting issues and pull requests
- New to open source?
- AI contribution guidelines
- Code of conduct

How you can help

We would love your contributions in the form of:

🐛 Bug fixes\
⚡️ Performance improvements\
✨ API additions or enhancements\
📝 Documentation\
🧑‍💻 Project advocacy: blogs, conference talks, and more

Anything else that could enhance the project!

Submitting issues and pull requests

Issues

To file a bug or feature request, use GitHub issues.

🚧 For unexpected behavior or usability limitations, detailed instructions on how to reproduce the issue are appreciated. This will greatly help the priority setting and speed at which maintainers can get to your issue.

Pull requests

We require all commits be signed with any of GitHub's supported methods, such as GPG or SSH. Information on how to set this up can be found on GitHub's docs.

To make a pull request, use GitHub. Please give the team a few days to review but it's ok to check in on occasion. We appreciate your contribution!

IMPORTANT

If you plan to make substantial changes or add new features, we encourage you to first discuss them with the wider containerization developer community.


You can do this by filing a GitHub issue.

This will save time and increases the chance of your pull request being accepted.

We use a "squash and merge" strategy to keep our main branch history clean and easy to follow. When your pull request
is merged, all of your commits will be combined into a single commit.

With the "squash and merge" strategy, the title and body of your pull request is extremely important. It will become the commit message
for the squashed commit. Think of it as the single, definitive description of your contribution.

Before merging, we'll review the pull request title and body to ensure it:

* Clearly and concisely describes the changes.
* Uses the imperative mood (for example, "Add feature," "Fix bug").
* Provides enough context for future developers to understand the purpose of the change.

The pull request description should be concise and accurately describe the what and why of your changes.

#### .gitignore contributions

We do not currently accept contributions to add editor specific additions to the root .gitignore. We urge contributors to make a global .gitignore file with their rulesets they may want to add instead. A global .gitignore file can be set like so:

bash
git config --global core.excludesfile ~/.gitignore

#### Formatting contributions

Make sure your contributions are consistent with the rest of the project's formatting. You can do this using our Makefile:

bash
make fmt

#### Applying license header to new files

If you submit a contribution that adds a new file, please add the license header. You can do this using our Makefile:

bash
make update-licenses

New to open source?

How do I pick something to work on?

Take a look at the good first issue label in the containerization or container project.
Before you start working on an issue:
* Check the comments, assignees, and any references to pull requests — make sure nobody else is actively working on it, or awaiting help or review.
* If someone is assigned to the issue or volunteered to work on it, and there are no signs of progress or activity over at least the past month, don't hesitate to check in with them
* Leave a comment that you have started working on it.

Getting help

Don't be afraid to ask for help! When asking for help, provide as much information as possible, while highlighting anything you think may be important. Refer to the MAINTAINERS.txt file for the appropriate people to ping.

I didn't get a response from someone. What should I do?

It's possible that you ask someone a question in an issue/pull request and you don't get a response as quickly as you'd like. If you don't get a response within a week, it's okay to politely ping them using an @ mention. If you don't get a response for 2-3 weeks in a row, please ping someone else.

I can't finish the contribution I started

Sometimes an issue ends up bigger, harder, or more time-consuming than expected — and that’s completely fine. Be sure to comment on the issue saying you’re stepping away, so that someone else is able to pick it up.

AI contribution guidelines

We welcome thoughtful use of AI tools in your contributions to this repository. We ask that you adhere to these rules in order to preserve the project's integrity, clarity, and quality, and to respect maintainer bandwidth:

* You should be able to explain and justify every line of code or documentation that was generated or assisted by AI. Your submission should reflect your own understanding and intent.
* Use AI to augment, not totally replace, your reasoning or familiarity, especially for non-trivial parts of the system.
* Avoid dumping AI-generated walls of text that you cannot explain. Low-effort, unexplained submissions will be deprioritized to protect maintainer bandwidth.

AI tools should be used to enhance, not replace the human elements that make OSS special: learning, collaboration, and community growth.

Code of conduct

To clarify what is expected of our contributors and community members, the Containerization team has adopted the code of conduct defined by the Contributor Covenant. This document is used across many open source communities and articulates our values well. For more detail, please read the Code of Conduct.

---

README

<h1>
<img alt="Containerization logo" src="./assets/Containerization-Logo.png" width="70" valign="middle">
&nbsp;Containerization
</h1>

The Containerization package allows applications to use Linux containers.
Containerization is written in Swift and uses Virtualization.framework on Apple silicon.

Looking for command line binaries for running containers?\

They are available in the dedicated apple/container repository.

Containerization provides APIs to:

- Manage OCI images.
- Interact with remote registries.
- Create and populate ext4 file systems.
- Interact with the Netlink socket family.
- Create an optimized Linux kernel for fast boot times.
- Spawn lightweight virtual machines and manage the runtime environment.
- Spawn and interact with containerized processes.
- Use Rosetta 2 for running linux/amd64 containers on Apple silicon.

Please view the API documentation for information on the Swift packages that Containerization provides.

Design

Containerization executes each Linux container inside of its own lightweight virtual machine. Clients can create dedicated IP addresses for every container to remove the need for individual port forwarding. Containers achieve sub-second start times using an optimized Linux kernel configuration and a minimal root filesystem with a lightweight init system.

vminitd is a small init system, which is a subproject within Containerization.
vminitd is spawned as the initial process inside of the virtual machine and provides a GRPC API over vsock.
The API allows the runtime environment to be configured and containerized processes to be launched.
vminitd provides I/O, signals, and events to the calling process when a process is run.

Backends

Containerization abstracts the VMM behind the VirtualMachineManager /
VirtualMachineInstance protocols and ships two implementations:

- macOS — Virtualization.framework (VZVirtualMachineManager). The shipping path on Apple silicon. Uses Apple's Virtualization framework directly; no extra binaries required.
- Linux — cloud-hypervisor + KVM (CHVirtualMachineManager). One cloud-hypervisor subprocess per VM, controlled over its REST-on-UDS API by the standalone CloudHypervisor Swift package. Block storage uses virtio-blk, shared directories use virtio-fs (one virtiofsd per share), networking uses TAP, and the guest agent is reached over cloud-hypervisor's hybrid vsock — same vminitd contract as the macOS path, so guest-side semantics are unchanged.

The Linux backend requires:

- cloud-hypervisor and virtiofsd on the host. Both are looked up on PATH by default; CHVirtualMachineManager.init accepts explicit URLs to override. virtiofsd is resolved lazily — a VM that uses only block-device mounts can run without it installed at all. Recent stable releases of each are recommended (smoke testing pins specific versions).
- KVM access (/dev/kvm readable + writable by the calling user).
- Pre-staged TAP / bridge / NAT plumbing if the container needs networking. TAPInterface consumes an existing TAP device by name; bringing it up, attaching it to a bridge, and configuring NAT or routing is the caller's responsibility.

The integration test suite (make linux-integration) runs inside an apple/container Linux VM with nested virt enabled (container run --virtualization). The kata kernel fetched by make fetch-default-kernel does not enable KVM, so the integration suite uses the in-repo kernel at kernel/vmlinux-arm64 (or kernel/vmlinuz-x86_64 on x86_64 hosts) instead — build it with make -C kernel before invoking make linux-integration. On Linux the suite runs only the cross-platform scenarios that don't depend on macOS-only types; the full suite remains macOS-only for now.

Requirements

To build the Containerization package, you need:

- Mac with Apple silicon
- macOS 26
- Xcode 26

Older versions of macOS are not supported.

Example Usage

For examples of how to use the libraries' API surface, the cctl executable is a good start. This app is a useful playground for exploring the API. It contains commands that exercise some of the core functionality of the various products, such as:

1. Manipulating OCI images
2. Logging in to container registries
3. Creating root filesystem blocks
4. Running simple Linux containers

Linux kernel

A Linux kernel is required for spawning lightweight virtual machines on macOS.
Containerization provides an optimized kernel configuration located in the kernel directory.

This directory includes a containerized build environment to easily compile a kernel for use with Containerization.

The kernel configuration is a minimal set of features to support fast start times and a lightweight environment.

While this configuration will work for the majority of workloads we understand that some will need extra features.
To solve this Containerization provides first class APIs to use different kernel configurations and versions on a per container basis.
This enables containers to be developed and validated across different kernel versions.

See the README in the kernel directory for instructions on how to compile the optimized kernel.

Kernel Support

Containerization allows user provided kernels but tests functionality starting with kernel version 6.14.9.

Pre-built Kernel

If you wish to consume a pre-built kernel, make sure it has VIRTIO drivers compiled into the kernel (not merely as modules).

The Kata Containers project provides a Linux kernel that is optimized for containers, with all required configuration options enabled. The releases page contains downloadable artifacts, and the image itself (vmlinux.container) can be found in the /opt/kata/share/kata-containers/ directory.

Prepare to build package

Install the recommended version of Xcode.

Set the active developer directory to the installed Xcode (replace <PATH_TO_XCODE>):

bash
sudo xcode-select -s <PATH_TO_XCODE>

The Linux guest init (vminitd/vmexec) is compiled as a static binary
inside a Linux container rather than cross-compiled on your Mac, so no Swift
toolchain, Swiftly, or Static Linux SDK setup is required on the host. Install
the container CLI, which the build uses
to compile the guest:

bash

Install per https://github.com/apple/container, then verify it is on PATH:


container --version

The first build automatically builds the Linux dev image used to compile the
guest, which can take a few minutes.

Build the package

Build Containerization from sources:

bash
make all

Test the package

After building, run basic and integration tests:

bash
make test integration

A kernel is required to run integration tests.
If you do not have a kernel locally, a default kernel can be fetched using the make fetch-default-kernel target.

Fetching the default kernel only needs to happen after an initial build or after a make clean.

bash
make fetch-default-kernel
make all test integration

Protobufs

Containerization depends on specific versions of grpc-swift and swift-protobuf. You can install them and re-generate RPC interfaces with:

bash
make protos

Building a kernel

If you'd like to build your own kernel please see the instructions in the kernel directory.

Pre-commit hook

Run make pre-commit to install a pre-commit hook that ensures that your changes have correct formatting and license headers when you run git commit.

Documentation

Generate the API documentation for local viewing with:

bash
make docs
make serve-docs

Preview the documentation by running in another terminal:

bash
open http://localhost:8000/containerization/documentation/

Contributing

Contributions to Containerization are welcomed and encouraged. Please see CONTRIBUTING.md for more information.

Project Status

Version 0.1.0 is the first official release of Containerization. Earlier versions have no source stability guarantees.

Because the Containerization library is under active development, source stability is only guaranteed within minor versions (for example, between 0.1.1 and 0.1.2). If you don't want potentially source-breaking package updates, you can specify your package dependency using .upToNextMinorVersion(from: "0.1.0") instead.

Future minor versions of the package may introduce changes to these rules as needed.

---

SECURITY

Security disclosure process

If you believe that you have discovered a security or privacy vulnerability in our open source software, please report it to us using the GitHub private vulnerability feature. Reports should include specific product and software version(s) that you believe are affected; a technical description of the behavior that you observed and the behavior that you expected; the steps required to reproduce the issue; and a proof of concept or exploit.

The project team will do their best to acknowledge receiving all security reports within 7 days of submission. This initial acknowledgment is neither acceptance nor rejection of your report. The project team may come back to you with further questions or invite you to collaborate while working through the details of your report.

Keep these additional guidelines in mind when submitting your report:

* Reports concerning known, publicly disclosed CVEs can be submitted as normal issues to this project.
* Output from automated security scans or fuzzers MUST include additional context demonstrating the vulnerability with a proof of concept or working exploit.
* Application crashes due to malformed inputs are typically not treated as security vulnerabilities, unless they are shown to also impact other processes on the system.

While we welcome reports for open source software projects, they are not eligible for Apple Security Bounties.

---