CAP-AUDIT(8)

NAME
cap-audit - discover the minimal capability set for a program

SYNOPSIS
cap-audit [options] -- command [args...]
cap-audit --service file [-- command-or-args...]

DESCRIPTION
cap-audit traces a target process and its descendants to record every kernel capability check it performs. The tool uses eBPF to hook capability verification paths in the kernel and libcap-ng to format the results. Events are filtered to only the traced process tree to reduce overhead.

The auditor fork/execs the requested command, registers its PID for tracing before exec, and automatically tracks child PIDs. At the end of execution it reports which capability checks returned granted or not granted and presents deployment snippets showing how to grant the minimal set.

For syscall-associated checks returning not granted, cap-audit correlates the check with the raw kernel syscall return value when available. A syscall invocation may contain more than one such check, so capability-check and syscall-outcome counts are independent. Successful syscalls show that the not-granted check did not prevent that invocation from completing. EPERM and EACCES results are reported as permission-related failures requiring manual investigation. Other failures are retained as diagnostic evidence. EINTR and kernel restart results are treated as interruption evidence: interruption alone is inconclusive, while a mix of interrupted and successful invocations requires manual investigation because cap-audit cannot distinguish call sites or arguments. Capabilities with only not-granted checks are never added to automatic recommendations; users should add one only after confirming that required functionality fails because it is absent.

The capability masks installed by successful capset(2) calls are also recorded. A capability requested by capset without a confirmed granted check is reported under CAPSET-ONLY CAPABILITIES rather than being classified as required. Deployment snippets retain it as a current-binary compatibility constraint because removing it from the deployment boundary can cause the application's capset to fail. To remove such a capability, first remove it from the application's capability setup, exercise representative code paths in additional runs, and then narrow the deployment boundary. Failed capset calls do not establish this constraint.

Runtime tracing requires root or the CAP_BPF, CAP_PERFMON, and CAP_SYS_PTRACE capabilities, along with kernel BTF data in /sys/kernel/btf/vmlinux.

OPTIONS

-h, --help
    Show a help message and exit.

-v, --verbose
    Print each capability check as it occurs.

-j, --json
    Emit the analysis as JSON.

-y, --yaml
    Emit the analysis as YAML.

-s, --service FILE
    Parse a systemd service unit file, simulate the service user, group, supplementary group, capability, and NoNewPrivileges settings in the traced child, and emit service-specific recommendations. Without an explicit command after --, the parsed ExecStart= command is traced. With --, a command can be supplied explicitly; if the first supplied word starts with -, it is treated as replacement arguments for the parsed ExecStart= executable.

Capabilities explicitly configured in the unit but not observed during the trace are retained in a current-service-compatible recommendation. They are also identified as removal candidates because the relevant functionality may not have been exercised. Cap-audit does not generate a configuration that removes them; targeted testing or manual review must first confirm that each configured capability is unnecessary.

The generated service configuration preserves the NoNewPrivileges= setting used for the audit. When the setting is disabled, enabling it has not been validated by the trace and must be tested separately, including service functionality that starts child processes or helper programs.

Cap-audit does not load the environment configured by Environment= or EnvironmentFile=. A standalone $NAME argument in ExecStart= is therefore treated as unset and omitted. Supply an explicit command after -- when a non-empty expansion is needed for the audit.

A single ! prefix on the ExecStart= executable is supported. It leaves the configured user, group, and supplementary group changes to the executed program while continuing to apply the configured capability and NoNewPrivileges= settings. The fully privileged + prefix and the legacy !! prefix are rejected because cap-audit cannot safely simulate their execution semantics.

If a capability check targets a user namespace different from the namespace in which cap-audit started, the observation is retained in the diagnostic output but automatic capability recommendations are suppressed. The safe scope of a capability grant cannot be determined from the target namespace alone.

--  End option parsing and treat the rest of the command line as the program to execute under audit.

EXIT STATUS
The program returns 0 on success. Non-zero values indicate an error occurred while setting up tracing or executing the target command.

NOTES
1. This utility observes the application behavior to decide what is needed. If you do not exercise all functionality, it can result in an incomplete inventory of needed capabilities. If it can't see it, cap-audit can't record it. 2. There are hard memory constraints for event collection. The limit for the number of children that can be traced is 8192. If an application is fork heavy, such as shell scripts or spawns a lot of short lived helper applications, the tracer will stop collecting events on new children once the buffer fills. Also, the tracer only has space to hold 20k unique stack traces. This is not as problematic as the other constraint as the same code paths often repeat. If this fills up, new code paths will not be collected. This buffer is used to map a capability request to the syscall needing it. Knowing the syscall causing the needed capability is a "nice to have". What's more important is the capability needed - which is in a different memory area and safe from the described issue. In both cases, there is no indication to user space that the tracer is out of memory. 3. When auditing a daemon, pass options to keep it in the foreground. If it forks and exits, that will end the session and you will only get the capabilities traced up to the exit. Here's an example keeping the daemon in the foreground:
cap-audit /usr/sbin/sshd -D

EXPERIMENTAL: cap-audit output is experimental, but very close.

FILES
/sys/kernel/btf/vmlinux

SEE ALSO
capabilities(7), filecap(8).

AUTHOR
Steve Grubb