CodePark/ questions / Scanning, containers & least privilege
START PRACTICINGPRACTICE
Backend question · Auth & security › Scanning, containers & least privilege

Review this Dockerfile for security problems.

FROM node:latest
WORKDIR /app
COPY . .
ARG NPM_TOKEN
RUN echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" > .npmrc && npm install
EXPOSE 3000
CMD ["node", "server.js"]

There are five problems.

  • node:latest isn't pinned. It changes without warning, and the full image has many extra packages, each a possible CVE. Use a pinned, small base such as node:22-slim or a distroless image, ideally pinned by digest.
  • COPY . . copies everything. Without a .dockerignore, the image gets .env files, .git, local node_modules and any keys in the folder.
  • The npm token leaks. Build arguments show up in the image history (docker history). The .npmrc file also stays in that image layer. Use a BuildKit secret mount instead: RUN --mount=type=secret,id=npmrc,target=/root/.npmrc npm ci.
  • npm install installs too much. Use npm ci --omit=dev for exact versions with no dev tools. A multi-stage build keeps build tools and source files out of the final image.
  • It runs as root. There is no USER line. If an attacker breaks in, root makes escaping the container easier. The official Node image has a node user, so add USER node.

Also scan the image in CI. At runtime, use a read-only file system and drop Linux capabilities you don't need.

  • Pin a small base image instead of node:latest.
  • Add a .dockerignore so .env files and .git aren't copied.
  • Build arguments and files in layers leak secrets, so use BuildKit secret mounts.
  • Use npm ci --omit=dev and multi-stage builds.
  • Run as a non-root user with USER node.