Dockerfile Security Linter

Dockerfile Security & Best Practices Linter

Audit Dockerfiles for security risks (root execution, unpinned tags, hardcoded secrets) and performance bloat in real-time. 100% client-side privacy, zero server telemetry.

dockerfile linter onlinehadolint client webcis docker benchmark
F0/100
Security Score
Critical Pitfalls
17 findings require review
Critical & Errors
3
Root users, secrets, syntax
Warnings
5
Unpinned tags, cache bloat
Best Practices
9
Healthcheck, exec forms, ADD
Presets:
Detected Build Architecture (1 Stage - Single Stage)
⚠️ Single Stage
Stage 0: stage-0Final TargetL2
Base Image:node:latest
Pinned Tag:⚠️ Unpinned
User Security:Root (UID 0)
Dockerfile Editor(27 lines, 656 chars)
Live Linting
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
Quick Snippets:
Audit Findings17 of 17
errorDL3002security

Container Executes as Root User (UID 0)

The final production image does not specify a non-root USER instruction.

L2:Stage: stage-0 (node)
Why this matters:Containers that run as root share UID 0 with the host Linux kernel. Any remote code execution in your app grants immediate root access inside the container environment.
Recommended Remediation:
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
USER appuser
errorSYNTAX-001syntax

Unknown Instruction 'MAINTAINER'

Unknown Dockerfile instruction 'MAINTAINER'. Verify spelling.

L4:MAINTAINER [email protected]
Why this matters:Docker daemon will fail the build with a parser syntax error.
errorDL4001security

Insecure Remote Script Piped to Shell

Piping curl or wget directly into shell ('curl ... | bash') is unsafe.

L18:RUN curl -fsSL https://deb.nodesource.com/setup_20.x | bash -
Why this matters:Remote scripts executed without cryptographic hash validation are susceptible to MitM tampering and supply-chain hijack.
Recommended Remediation:
# Download script, verify SHA256 checksum, then execute
warningDL3007security

Using ':latest' Base Image Tag 'node:latest'

Avoid using ':latest' tag for base images in production Dockerfiles.

L2:FROM node:latest
Why this matters:The latest tag changes without notice, risking sudden build breaks or untested upstream security changes.
Recommended Remediation:
FROM node:<exact-version>
warningPERF-MULTIperformance

Multi-Stage Build Opportunity Detected

Build toolchains and compilers detected inside a single-stage Dockerfile.

L2:FROM node
Why this matters:Single-stage builds bundle compiler tools, SDKs, and build caches directly into the production container image, inflating size by hundreds of megabytes.
Recommended Remediation:
# Convert to multi-stage: FROM base AS builder ... FROM runtime ... COPY --from=builder
warningDL3000best-practice

Relative WORKDIR Path 'app'

Use absolute paths for WORKDIR instructions.

L10:WORKDIR app
Why this matters:Relative WORKDIR paths can lead to unintended directory hierarchies and make the Dockerfile difficult to maintain.
Recommended Remediation:
WORKDIR /app
warningDL3009performance

Standalone 'apt-get update' Instruction

'apt-get update' should be chained in the same RUN layer with 'apt-get install'.

L16:RUN apt-get update
Why this matters:Caching standalone update layers causes subsequent install layers to use outdated package lists.
warningDL3008performance

Apt Package Cache Not Cleaned Up

Delete package lists ('rm -rf /var/lib/apt/lists/*') after apt-get install.

