How to Manage Linux Capabilities for Containers on macOS
macOS provides the container CLI to add or drop Linux capabilities when creating or running containers, using the --cap-add and --cap-drop flags to fine-tune process permissions beyond the default restricted set.
The apple/container repository provides a lightweight container runtime for macOS that supports Linux capabilities. You can manage Linux capabilities for containers on macOS using the container command-line interface, which accepts standard Docker-like flags to customize the permission set available to containerized processes according to the source documentation.
Default Linux Capabilities on macOS
By default, containers started on macOS receive a restricted set of Linux capabilities. As documented in docs/how-to.md, the default permitted set includes:
CAP_AUDIT_WRITECAP_CHOWNCAP_DAC_OVERRIDECAP_FOWNERCAP_FSETIDCAP_KILLCAP_MKNODCAP_NET_BIND_SERVICECAP_NET_RAWCAP_SETFCAPCAP_SETGIDCAP_SETPCAPCAP_SETUIDCAP_SYS_CHROOT
This default set provides basic privileges while maintaining security boundaries, but you can modify it using the capability management flags.
Adding and Dropping Capabilities
The container CLI supports two flags for capability management, documented in both docs/how-to.md and docs/command-reference.md:
--cap-add <cap> - Adds a capability to the container's permitted set. The name can be written with or without the CAP_ prefix and is case-insensitive.
--cap-drop <cap> - Removes a capability from the default set.
Both flags are accepted by the container run and container create commands.
Syntax and Formatting
Capability names are case-insensitive and flexible in formatting. For example, NET_ADMIN, net_admin, and CAP_NET_ADMIN are all valid when passed to --cap-add or --cap-drop.
Capability Ordering Semantics
When you specify multiple capability modifications, the runtime applies all --cap-drop operations first, then all --cap-add operations. This ordering has specific implications:
--cap-drop ALL --cap-add ALLresults in all capabilities being granted (the drop happens first, then the add restores everything)--cap-drop ALL --cap-add SETUID --cap-add SETGIDgives you only the two specified capabilities
This behavior is implemented in the runtime logic and documented in docs/how-to.md.
Common Capability Patterns
Grant All Capabilities
To run a container with full privileges, add all capabilities:
container run --cap-add ALL alpine sh -c "ip link set lo down && echo ok"
This pattern is useful when you need unrestricted access to system resources.
Drop Everything and Selectively Re-add
For maximum security, start with a blank slate and enable only specific capabilities:
container run --cap-drop ALL --cap-add SETUID --cap-add SETGID alpine id
This approach follows the principle of least privilege, granting only the minimum permissions required for your workload.
Grant All Except Specific Capabilities
When you need most privileges but must forbid specific ones:
container run --cap-add ALL --cap-drop NET_ADMIN alpine sh
This pattern keeps the full privilege set while blocking specific dangerous capabilities.
Remove a Single Default Capability
To demonstrate that a capability is indeed removed and enforce restrictions:
container run --cap-drop CHOWN alpine chown 100 /tmp
# → "Operation not permitted"
This command fails because the CHOWN capability has been removed from the container's permitted set.
Implementation Details
The capability flags are processed through the container runtime's IPC layer. According to the source code in Sources/ContainerXPC (specifically XPCServer.swift and XPCClient.swift), the CLI forwards these flags to the XPC server, which manages the container lifecycle.
The wrapper script scripts/update-container.sh demonstrates how the CLI options are passed through to the underlying container binary, ensuring that your capability specifications reach the runtime intact.
Summary
- Default capabilities: macOS containers start with 14 restricted capabilities including
CAP_NET_RAW,CAP_SETUID, andCAP_CHOWN. - Management flags: Use
--cap-addto grant additional permissions and--cap-dropto remove them. - Flexible naming: Capability names accept
CAP_prefix or plain names, case-insensitive. - Ordering matters: All drops are applied before adds, allowing complex permission scenarios like "drop all then add specific."
- Source locations: Documentation resides in
docs/how-to.mdanddocs/command-reference.md, while implementation logic is inSources/ContainerXPC.
Frequently Asked Questions
What are the default Linux capabilities for containers on macOS?
By default, macOS containers receive a restricted set of 14 capabilities including CAP_AUDIT_WRITE, CAP_CHOWN, CAP_DAC_OVERRIDE, CAP_FOWNER, CAP_FSETID, CAP_KILL, CAP_MKNOD, CAP_NET_BIND_SERVICE, CAP_NET_RAW, CAP_SETFCAP, CAP_SETGID, CAP_SETPCAP, CAP_SETUID, and CAP_SYS_CHROOT. This set is defined in the docs/how-to.md file and provides basic container functionality while maintaining security boundaries.
How do I grant all Linux capabilities to a container on macOS?
Use the --cap-add ALL flag when running or creating a container: container run --cap-add ALL alpine sh. This grants every available Linux capability to the container process, effectively giving it full privileges similar to running as root without restrictions.
Can I remove specific capabilities from the default set?
Yes, use the --cap-drop flag followed by the capability name. For example, container run --cap-drop CHOWN alpine chown 100 /tmp removes the CHOWN capability, causing chown operations to fail with "Operation not permitted". You can drop multiple capabilities by specifying the flag multiple times.
In what order are capability modifications applied?
All --cap-drop operations are applied first, followed by all --cap-add operations. This means that --cap-drop ALL --cap-add SETUID results in only the SETUID capability being granted, while --cap-add ALL --cap-drop NET_ADMIN grants all capabilities except NET_ADMIN. This ordering is documented in docs/how-to.md and enforced by the runtime implementation in Sources/ContainerXPC.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →