# How to Manage Linux Capabilities for Containers on macOS

> Learn how to manage Linux capabilities for containers on macOS using the apple/container CLI. Fine-tune process permissions with `--cap-add` and `--cap-drop` flags for enhanced control.

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

---

**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`](https://github.com/apple/container/blob/main/docs/how-to.md), the default permitted set includes:

- `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`
- `CAP_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`](https://github.com/apple/container/blob/main/docs/how-to.md) and [`docs/command-reference.md`](https://github.com/apple/container/blob/main/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 ALL` results in **all** capabilities being granted (the drop happens first, then the add restores everything)
- `--cap-drop ALL --cap-add SETUID --cap-add SETGID` gives you only the two specified capabilities

This behavior is implemented in the runtime logic and documented in [`docs/how-to.md`](https://github.com/apple/container/blob/main/docs/how-to.md).

## Common Capability Patterns

### Grant All Capabilities

To run a container with full privileges, add all capabilities:

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

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

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

```bash
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`](https://github.com/apple/container/blob/main/XPCServer.swift) and [`XPCClient.swift`](https://github.com/apple/container/blob/main/XPCClient.swift)), the CLI forwards these flags to the XPC server, which manages the container lifecycle.

The wrapper script [`scripts/update-container.sh`](https://github.com/apple/container/blob/main/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`, and `CAP_CHOWN`.
- **Management flags**: Use `--cap-add` to grant additional permissions and `--cap-drop` to 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.md`](https://github.com/apple/container/blob/main/docs/how-to.md) and [`docs/command-reference.md`](https://github.com/apple/container/blob/main/docs/command-reference.md), while implementation logic is in `Sources/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`](https://github.com/apple/container/blob/main/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`](https://github.com/apple/container/blob/main/docs/how-to.md) and enforced by the runtime implementation in `Sources/ContainerXPC`.