Build Image on Host
This detection identifies adversaries building custom container images directly on a compromised host to evade registry-based defenses. Rather than pulling a pre-built malicious image — which would trigger image scanning alerts — attackers issue docker build commands referencing Dockerfiles that download malware or backdoors at build time using RUN curl/wget instructions. The detection monitors for docker build process execution with suspicious argument patterns (temporary directory Dockerfiles, no-cache flags, external URL fetches), Dockerfile creation in writable system directories, and Docker daemon network connections to unexpected destinations during image construction. Correlation across process telemetry, file events, and network activity surfaces the build-then-deploy attack chain used by groups like TeamTNT and WatchDog cryptomining campaigns.
What is T1612 Build Image on Host?
Build Image on Host (T1612) maps to the Defense Evasion tactic — the adversary is trying to avoid being detected in MITRE ATT&CK.
This page provides production-ready detection logic for Build Image on Host, covering the data sources and telemetry it touches: Microsoft Defender for Endpoint. The queries below are rated high severity at medium confidence, and ship for 7 SIEM platforms — KQL, SPL, Elastic, QRadar, Sumo, YARA-L, LogScale.
MITRE ATT&CK
- Tactic
- Defense Evasion
- Technique
- T1612 Build Image on Host
- Canonical reference
- https://attack.mitre.org/techniques/T1612/
let TimeWindow = 1d;
let TempPaths = dynamic(["/tmp/", "/dev/shm/", "/var/tmp/", "/run/user/", "\\Temp\\", "\\AppData\\Local\\Temp\\"]);
let SuspiciousParents = dynamic(["bash", "sh", "zsh", "python", "python3", "perl", "ruby", "curl", "wget"]);
// Detect suspicious docker build executions
let DockerBuilds = DeviceProcessEvents
| where TimeGenerated > ago(TimeWindow)
| where (FileName =~ "docker" or FileName =~ "docker.exe")
and ProcessCommandLine has_any ("build", "image build")
| extend BuildFromTemp = ProcessCommandLine has_any (TempPaths)
| extend BuildNoCache = ProcessCommandLine has "--no-cache"
| extend BuildExternalFile = ProcessCommandLine matches regex @"-f\s+https?://"
| extend SuspiciousParentProc = InitiatingProcessFileName has_any (SuspiciousParents)
| extend RiskScore = toint(BuildFromTemp) * 3
+ toint(BuildNoCache) * 1
+ toint(BuildExternalFile) * 4
+ toint(SuspiciousParentProc) * 2
| where RiskScore >= 2
| project TimeGenerated, DeviceName, AccountName, AccountDomain,
ProcessCommandLine, InitiatingProcessCommandLine, InitiatingProcessFileName,
BuildFromTemp, BuildNoCache, BuildExternalFile, SuspiciousParentProc, RiskScore;
// Detect Dockerfile written to suspicious locations
let SuspiciousDockerfiles = DeviceFileEvents
| where TimeGenerated > ago(TimeWindow)
| where (FileName =~ "Dockerfile" or FileName endswith ".dockerfile" or FileName endswith ".Dockerfile")
and FolderPath has_any (TempPaths)
| extend RiskScore = 3
| project TimeGenerated, DeviceName, AccountName, FolderPath, FileName,
InitiatingProcessCommandLine, RiskScore;
// Detect docker daemon making external connections during potential build phase
let DockerNetworkBuild = DeviceNetworkEvents
| where TimeGenerated > ago(TimeWindow)
| where InitiatingProcessFileName =~ "dockerd"
and RemotePort in (80, 443, 8080, 8443)
and not(ipv4_is_private(RemoteIP))
and not(RemoteUrl has_any ("docker.io", "hub.docker.com", "registry-1.docker.io",
"production.cloudflare.docker.com", "auth.docker.io",
"registry.k8s.io", "gcr.io", "mcr.microsoft.com",
"quay.io", "ghcr.io"))
| extend RiskScore = 2
| project TimeGenerated, DeviceName, RemoteIP, RemoteUrl, RemotePort,
InitiatingProcessCommandLine, RiskScore;
// Union all findings
DockerBuilds
| project TimeGenerated, DeviceName, AccountName, Description = "Suspicious docker build execution",
Detail = ProcessCommandLine, RiskScore
| union (
SuspiciousDockerfiles
| project TimeGenerated, DeviceName, AccountName, Description = "Dockerfile written to temp path",
Detail = strcat(FolderPath, FileName), RiskScore
)
| union (
DockerNetworkBuild
| project TimeGenerated, DeviceName, AccountName = "", Description = "Docker daemon external connection during build",
Detail = strcat(RemoteIP, " (", RemoteUrl, "):", tostring(RemotePort)), RiskScore
)
| order by TimeGenerated desc Detects suspicious container image builds on the host by monitoring docker build process executions with high-risk argument patterns (Dockerfiles from temp directories, external file references, no-cache flags combined with suspicious parent processes), Dockerfile creation in writable system paths, and Docker daemon making network connections to non-registry external hosts during what may be a build phase. Risk scoring prioritizes combinations most consistent with adversary build-to-deploy workflows.
Data Sources
Required Tables
False Positives
- Legitimate CI/CD pipeline agents (Jenkins, GitLab Runner, GitHub Actions self-hosted) that build images on the host using --no-cache for reproducibility
- Developer workstations with Docker Desktop where developers routinely build images from ~/Downloads or temp directories during testing
- Container security scanning tools (Trivy, Grype, Snyk) that build test images from temporary Dockerfiles to verify vulnerability detection coverage
- Infrastructure-as-code tools like Packer or Terraform using Docker builder that create Dockerfiles in temp locations as part of their workflow
Sigma rule & cross-platform mapping
The detection logic for Build Image on Host (T1612) above is provided in a vendor-neutral
form so you can deploy it on any SIEM. The same logic is shipped here as native
KQL (Microsoft Sentinel / Defender), SPL (Splunk), Elastic (Elastic Security (EQL)), QRadar (IBM QRadar (AQL)), Sumo (Sumo Logic CSE), YARA-L (Google Chronicle / SecOps), LogScale (CrowdStrike LogScale (CQL)) queries. In Sigma terms, this detection targets the
following logsource:
logsource:
category: process_creation
product: windows Browse the community-maintained Sigma rules for this technique:
Platform-specific guides for T1612
Testing Methodology
Validate this detection against 3 adversary techniques from Atomic Red Team. Each test below lists the behaviour to exercise and the telemetry you should expect to see. Executable commands and cleanup steps are available with Pro.
- Test 1Build Custom Image with Embedded Payload Simulation
Expected signal: DeviceProcessEvents: FileName=docker, ProcessCommandLine contains 'build --no-cache -t atomictest_t1612' and '/tmp/atomictest_t1612/Dockerfile'. DeviceNetworkEvents: dockerd process making connection to example.com:443 during RUN curl step.
- Test 2Docker API Remote Build Request Simulation
Expected signal: Auditd: access to /var/run/docker.sock by curl process. Docker daemon logs (journalctl -u docker): POST /v1.43/build request logged. DeviceProcessEvents may not show docker CLI — hunting via socket access rules is required for API-based builds.
- Test 3Build Privileged Escape-Ready Container Image
Expected signal: DeviceProcessEvents: docker run with ProcessCommandLine containing '-v /var/run/docker.sock:/var/run/docker.sock'. Sysmon EventCode 11: file access to /var/run/docker.sock from container process namespace.
Response Playbook
Triage
- Step 1: Identify the exact docker build command — retrieve the full ProcessCommandLine or CommandLine field. Extract the Dockerfile path (-f flag) or confirm a local Dockerfile was used. If the Dockerfile path references /tmp, /dev/shm, or an HTTP/HTTPS URL, escalate priority immediately.
- Step 2: Retrieve the Dockerfile contents. On the host, run: cat <dockerfile_path> and inspect for RUN curl, RUN wget, ADD http://, RUN bash -i, RUN chmod +s, or any instruction that fetches external payloads. Note any C2-like domains or IPs in fetch commands.
- Step 3: Determine the image tag built (-t flag). Run docker images --format '{{.Repository}}:{{.Tag}} {{.CreatedAt}} {{.ID}}' to identify recently created images. Correlate image creation timestamp with the suspicious build event.
- Step 4: Check if the built image was subsequently deployed. Query DeviceProcessEvents for docker run commands referencing the same image tag within 30 minutes of the build. Also check for docker create, docker start, or kubectl create with matching image hashes.
- Step 5: Examine the parent process of the docker build command. If launched by curl, wget, bash -c, python -c, or a cron job, identify the full execution chain by pivoting on InitiatingProcessId to reconstruct the kill chain.
- Step 6: Review Docker daemon logs for the build session. On the host: journalctl -u docker --since '30 min ago' | grep -E '(build|Sending build context|Step [0-9]+|RUN|Successfully built)'. Note any external fetch attempts logged during build steps.
- Step 7: Check for Docker API exposure. Verify whether the Docker socket (/var/run/docker.sock) is accessible from containers or via TCP (docker -H tcp://0.0.0.0:2375). An exposed API is a critical finding indicating broader compromise vector.
Containment
- If malicious image confirmed: immediately stop any running containers based on it — docker ps -q --filter ancestor=<image_id> | xargs docker stop — then remove the image with docker rmi <image_id> --force.
- If Docker API is exposed over TCP (port 2375/2376): block the port at the host firewall immediately using iptables -I INPUT -p tcp --dport 2375 -j DROP, then coordinate with the host owner to restrict API access to Unix socket only.
- Isolate the host from the network if the docker build pulled from or pushed to an unknown external IP/domain. Initiate EDR-level network isolation via your endpoint management platform while preserving disk state for forensics.
- Revoke any credentials or tokens that were present in environment variables, mounted secrets, or the Docker build context (--build-arg secrets are captured in image layers — verify with docker history <image_id> --no-trunc).
- If the compromised build was part of a CI/CD pipeline: suspend the pipeline job, rotate the service account credentials used by the runner, and audit all images built by that runner in the preceding 72 hours.
Evidence Collection
- Capture the full Dockerfile used in the build: copy from the path specified in the build command or from /var/lib/docker/tmp/ before it is cleaned up.
- Export Docker image layers for forensic analysis: docker save <image_id> -o /evidence/malicious_image.tar. Examine layers with: tar -xf malicious_image.tar && for layer in */layer.tar; do tar -tf $layer; done to enumerate all files added.
- Collect Docker daemon logs: journalctl -u docker -n 5000 --no-pager > /evidence/docker_daemon.log. Include timestamps bracketing the build event.
- Capture process execution telemetry from EDR covering the 10-minute window before and after the docker build event — specifically parent/child process trees showing how the build was triggered.
- Preserve network flow logs (NetFlow, VPC flow logs, or firewall logs) for the Docker host's IP for the duration of the build — typically seconds to minutes — to identify all external IPs contacted during the RUN instruction phase.
- Extract container runtime artifacts: docker inspect <container_id> for any spawned containers, and collect /proc/<container_pid>/net/tcp for active network connections at time of isolation.
Escalation Criteria
- ! Escalate immediately if the Dockerfile or build logs show fetching payloads from a known malicious IP or domain (cross-reference against threat intelligence feeds).
- ! Escalate if docker run or container deployment of the newly built image is detected within 30 minutes of build completion — this confirms active T1610 Deploy Container follow-on activity.
- ! Escalate if the Docker API was accessed remotely (non-localhost source IP on port 2375/2376/2377) — this indicates external attacker-controlled infrastructure issuing the build request.
- ! Escalate if the built image is tagged to mimic a legitimate base image (alpine:latest, ubuntu:20.04, nginx:stable) to facilitate blend-in persistence.
- ! Escalate if the docker build was triggered by a cron job, systemd timer, or web application process — indicates established persistence or RCE being leveraged to repeatedly rebuild malicious images.
Investigation Guide
Forensic Artifacts
- >
/var/lib/docker/overlay2/ — layer directories containing filesystem changes introduced by each Dockerfile instruction including downloaded malware - >
/var/lib/docker/image/overlay2/imagedb/ — image metadata JSON files recording build history, layer hashes, and environment variables - >
docker history <image_id> --no-trunc — command history showing all RUN instructions executed during build, including malicious fetch commands - >
/tmp/docker-builder<random>/ or /var/lib/docker/tmp/ — temporary build context directories, may persist briefly after build completion - >
Docker daemon log via journald: journalctl -u docker — records API calls, build initiation, layer creation, and network fetches during build - >
/proc/<dockerd_pid>/net/tcp and /proc/<dockerd_pid>/net/tcp6 — active network connections from daemon process at time of investigation - >
auditd logs with -w /var/run/docker.sock -p rwxa — captures all processes accessing the Docker socket, revealing how the build was triggered - >
Container runtime shim process tree in /proc/ — short-lived runc/containerd-shim processes spawned per build step can be captured if monitoring is real-time
Tuning Guidance
Begin by baselining legitimate build activity per host: CI/CD runners (Jenkins agents, GitLab runners, GitHub Actions self-hosted) will generate high-volume docker build events that are expected. Create allow-list rules for known CI/CD service accounts and their typical build paths (e.g., /home/jenkins/workspace/, /opt/gitlab-runner/). For the Dockerfile-in-temp-path signal, exclude paths that your build tooling legitimately uses (Packer stages Dockerfiles in temp directories by design). For the Docker daemon network connection hunt, maintain a registry allow-list specific to your environment including any private registries (Harbor, ECR, ACR, Nexus). The build-then-deploy hunting query is highest fidelity in environments where builds are always separated from deployments by a pipeline stage — in developer workstations where devs regularly build and immediately test, tune the MinutesUntilDeploy threshold down to under 5 minutes to reduce noise. Disable monitoring on known container build servers entirely in favor of only alerting on unexpected hosts (servers, databases, application nodes) executing docker build commands.
Hunting Queries
Hunts for the build-then-deploy pattern where a locally built image is run within 30 minutes of creation — a strong indicator of adversary T1612 followed by T1610 activity.
// Hunt for docker builds that immediately result in container deployment (build-then-run pattern)
let BuildEvents = DeviceProcessEvents
| where TimeGenerated > ago(7d)
| where FileName =~ "docker" and ProcessCommandLine has "build"
| extend ImageTag = extract(@"-t\s+([\w./_:@-]+)", 1, ProcessCommandLine)
| where isnotempty(ImageTag)
| project BuildTime = TimeGenerated, DeviceName, AccountName, ImageTag, BuildCommandLine = ProcessCommandLine;
let RunEvents = DeviceProcessEvents
| where TimeGenerated > ago(7d)
| where FileName =~ "docker" and ProcessCommandLine has_any ("run", "create", "start")
| extend ImageTag = extract(@"docker\s+(?:run|create)\s+(?:[\s\S]*?)\s+([\w./_:@-]+)", 1, ProcessCommandLine)
| where isnotempty(ImageTag)
| project RunTime = TimeGenerated, DeviceName, RunCommandLine = ProcessCommandLine, ImageTag;
BuildEvents
| join kind=inner RunEvents on DeviceName, ImageTag
| where RunTime > BuildTime and RunTime < datetime_add('minute', 30, BuildTime)
| extend MinutesUntilDeploy = datetime_diff('minute', RunTime, BuildTime)
| project BuildTime, RunTime, MinutesUntilDeploy, DeviceName, AccountName, ImageTag, BuildCommandLine, RunCommandLine
| order by MinutesUntilDeploy asc index=* sourcetype="XmlWinEventLog:Microsoft-Windows-Sysmon/Operational" EventCode=1
| search CommandLine="*docker*build*"
| rex field=CommandLine "-t\s+(?P<image_tag>[\w./_:@-]+)"
| where isnotnull(image_tag)
| eval build_time=_time
| rename host as build_host
| eval event_type="build"
| append [
search index=* sourcetype="XmlWinEventLog:Microsoft-Windows-Sysmon/Operational" EventCode=1
| search CommandLine="*docker*run*" OR CommandLine="*docker*create*"
| rex field=CommandLine "docker\s+(?:run|create)\s+[\s\S]*?\s+(?P<image_tag>[\w./_:@-]+)"
| where isnotnull(image_tag)
| eval event_type="deploy"
| rename host as build_host
]
| sort build_host, image_tag, _time
| streamstats window=2 current=t values(event_type) as event_seq by build_host, image_tag
| where event_seq="build deploy" OR event_seq="deploy build"
| table _time, build_host, image_tag, CommandLine, event_type Hunts for Docker daemon making outbound connections to non-standard registries or unknown external hosts, which may indicate Dockerfile RUN instructions fetching payloads from attacker-controlled C2 infrastructure.
// Hunt for Docker daemon making connections to non-standard registries or C2 infrastructure
DeviceNetworkEvents
| where TimeGenerated > ago(7d)
| where InitiatingProcessFileName =~ "dockerd"
| where not(ipv4_is_private(RemoteIP))
| where RemotePort in (80, 443, 8080, 8443, 4444, 1337, 9001)
| extend KnownRegistry = RemoteUrl has_any (
"docker.io", "hub.docker.com", "registry-1.docker.io", "auth.docker.io",
"production.cloudflare.docker.com", "registry.k8s.io", "gcr.io",
"mcr.microsoft.com", "quay.io", "ghcr.io", "amazonaws.com",
"azurecr.io", "pkg.dev"
)
| where not(KnownRegistry)
| summarize
ConnectionCount = count(),
BytesSent = sum(SentBytes),
BytesReceived = sum(ReceivedBytes),
Ports = make_set(RemotePort),
FirstSeen = min(TimeGenerated),
LastSeen = max(TimeGenerated)
by DeviceName, RemoteIP, RemoteUrl
| where ConnectionCount >= 1
| extend SuspicionScore = case(
RemotePort in (Ports, dynamic([4444, 1337, 9001])), 4,
BytesSent > 1048576, 3,
ConnectionCount > 5, 2,
true(), 1)
| order by SuspicionScore desc, ConnectionCount desc index=* sourcetype="linux_secure" OR sourcetype="syslog"
| search "dockerd" ("connect" OR "GET" OR "POST" OR "curl" OR "wget")
| rex field=_raw "(?P<remote_host>(?:[0-9]{1,3}\.){3}[0-9]{1,3}|(?:[a-zA-Z0-9-]+\.)+[a-zA-Z]{2,})"
| where isnotnull(remote_host)
| eval is_known_registry=if(match(remote_host, "(docker\.io|hub\.docker\.com|registry-1\.docker\.io|gcr\.io|mcr\.microsoft\.com|quay\.io|ghcr\.io|amazonaws\.com|azurecr\.io)"), 1, 0)
| where is_known_registry=0
| stats count as connection_count, dc(remote_host) as unique_hosts, values(remote_host) as contacted_hosts by host
| where connection_count >= 2
| sort -connection_count Hunts for container build or run commands using flags that enable container escape to the host (--privileged, --pid=host, Docker socket mounts, host filesystem mounts) — adversaries building malicious images often embed these flags in automated deployment scripts.
// Hunt for privileged or dangerous build flags that enable container escape post-build
DeviceProcessEvents
| where TimeGenerated > ago(7d)
| where FileName =~ "docker"
| where ProcessCommandLine has_any ("build", "run", "create")
| extend HasPrivileged = ProcessCommandLine has "--privileged"
| extend HasHostPID = ProcessCommandLine has "--pid=host" or ProcessCommandLine has "--pid host"
| extend HasHostNet = ProcessCommandLine has "--network=host" or ProcessCommandLine has "--network host"
| extend HasSocketMount = ProcessCommandLine has "/var/run/docker.sock"
| extend HasHostMount = ProcessCommandLine matches regex @"-v\s+/[a-z]+:/" and not(ProcessCommandLine has "/var/lib/docker")
| extend HasCapAdd = ProcessCommandLine has "--cap-add"
| extend EscapeRiskScore = toint(HasPrivileged) * 5
+ toint(HasHostPID) * 4
+ toint(HasSocketMount) * 5
+ toint(HasHostMount) * 3
+ toint(HasHostNet) * 2
+ toint(HasCapAdd) * 2
| where EscapeRiskScore >= 3
| project TimeGenerated, DeviceName, AccountName, ProcessCommandLine,
HasPrivileged, HasHostPID, HasSocketMount, HasHostMount, HasCapAdd, EscapeRiskScore
| order by EscapeRiskScore desc, TimeGenerated desc index=* (sourcetype="XmlWinEventLog:Microsoft-Windows-Sysmon/Operational" EventCode=1 OR sourcetype="auditd")
| search "docker" ("build" OR "run" OR "create")
| eval CommandLine=coalesce(CommandLine, msg)
| eval has_privileged=if(match(CommandLine, "--privileged"), 1, 0)
| eval has_host_pid=if(match(CommandLine, "--pid[=\s]host"), 1, 0)
| eval has_socket_mount=if(match(CommandLine, "/var/run/docker\.sock"), 1, 0)
| eval has_host_mount=if(match(CommandLine, "-v\s+/[a-z]+:/") AND NOT match(CommandLine, "/var/lib/docker"), 1, 0)
| eval has_cap_add=if(match(CommandLine, "--cap-add"), 1, 0)
| eval escape_risk=has_privileged*5 + has_host_pid*4 + has_socket_mount*5 + has_host_mount*3 + has_cap_add*2
| where escape_risk >= 3
| table _time, host, user, CommandLine, has_privileged, has_host_pid, has_socket_mount, has_host_mount, escape_risk
| sort -escape_risk, -_time Atomic Red Team Tests
Simulates an adversary building a container image on the host that downloads a benign payload during the build process to mimic malware staging via Dockerfile RUN instructions. Tests detection of docker build from /tmp with --no-cache and external fetch.
Command
# Create a simulated malicious Dockerfile in /tmp
mkdir -p /tmp/atomictest_t1612
cat > /tmp/atomictest_t1612/Dockerfile << 'EOF'
FROM alpine:latest
RUN apk add --no-cache curl
RUN curl -s https://example.com/robots.txt -o /tmp/payload_simulation.txt
RUN echo 'build_complete' > /tmp/build_marker
EOF
# Build the image — this is the key telemetry-generating event
docker build --no-cache -t atomictest_t1612:latest -f /tmp/atomictest_t1612/Dockerfile /tmp/atomictest_t1612/
echo 'Build completed. Check for docker build process event with /tmp path and --no-cache flag.' Cleanup
docker rmi atomictest_t1612:latest --force 2>/dev/null; rm -rf /tmp/atomictest_t1612/ Expected Telemetry
DeviceProcessEvents: FileName=docker, ProcessCommandLine contains 'build --no-cache -t atomictest_t1612' and '/tmp/atomictest_t1612/Dockerfile'. DeviceNetworkEvents: dockerd process making connection to example.com:443 during RUN curl step.
Expected Detection
KQL query should fire with RiskScore >= 3 (BuildFromTemp=true score 3 + BuildNoCache=true score 1 = 4). SPL query should match with risk_score=4 and alert_detail='HIGH: Build from temp path launched by shell/script'.
Simulates an adversary sending a docker build request directly to the Docker API endpoint (as TeamTNT and WatchDog do when they find exposed Docker sockets), bypassing CLI tooling and creating API-level telemetry.
Command
# Create build context archive for API-based build
mkdir -p /tmp/atomictest_t1612_api
cat > /tmp/atomictest_t1612_api/Dockerfile << 'EOF'
FROM busybox:latest
RUN echo 'api_build_simulation' > /tmp/api_test_marker
EOF
cd /tmp/atomictest_t1612_api && tar -czf /tmp/build_context.tar.gz Dockerfile
# Submit build via Docker API (simulates remote attacker using exposed socket/API)
# This generates dockerd telemetry rather than docker CLI process events
curl -s --unix-socket /var/run/docker.sock \
-X POST \
-H 'Content-Type: application/x-tar' \
--data-binary @/tmp/build_context.tar.gz \
'http://localhost/v1.43/build?t=atomictest_api_t1612:latest&nocache=true' \
| python3 -m json.tool 2>/dev/null | grep -E '(stream|error|aux)' | head -20
echo 'API build submitted. Check Docker daemon logs and socket access telemetry.' Cleanup
docker rmi atomictest_api_t1612:latest --force 2>/dev/null; rm -rf /tmp/atomictest_t1612_api/ /tmp/build_context.tar.gz Expected Telemetry
Auditd: access to /var/run/docker.sock by curl process. Docker daemon logs (journalctl -u docker): POST /v1.43/build request logged. DeviceProcessEvents may not show docker CLI — hunting via socket access rules is required for API-based builds.
Expected Detection
Primary detection via auditd /var/run/docker.sock watch rule. Docker daemon network connection hunt should fire if the Dockerfile triggers any external fetch. NOTE: Docker CLI-based detections will NOT fire for API-direct builds — this test validates the need for socket-level monitoring.
Simulates building and running a container with dangerous flags (--privileged, Docker socket mount) that would enable container escape — a common follow-on after T1612 adversary image construction. Tests the escape risk hunting query.
Command
# Build a minimal 'escape-ready' image locally
mkdir -p /tmp/atomictest_t1612_escape
cat > /tmp/atomictest_t1612_escape/Dockerfile << 'EOF'
FROM alpine:latest
RUN apk add --no-cache bash
CMD ["/bin/sh"]
EOF
docker build -t atomictest_escape_t1612:latest /tmp/atomictest_t1612_escape/
# Run the image with socket mount (simulates adversary enabling Docker-in-Docker for escape)
# Container exits immediately due to --rm and no interactive TTY
docker run --rm \
-v /var/run/docker.sock:/var/run/docker.sock \
atomictest_escape_t1612:latest \
/bin/sh -c 'ls /var/run/docker.sock && echo escape_vector_validated'
echo 'Privileged run completed. Check for --privileged or socket-mount docker run events.' Cleanup
docker rmi atomictest_escape_t1612:latest --force 2>/dev/null; rm -rf /tmp/atomictest_t1612_escape/ Expected Telemetry
DeviceProcessEvents: docker run with ProcessCommandLine containing '-v /var/run/docker.sock:/var/run/docker.sock'. Sysmon EventCode 11: file access to /var/run/docker.sock from container process namespace.
Expected Detection
Escape risk hunting query should fire with escape_risk=5 (HasSocketMount=true). EDR should surface the docker run command with socket mount flag in process telemetry.