How to Drop Linux Capabilities from a Container with the Apple Container CLI
You can drop Linux capabilities from a container using the Apple container CLI by passing the --cap-drop flag, which modifies the effective capability set calculated in RuntimeService.effectiveCapabilities before the container starts.
The Apple container repository provides a command-line interface for managing Linux containers. Dropping Linux capabilities reduces the attack surface by removing specific privileges—such as CAP_NET_RAW or CAP_MKNOD—from the container process. The CLI implements this security feature through a multi-stage pipeline that parses user input, validates capability names, and computes the final effective set before invoking the low-level runtime.
Understanding Linux Capabilities in Containers
Linux capabilities are fine-grained privileges that allow processes to perform specific privileged operations without requiring full root access. When you drop a capability, you explicitly remove that permission from the container's process tree, enforcing the principle of least privilege. The Apple Container CLI manages these permissions through the --cap-drop flag, which interfaces with the OCI runtime specification to modify the container's security profile.
How the Apple Container CLI Handles Capability Dropping
The implementation spans several components across the codebase, from CLI argument parsing to runtime execution.
CLI Flag Definition in Flags.swift
The --cap-drop flag is defined in Sources/Services/ContainerAPIService/Client/Flags.swift (lines 38-41) as a string array that accepts one or more capability names. When users specify multiple capabilities, the CLI aggregates them into a single list for processing.
Capability Normalization in Parser.swift
Before storage, capability names undergo normalization in Sources/Services/ContainerAPIService/Client/Parser.swift. The Parser.capabilities method (lines 1025-1050) automatically adds the CAP_ prefix if missing, validates the capability names against the kernel's supported set, and removes duplicates to ensure a clean configuration.
Configuration Storage in ContainerConfiguration.swift
The parsed capabilities are stored in the ContainerConfiguration.capDrop property within Sources/ContainerResource/Container/ContainerConfiguration.swift (lines 60-62). This configuration object serves as the source of truth for the container's security profile, holding both capAdd and capDrop arrays that will be passed to the runtime.
Runtime Calculation in RuntimeService.swift
The critical logic resides in Sources/Services/RuntimeLinux/Server/RuntimeService.swift. The effectiveCapabilities method (lines 1170-1195) computes the final capability set through a four-step process:
- Start with the OCI default capability list.
- If
"ALL"appears incapDrop, clear the list entirely. - Add any capabilities specified in
capAdd. - Remove specific capabilities listed in
capDropthat are not"ALL".
The resulting array is then transmitted to the low-level runtime via the gRPC CreateContainer request in the createContainer implementation.
Practical Examples for Dropping Capabilities
Here are concrete examples demonstrating how to use the --cap-drop flag in different scenarios.
Drop a single capability to remove raw socket access:
container run --cap-drop CAP_NET_RAW myimage:latest
This removes only the CAP_NET_RAW capability from the default OCI set, preventing the container from creating raw sockets while retaining other privileges.
Drop multiple capabilities for a more locked-down environment:
container run \
--cap-drop CAP_MKNOD \
--cap-drop CAP_CHOWN \
myimage:latest
The CLI merges these into ["CAP_MKNOD", "CAP_CHOWN"] and the runtime subtracts both from the effective set.
Drop all capabilities to start with zero privileges:
container run --cap-drop ALL myimage:latest
When "ALL" is specified, effectiveCapabilities starts with an empty list, creating a container with no capabilities unless explicitly added back.
Combine add and drop for minimal privileges:
container run \
--cap-add CAP_NET_RAW \
--cap-drop ALL \
myimage:latest
This pattern starts with zero capabilities, then re-adds only CAP_NET_RAW, resulting in a container with exactly one privilege.
Summary
- The
--cap-dropflag in the Apple Container CLI removes specific Linux capabilities from the container process. - The implementation spans
Flags.swiftfor input parsing,Parser.swiftfor validation, andRuntimeService.swiftfor final computation. - The
RuntimeService.effectiveCapabilitiesmethod handles the special"ALL"keyword to clear capabilities and supports combining--cap-dropwith--cap-addfor fine-grained control. - All capability modifications are passed to the Linux runtime via gRPC before the container starts.
Frequently Asked Questions
Can I drop all capabilities and add back only specific ones?
Yes. Specify --cap-drop ALL to clear the default capability set, then use --cap-add to grant only the specific capabilities your container requires. According to the source code in Sources/Services/RuntimeLinux/Server/RuntimeService.swift, the runtime processes the clear operation first when "ALL" is detected, then applies capAdd entries, resulting in a minimal privilege set.
Does the Apple Container CLI validate capability names before runtime?
Yes. The Parser.capabilities method in Sources/Services/ContainerAPIService/Client/Parser.swift normalizes capability names by adding the CAP_ prefix if missing and validates them against the kernel's supported set, removing duplicates before storing them in the container configuration.
What happens if I specify the same capability in both --cap-add and --cap-drop?
The logic in RuntimeService.effectiveCapabilities processes additions after handling the "ALL" drop flag, then removes specific capabilities listed in capDrop. Since specific drops are applied after additions, a capability listed in both will be removed from the final effective set.
Where is the final capability set calculated before the container starts?
The final calculation occurs in Sources/Services/RuntimeLinux/Server/RuntimeService.swift within the effectiveCapabilities method (lines 1170-1195). This function computes the effective set and passes it to the low-level runtime via the gRPC CreateContainer request.
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 →