lookout audit hardening
Workload security posture: containers running privileged or holding node-root capabilities, pods sharing the host network/PID/IPC namespaces, hostPath mounts, default-ServiceAccount tokens that something actually uses, and namespaces with no Pod Security Admission enforcement. Judges every pod-template owner in scope — Deployments, StatefulSets, DaemonSets, CronJobs, unowned Jobs and unowned Pods — plus the namespaces around them. Scope with —namespace or -A; scanned counts pod templates examined, the namespaces note counts namespaces.
MCP tool: k8s_audit_hardening (MCP profile: audit)
lookout audit hardening [flags]Common flags (every lookout command)
Section titled “Common flags (every lookout command)”| Flag | Type | Default | Meaning |
|---|---|---|---|
--namespace | string | — | limit the scan to one namespace |
-A | bool | — | scan all namespaces |
--workload | string | — | target one workload as <Kind>/<namespace>/<name>, e.g. Deployment/prod/api |
--since | duration | — | how far back to look (0 = command default) |
--format | string | logfmt | output format: logfmt|json (one record per line either way) |
--timeout | duration | 10s | abort the invocation after this long (exit 1) |
--kubeconfig | string | — | path to a kubeconfig file, instead of $KUBECONFIG / ~/.kube/config |
--context | string | — | kubeconfig context to read, instead of its current-context. Selects a cluster for THIS invocation only — nothing is written back — so concurrent invocations can target different clusters. Reported as context=<name> in the summary line |
--exemptions | string | — | path to a git-reviewed exemption file (YAML); covered findings are ANNOTATED with their reason and expiry and counted as exempt=<n> in the summary, never dropped |
Finding kinds
Section titled “Finding kinds”Every kind= this command can emit, and the severities it carries them at. Nothing else appears in its output; a kind absent from a run means the check looked and found nothing. See the finding-kind glossary for the whole vocabulary.
| Kind | Severity | Claim |
|---|---|---|
audit.privileged_container | warning | a container runs privileged or holds a node-root capability (ALL, SYS_ADMIN): a container escape is a node compromise |
audit.host_namespace | warning | the pod shares the node’s network, PID, or IPC namespace |
audit.hostpath_mount | warning, info | the pod mounts a host path; warning when it is writable, info when read-only |
audit.default_sa_automount | warning | the pod runs as the namespace’s default ServiceAccount with its token automounted, and something in the pod can use it |
audit.podsecurity_gaps | warning | the namespace enforces no Pod Security Admission level, so none of the above is prevented |
Output fields
Section titled “Output fields”Beyond the shared envelope fields (kind, severity, namespace, kind_of_object, name, reason, message, fingerprint, exempt_reason, exempt_expires):
| Field | Meaning |
|---|---|
containers | containers implicated by the finding — those running privileged, or holding a node-root capability |
container_names | their names, capped at 8 with a +N more tail |
total_containers | containers in the pod template, init containers included, so containers reads as a fraction |
capabilities | the node-root capabilities added by those containers (ALL, SYS_ADMIN), sorted and deduplicated |
host_paths | hostPath volumes the template mounts; a declared but unmounted hostPath volume grants no access and is not counted |
host_path_names | the paths on the node, sorted and capped at 8 |
service_account | the ServiceAccount the finding is about — always default, the one every pod gets when its template names none |
mounting_workloads | workloads in the namespace running as the default ServiceAccount without disabling automount at the pod level; the finding does not fire at 0 |
mounting_workload_names | their Kind/name, sorted and capped at 8 |
pss_enforce | the namespace’s pod-security.kubernetes.io/enforce label, omitted when unset |
pss_warn | its /warn label, omitted when unset — set without /enforce means the namespace is in dry-run |
pss_audit | its /audit label, omitted when unset — same dry-run meaning |
workloads | pod templates this pass judged in the namespace, so an unenforced namespace with nothing in it reads differently from a busy one |
namespaces | summary note: namespaces examined — the denominator for every namespace-subject claim, which scanned (pod templates) does not cover |
Output contract
Section titled “Output contract”Output: one finding per line (logfmt; —format=json for one JSON object
per line), keys in fixed order; healthy resources emit nothing. The final
line is always the summary: scanned=
Examples
Section titled “Examples”lookout audit hardening -Alookout audit hardening --namespace=prodlookout audit hardening -A --exemptions=exemptions.yaml --format=json