Enforce proper privilege separation in Docker containers
FROM node:20
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 8080
CMD [ "node", "app.js" ]
The Dockerfile above is used to create a Node.js application running on Docker. Dockerfile instructions are executed in order. Here is a breakdown of what each line does:
1.
FROM node:20
: This line is pulling the base image for Node.js version 20.
2.
WORKDIR /app
: This sets the working directory in the container to
/app
.
3.
COPY package*.json ./
: This line is copying the
package.json
and
package-lock.json
(if available) to the working directory in the container.
4.
RUN npm install
: This installs the dependencies defined in
package.json
.
5.
COPY . .
: This copies the rest of the application to the working directory in the container.
6.
EXPOSE 8080
: This informs Docker that the container listens on the specified network ports at runtime. Here it is set to 8080.
7.
CMD [ "node", "app.js" ]
: This provides defaults for an executing container which includes an executable, or if an entry point is not specified, to run an application when the container is run.
The vulnerability in this Dockerfile is that it runs the application as root in the Docker container. This is a security risk because if an attacker gains control of the container, they could gain root access to the host machine. This is an example of the excessive privileges vulnerability.
# Use an official Node runtime as a parent image with digest
FROM node@sha256:c2ed73be34c27a42bd202021c7fdf1a92999fb171f2e1d54bd4b461d9344eeb2
# Create app directory
WORKDIR /app
# Install app dependencies
COPY package*.json ./
# Create a user named "appuser"
RUN groupadd -r appuser &&\
useradd -r -g appuser -d /app -s /sbin/nologin -c "Docker image user" appuser &&\
chown -R appuser:appuser /app &&\
npm install
# Bundle app source
COPY . .
# Change to non-root user
USER appuser
# Expose port and start application
EXPOSE 8080
CMD [ "node", "app.js" ]
The Dockerfile has been updated to fix the excessive privileges vulnerability. A new user named "appuser" has been created and is used to run the application instead of the root user. This restricts the privileges of the application and minimizes potential risks.
The Docker image is also now referenced by its digest, ensuring that the same image is always used, increasing the reproducibility of the build.
The application's dependencies are installed and the application source is bundled while the root user is active, then the user is switched to "appuser" before the application is started. This ensures that the application runs with restricted privileges.
The Dockerfile now needs to be used to build a new Docker image, and the application should be tested to ensure it still functions correctly with the "appuser".