container-forensics
Investigates containerized environments for signs of compromise, misconfiguration, or container escape. Covers standalone Docker hosts and Kubernetes clusters. Produces a structured findings document with severity tagging.
Triggers
Alternate expressions and non-obvious activations (primary phrases are matched automatically from the skill description):
- "Falco" / "Tetragon" / "Tracee" → eBPF runtime monitoring tools
- "dive" → Docker image layer analysis
- "crictl" → containerd/CRI-O environment forensics
- "escape" → container escape investigation
Purpose
Container environments introduce unique attack surfaces: privileged containers, host namespace access, writable image layers, and overpermissioned service accounts. Standard host forensics misses these vectors. This skill applies container-aware investigation procedures and maps findings to MITRE ATT&CK for Containers.
Behavior
When triggered, this skill:
Detect environment type:
- Check for Docker:
docker info 2>/dev/null
- Check for Kubernetes:
kubectl cluster-info 2>/dev/null or presence of /var/run/secrets/kubernetes.io/
- Check for containerd-only (no Docker):
ctr version 2>/dev/null
- Check for CRI-O or containerd via CRI:
crictl version 2>/dev/null
- Determine if running inside a container: check for
/.dockerenv, inspect cgroup paths
Container inventory and privilege audit:
- List all containers (running and stopped):
docker ps -a --format '{{json .}}'
- For containerd/CRI-O environments:
crictl pods and crictl ps -a
- Inspect individual containers:
crictl inspect <id> (equivalent of docker inspect)
- List images on CRI nodes:
crictl images and crictl inspecti <image-id>
- Pull container logs via CRI:
crictl logs <container-id>
- Flag containers with dangerous flags:
--privileged: docker inspect <id> | jq '.[].HostConfig.Privileged'
- Host network mode:
NetworkMode == "host"
- Host PID namespace:
PidMode == "host"
- Dangerous capability additions:
CapAdd containing SYS_ADMIN, NET_ADMIN, SYS_PTRACE
- Enumerate bind mounts of sensitive host paths (
/, /etc, /var/run/docker.sock, /proc, /sys)
Docker — image verification:
- List all local images with digests:
docker images --digests
- Check image provenance: compare
RepoDigests against expected registry
- Flag images tagged
latest without a pinned digest
- Inspect image build history for suspicious
RUN layers: docker history --no-trunc <image>
- Check for images not associated with any running or stopped container (orphaned images)
Image layer analysis with dive:
- Run
dive <image> --ci for non-interactive efficiency and layer summary
- Identify layers that delete files immediately after downloading them (evidence wiping pattern)
- Flag layers installing unexpected tooling (
curl, nc, nmap, socat, python)
- Identify unusually large layers inconsistent with the image's declared purpose
- Check for world-writable permissions set in later layers after a trusted base image
Docker — volume and filesystem inspection:
- List named volumes:
docker volume ls
- Inspect volumes mounted into containers for sensitive data paths
- Examine container overlay filesystem changes:
docker diff <container_id>
- Flag containers with writable root filesystems where
ReadonlyRootfs is false
Docker — socket and API exposure:
- Check if Docker socket is bind-mounted into any container — this grants effective root on the host
- Check for TCP Docker API exposure:
ss -tlnp | grep ':2375\|:2376'
- Review Docker daemon configuration:
/etc/docker/daemon.json
Container escape indicators:
- Processes running in container namespaces that share host PID/network: compare namespace inodes in
/proc/1/ns/ vs /proc/<container-pid>/ns/
- Unexpected cgroup escape patterns in
/proc/<pid>/cgroup
- Files written to host paths from within container overlay mounts
runc or containerd-shim process anomalies in host process tree
eBPF runtime monitoring:
- Check for Falco service and alert logs:
journalctl -u falco and /var/log/falco.log
- Review active Falco rules for coverage gaps (shell-in-container, outbound connections, writes below root)
- Collect Tetragon execution traces via
kubectl logs -n kube-system -l app.kubernetes.io/name=tetragon or tetra getevents
- Review active Tetragon
TracingPolicy resources: kubectl get tracingpolicies -A
- Collect Tracee event logs from container or systemd deployment
- If no eBPF tooling was active during the incident, document this gap in the findings
Kubernetes — cluster-level audit:
- List all pods across all namespaces:
kubectl get pods -A -o json
- Flag pods running as root:
.spec.containers[].securityContext.runAsUser == 0 or unset
- Flag pods with
hostPID, hostNetwork, or hostIPC set to true
- Flag pods mounting the Docker socket or host paths
- List privileged containers across the cluster
Kubernetes — RBAC audit:
- List ClusterRoleBindings granting
cluster-admin: kubectl get clusterrolebindings -o json | jq '...'
- Identify service accounts with wildcard permissions or
* verbs on sensitive resources
- Check for default service account token automounting:
automountServiceAccountToken: true
- List RoleBindings in high-value namespaces (kube-system, kube-public)
Kubernetes — pod security and network policy:
- Check for absent NetworkPolicies (pods with unrestricted egress/ingress)
- Review PodSecurityAdmission or OPA/Gatekeeper policy coverage
- List nodes and check for unauthorized node additions:
kubectl get nodes -o wide
etcd security audit (Kubernetes control-plane only):
- Verify etcd is not listening on a non-loopback address:
ps aux | grep etcd | grep listen-client-urls
- Confirm
--client-cert-auth=true is set in the etcd process flags
- Check for encryption-at-rest configuration in the API server manifest (
--encryption-provider-config)
- List etcd client certificates in
/etc/kubernetes/pki/etcd/ and flag any unexpected certs
- Take a read-only snapshot with
etcdctl snapshot save for offline analysis
- Enumerate etcd key paths for secrets and serviceaccount tokens using
etcdctl get / --prefix --keys-only
K8s API server audit log analysis (if audit logging is enabled):
- Locate audit log path from
kube-apiserver.yaml (--audit-log-path)
- Summarize request activity by user and verb to identify outliers
- Detect anonymous (
system:anonymous) API calls to non-public endpoints
- Flag ServiceAccount tokens used outside their home namespace
- Identify bulk
list/get on secrets resources (credential harvesting pattern)
- Flag
exec subresource calls from non-operator users during the incident window
- Detect rapid
create/delete sequences on the same resource (attacker covering tracks)
Write findings document:
- Save to
.aiwg/forensics/findings/container-forensics.md
- Group by: Docker/containerd findings, eBPF runtime events, Kubernetes findings, etcd/API server findings, escape indicators
- Tag each finding: INFO, SUSPICIOUS, MALICIOUS
Usage Examples
Example 1 — Docker host
docker investigation
Audits the local Docker daemon.
Example 2 — Kubernetes cluster
kubernetes forensics
Requires kubectl configured with appropriate credentials.
Example 3 — Inside a container
container forensics
Detects the container context and adjusts collection accordingly.
Output Locations
- Findings:
.aiwg/forensics/findings/container-forensics.md
- Raw Docker inspection:
.aiwg/forensics/evidence/docker-inspect.json
- crictl inspection output:
.aiwg/forensics/evidence/crictl-inspect.json
- K8s pod manifest dump:
.aiwg/forensics/evidence/k8s-pods.json
- Falco alert log:
.aiwg/forensics/evidence/falco-alerts.log
- Tetragon events:
.aiwg/forensics/evidence/tetragon-events.json
- Tracee events:
.aiwg/forensics/evidence/tracee-events.json
- etcd snapshot:
.aiwg/forensics/evidence/etcd-snapshot-<timestamp>.db
- K8s API server audit log (copy):
.aiwg/forensics/evidence/k8s-audit.log
Configuration
container_forensics:
dangerous_capabilities:
- SYS_ADMIN
- NET_ADMIN
- SYS_PTRACE
- SYS_MODULE
sensitive_host_paths:
- /
- /etc
- /var/run/docker.sock
- /proc
- /sys
- /root
high_value_namespaces:
- kube-system
- kube-public
- default
References
- @$AIWG_ROOT/agentic/code/addons/aiwg-utils/rules/research-before-decision.md — Detect environment type (Docker, containerd, Kubernetes) before applying collection procedures
- @$AIWG_ROOT/agentic/code/frameworks/forensics-complete/rules/non-destructive.md — Do not stop or remove containers until all artifacts are collected and hashed
- @$AIWG_ROOT/agentic/code/frameworks/forensics-complete/rules/red-flag-escalation.md — Escalate immediately when container escape, Docker socket exposure, or privileged escape is confirmed
- @$AIWG_ROOT/agentic/code/frameworks/forensics-complete/rules/evidence-integrity.md — Hash container logs and filesystem exports immediately after collection
- @$AIWG_ROOT/agentic/code/frameworks/forensics-complete/skills/linux-forensics/SKILL.md — Investigate the underlying host after container forensics; container escapes leave traces on the host
1---2namespace: aiwg3name: container-forensics4description: "Forensic investigation of Docker, containerd/CRI-O, and Kubernetes — inventory, escape detection, eBPF runtime monitoring, RBAC and etcd audit. Use when investigating container compromise."5tools: Bash, Read, Write, Glob, Grep6platforms: [all]78---910# container-forensics1112Investigates containerized environments for signs of compromise, misconfiguration, or container escape. Covers standalone Docker hosts and Kubernetes clusters. Produces a structured findings document with severity tagging.1314## Triggers151617Alternate expressions and non-obvious activations (primary phrases are matched automatically from the skill description):1819- "Falco" / "Tetragon" / "Tracee" → eBPF runtime monitoring tools20- "dive" → Docker image layer analysis21- "crictl" → containerd/CRI-O environment forensics22- "escape" → container escape investigation2324## Purpose2526Container environments introduce unique attack surfaces: privileged containers, host namespace access, writable image layers, and overpermissioned service accounts. Standard host forensics misses these vectors. This skill applies container-aware investigation procedures and maps findings to MITRE ATT&CK for Containers.2728## Behavior2930When triggered, this skill:31321. **Detect environment type**:33 - Check for Docker: `docker info 2>/dev/null`34 - Check for Kubernetes: `kubectl cluster-info 2>/dev/null` or presence of `/var/run/secrets/kubernetes.io/`35 - Check for containerd-only (no Docker): `ctr version 2>/dev/null`36 - Check for CRI-O or containerd via CRI: `crictl version 2>/dev/null`37 - Determine if running inside a container: check for `/.dockerenv`, inspect cgroup paths38392. **Container inventory and privilege audit**:40 - List all containers (running and stopped): `docker ps -a --format '{{json .}}'`41 - For containerd/CRI-O environments: `crictl pods` and `crictl ps -a`42 - Inspect individual containers: `crictl inspect <id>` (equivalent of `docker inspect`)43 - List images on CRI nodes: `crictl images` and `crictl inspecti <image-id>`44 - Pull container logs via CRI: `crictl logs <container-id>`45 - Flag containers with dangerous flags:46 - `--privileged`: `docker inspect <id> | jq '.[].HostConfig.Privileged'`47 - Host network mode: `NetworkMode == "host"`48 - Host PID namespace: `PidMode == "host"`49 - Dangerous capability additions: `CapAdd` containing `SYS_ADMIN`, `NET_ADMIN`, `SYS_PTRACE`50 - Enumerate bind mounts of sensitive host paths (`/`, `/etc`, `/var/run/docker.sock`, `/proc`, `/sys`)51523. **Docker — image verification**:53 - List all local images with digests: `docker images --digests`54 - Check image provenance: compare `RepoDigests` against expected registry55 - Flag images tagged `latest` without a pinned digest56 - Inspect image build history for suspicious `RUN` layers: `docker history --no-trunc <image>`57 - Check for images not associated with any running or stopped container (orphaned images)58594. **Image layer analysis with dive**:60 - Run `dive <image> --ci` for non-interactive efficiency and layer summary61 - Identify layers that delete files immediately after downloading them (evidence wiping pattern)62 - Flag layers installing unexpected tooling (`curl`, `nc`, `nmap`, `socat`, `python`)63 - Identify unusually large layers inconsistent with the image's declared purpose64 - Check for world-writable permissions set in later layers after a trusted base image65665. **Docker — volume and filesystem inspection**:67 - List named volumes: `docker volume ls`68 - Inspect volumes mounted into containers for sensitive data paths69 - Examine container overlay filesystem changes: `docker diff <container_id>`70 - Flag containers with writable root filesystems where `ReadonlyRootfs` is false71726. **Docker — socket and API exposure**:73 - Check if Docker socket is bind-mounted into any container — this grants effective root on the host74 - Check for TCP Docker API exposure: `ss -tlnp | grep ':2375\|:2376'`75 - Review Docker daemon configuration: `/etc/docker/daemon.json`76777. **Container escape indicators**:78 - Processes running in container namespaces that share host PID/network: compare namespace inodes in `/proc/1/ns/` vs `/proc/<container-pid>/ns/`79 - Unexpected cgroup escape patterns in `/proc/<pid>/cgroup`80 - Files written to host paths from within container overlay mounts81 - `runc` or `containerd-shim` process anomalies in host process tree82838. **eBPF runtime monitoring**:84 - Check for Falco service and alert logs: `journalctl -u falco` and `/var/log/falco.log`85 - Review active Falco rules for coverage gaps (shell-in-container, outbound connections, writes below root)86 - Collect Tetragon execution traces via `kubectl logs -n kube-system -l app.kubernetes.io/name=tetragon` or `tetra getevents`87 - Review active Tetragon `TracingPolicy` resources: `kubectl get tracingpolicies -A`88 - Collect Tracee event logs from container or systemd deployment89 - If no eBPF tooling was active during the incident, document this gap in the findings90919. **Kubernetes — cluster-level audit**:92 - List all pods across all namespaces: `kubectl get pods -A -o json`93 - Flag pods running as root: `.spec.containers[].securityContext.runAsUser == 0` or unset94 - Flag pods with `hostPID`, `hostNetwork`, or `hostIPC` set to true95 - Flag pods mounting the Docker socket or host paths96 - List privileged containers across the cluster979810. **Kubernetes — RBAC audit**:99 - List ClusterRoleBindings granting `cluster-admin`: `kubectl get clusterrolebindings -o json | jq '...'`100 - Identify service accounts with wildcard permissions or `*` verbs on sensitive resources101 - Check for default service account token automounting: `automountServiceAccountToken: true`102 - List RoleBindings in high-value namespaces (kube-system, kube-public)10310411. **Kubernetes — pod security and network policy**:105 - Check for absent NetworkPolicies (pods with unrestricted egress/ingress)106 - Review PodSecurityAdmission or OPA/Gatekeeper policy coverage107 - List nodes and check for unauthorized node additions: `kubectl get nodes -o wide`10810912. **etcd security audit** (Kubernetes control-plane only):110 - Verify etcd is not listening on a non-loopback address: `ps aux | grep etcd | grep listen-client-urls`111 - Confirm `--client-cert-auth=true` is set in the etcd process flags112 - Check for encryption-at-rest configuration in the API server manifest (`--encryption-provider-config`)113 - List etcd client certificates in `/etc/kubernetes/pki/etcd/` and flag any unexpected certs114 - Take a read-only snapshot with `etcdctl snapshot save` for offline analysis115 - Enumerate etcd key paths for secrets and serviceaccount tokens using `etcdctl get / --prefix --keys-only`11611713. **K8s API server audit log analysis** (if audit logging is enabled):118 - Locate audit log path from `kube-apiserver.yaml` (`--audit-log-path`)119 - Summarize request activity by user and verb to identify outliers120 - Detect anonymous (`system:anonymous`) API calls to non-public endpoints121 - Flag ServiceAccount tokens used outside their home namespace122 - Identify bulk `list`/`get` on `secrets` resources (credential harvesting pattern)123 - Flag `exec` subresource calls from non-operator users during the incident window124 - Detect rapid `create`/`delete` sequences on the same resource (attacker covering tracks)12512614. **Write findings document**:127 - Save to `.aiwg/forensics/findings/container-forensics.md`128 - Group by: Docker/containerd findings, eBPF runtime events, Kubernetes findings, etcd/API server findings, escape indicators129 - Tag each finding: INFO, SUSPICIOUS, MALICIOUS130131## Usage Examples132133### Example 1 — Docker host134```135docker investigation136```137Audits the local Docker daemon.138139### Example 2 — Kubernetes cluster140```141kubernetes forensics142```143Requires `kubectl` configured with appropriate credentials.144145### Example 3 — Inside a container146```147container forensics148```149Detects the container context and adjusts collection accordingly.150151## Output Locations152153- Findings: `.aiwg/forensics/findings/container-forensics.md`154- Raw Docker inspection: `.aiwg/forensics/evidence/docker-inspect.json`155- crictl inspection output: `.aiwg/forensics/evidence/crictl-inspect.json`156- K8s pod manifest dump: `.aiwg/forensics/evidence/k8s-pods.json`157- Falco alert log: `.aiwg/forensics/evidence/falco-alerts.log`158- Tetragon events: `.aiwg/forensics/evidence/tetragon-events.json`159- Tracee events: `.aiwg/forensics/evidence/tracee-events.json`160- etcd snapshot: `.aiwg/forensics/evidence/etcd-snapshot-<timestamp>.db`161- K8s API server audit log (copy): `.aiwg/forensics/evidence/k8s-audit.log`162163## Configuration164165```yaml166container_forensics:167 dangerous_capabilities:168 - SYS_ADMIN169 - NET_ADMIN170 - SYS_PTRACE171 - SYS_MODULE172 sensitive_host_paths:173 - /174 - /etc175 - /var/run/docker.sock176 - /proc177 - /sys178 - /root179 high_value_namespaces:180 - kube-system181 - kube-public182 - default183```184185## References186187- @$AIWG_ROOT/agentic/code/addons/aiwg-utils/rules/research-before-decision.md — Detect environment type (Docker, containerd, Kubernetes) before applying collection procedures188- @$AIWG_ROOT/agentic/code/frameworks/forensics-complete/rules/non-destructive.md — Do not stop or remove containers until all artifacts are collected and hashed189- @$AIWG_ROOT/agentic/code/frameworks/forensics-complete/rules/red-flag-escalation.md — Escalate immediately when container escape, Docker socket exposure, or privileged escape is confirmed190- @$AIWG_ROOT/agentic/code/frameworks/forensics-complete/rules/evidence-integrity.md — Hash container logs and filesystem exports immediately after collection191- @$AIWG_ROOT/agentic/code/frameworks/forensics-complete/skills/linux-forensics/SKILL.md — Investigate the underlying host after container forensics; container escapes leave traces on the host