L17:RUN apt-get install -y curl git python3
Why this matters:Uncleaned package lists stay in image layers, inflating image size by dozens of megabytes.
Recommended Remediation:
RUN apt-get install -y curl git python3 && rm -rf /var/lib/apt/lists/*
infoCIS-4.6best-practice

Missing HEALTHCHECK Instruction in Final Stage

No HEALTHCHECK instruction defined for container health monitoring.

L2:Stage: stage-0
Why this matters:Container orchestrators (Docker Swarm, Kubernetes, AWS ECS) use HEALTHCHECK to detect hung application processes and restart containers automatically.
Recommended Remediation:
HEALTHCHECK --interval=30s --timeout=5s --start-period=5s --retries=3 \
  CMD curl -f http://localhost:8080/health || exit 1
infoDL3020best-practice

Use COPY Instead of ADD for Local Files

Prefer 'COPY' over 'ADD' when copying local files or folders.

L13:ADD . .
Why this matters:ADD has unexpected archive auto-extraction and remote URL fetching behaviors. COPY is explicit and safer.
Recommended Remediation:
COPY . .
infoDL3015performance

Missing '--no-install-recommends' in apt-get

Add '--no-install-recommends' to prevent installing non-essential packages.

L17:RUN apt-get install -y curl git python3
Why this matters:Avoids installing desktop dependencies, man pages, and extraneous documentation in headless containers.
Recommended Remediation:
RUN apt-get install -y --no-install-recommends -y curl git python3
infoDL3059performance

Multiple Consecutive RUN Instructions

Consolidate consecutive RUN instructions using '&& \' to reduce image layers.

L17:RUN apt-get install -y curl git python3
Why this matters:Each RUN instruction creates a separate layer in the Docker storage driver, increasing image size and metadata overhead.
infoDL4006best-practice

Piped Command Without Shell 'pipefail' Option

Pipes in RUN instructions should enable pipefail.

L18:RUN curl -fsSL https://deb.nodesource.com/setup_20.x | bash -
Why this matters:By default, shell returns the status of the last piped command. If the left command fails, the layer may erroneously succeed.
Recommended Remediation:
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
infoDL3059performance

Multiple Consecutive RUN Instructions

Consolidate consecutive RUN instructions using '&& \' to reduce image layers.

L18:RUN curl -fsSL https://deb.nodesource.com/setup_20.x | bash -
Why this matters:Each RUN instruction creates a separate layer in the Docker storage driver, increasing image size and metadata overhead.
infoDL3059performance

Multiple Consecutive RUN Instructions

Consolidate consecutive RUN instructions using '&& \' to reduce image layers.

L20:RUN npm install
Why this matters:Each RUN instruction creates a separate layer in the Docker storage driver, increasing image size and metadata overhead.
infoSEC-003best-practice

Privileged Port (< 1024) Exposed

Port '80' is below 1024, requiring root privileges to bind.

L23:EXPOSE 80
Why this matters:Prefer unprivileged ports (e.g. 8080 or 3000) so non-root users can bind without CAP_NET_BIND_SERVICE.
infoBEST-001best-practice

Shell Form Used for CMD Instruction

Use JSON exec array format for CMD instead of shell form.

L26:CMD npm start
Why this matters:Shell form launches via '/bin/sh -c' as PID 1, preventing graceful POSIX SIGTERM signal forwarding during shutdown.
Recommended Remediation:
CMD ["npm","start"]

Export Dockerfile & CI/CD Audit Report

Download hardened configurations or copy standard Markdown reports for PR comments and security audits.

Dockerfile Security & Best Practices Guide (FAQ)

Essential container security concepts, Hadolint rules, CIS Docker Benchmarks, and multi-stage build optimizations.

Why is running containers as root (UID 0) hazardous?

By default, Docker containers execute processes under the root user. If an attacker exploits an application vulnerability (e.g. remote code execution or path traversal), they gain root privileges inside the container. Combined with any Linux kernel vulnerability or mounted volumes, this enables complete host system compromise. Always declare an unprivileged USER appuser before your CMD or ENTRYPOINT.

What is a multi-stage build and how does it shrink images?

Multi-stage builds allow you to use multiple FROM instructions in a single Dockerfile. You can compile your application in a heavy builder stage containing Node.js, Go, or Maven toolchains, and then copy only the finalized compiled binaries into an ultra-lean runtime image (such as Alpine or Distroless). This reduces final container sizes from 1GB+ down to under 50MB and eliminates compiler attack surface.

Why must you avoid ':latest' or unpinned base tags?

The :latest tag is a moving target that updates upstream whenever upstream publishers push a new version. Builds performed on different days or by different developers can yield divergent runtime environments, breaking deterministic builds and introducing untested zero-day vulnerabilities silently into your production pipeline. Always pin exact semantic versions or SHA256 digest hashes.

How does ToolsAA protect proprietary Dockerfiles?

In strict accordance with our Privacy First Architecture, ToolsAA computes all Dockerfile AST parsing, Hadolint rule matching, and score evaluations 100% inside your local web browser via modern Web APIs. No code, tokens, or Dockerfiles are ever uploaded or transmitted to any external server or telemetry service.

What is the difference between shell form and exec form?

Writing CMD npm start uses shell form, which executes as /bin/sh -c as PID 1. The shell does not forward POSIX signals like SIGTERM to your node application, causing Docker to wait 10 seconds before forcibly issuing SIGKILL. Using JSON exec form CMD ["npm", "start"] runs the process directly as PID 1 for graceful zero-downtime terminations.

How should credentials and secrets be managed in builds?

Never declare secrets in ENV or ARG instructions. Even if you attempt to delete them in later layers, previous layer history retains the secret unencrypted. Use Docker BuildKit secret mounts (RUN --mount=type=secret,id=mysecret ...) which mount credentials in temporary memory during compilation without persisting them to layer cache.