# How to Drop Linux Capabilities from a Container with the Apple Container CLI

> Learn to drop Linux capabilities from a container using the Apple container CLI with the --cap-drop flag. Secure your containers by reducing their privileges before they start.

- Repository: [Apple/container](https://github.com/apple/container)
- Tags: how-to-guide
- Published: 2026-07-05

---

**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`](https://github.com/apple/container/blob/main/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`](https://github.com/apple/container/blob/main/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`](https://github.com/apple/container/blob/main/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`](https://github.com/apple/container/blob/main/Sources/Services/RuntimeLinux/Server/RuntimeService.swift). The `effectiveCapabilities` method (lines 1170-1195) computes the final capability set through a four-step process:

1. Start with the OCI default capability list.
2. If `"ALL"` appears in `capDrop`, clear the list entirely.
3. Add any capabilities specified in `capAdd`.
4. Remove specific capabilities listed in `capDrop` that 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:

```bash
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:

```bash
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:

```bash
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:

```bash
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-drop` flag in the Apple Container CLI removes specific Linux capabilities from the container process.
- The implementation spans [`Flags.swift`](https://github.com/apple/container/blob/main/Flags.swift) for input parsing, [`Parser.swift`](https://github.com/apple/container/blob/main/Parser.swift) for validation, and [`RuntimeService.swift`](https://github.com/apple/container/blob/main/RuntimeService.swift) for final computation.
- The `RuntimeService.effectiveCapabilities` method handles the special `"ALL"` keyword to clear capabilities and supports combining `--cap-drop` with `--cap-add` for 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`](https://github.com/apple/container/blob/main/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`](https://github.com/apple/container/blob/main/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`](https://github.com/apple/container/blob/main/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.