chmod 777 (or a+rwx) is the usual quick fix for permission errors after adding a non-root USER, but it makes the files writable by every user in the container. A compromised process can then rewrite your application code or config, which is a common way to persist a backdoor. Give the runtime user ownership of only the directory it needs to write, and leave the code read-only.
openrouting — dockerfile explainer
$ explain Dockerfile! RUN makes files world-writable mediumline 6fix: see below$
What the free Dockerfile explainer reports on the risky example below.
Why it matters
The point of running as a non-root user is that the process can't modify the image's code. World-writable files remove that protection.
chmod -R 777 on an application directory usually covers far more than the one cache or upload folder that actually needed write access.
The explainer flags chmod with 777, 0777, a+rwx or ugo+rwx in a RUN step.
Risky and safer Dockerfile
RiskyDockerfile
FROM node:22.11-slim
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci --omit=dev
COPY src ./src
RUN mkdir -p /app/uploads && chmod -R 777 /app
USER 10001
HEALTHCHECK CMD ["node", "src/healthcheck.js"]
CMD ["node", "src/server.js"]
SaferDockerfile
FROM node:22.11-slim
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci --omit=dev
COPY src ./src
RUN mkdir -p /app/uploads && chown 10001:10001 /app/uploads
USER 10001
HEALTHCHECK CMD ["node", "src/healthcheck.js"]
CMD ["node", "src/server.js"]
How to fix it
Find the directories the app really writes to (uploads, cache, temp files).
Make the runtime user own just those: RUN mkdir -p /app/uploads && chown 10001:10001 /app/uploads.
Leave application code owned by root and not writable by the runtime user. For data that must survive restarts, mount a volume there instead.
When it's acceptable
Scratch directories that are already world-writable by design, such as /tmp, which uses the sticky bit (1777) so users can't delete each other's files. The rule matches 777 and 0777, not 1777.
Check your own Dockerfile
The risky example is loaded below. Paste your own file to check it for this and every other Dockerfile rule. It runs in your browser; nothing is uploaded.
Sets the default command to node src/server.js. It runs when the container starts, and anything passed to docker run replaces it.
Questions
Is chmod 777 bad in a Dockerfile?
Yes, for application files. It lets any process in the container modify them, which undoes the benefit of running as a non-root user.
How do I fix permission denied after adding USER to a Dockerfile?
Before the USER line, chown only the directories the app writes to, e.g. chown 10001:10001 /app/uploads, or use COPY --chown for files the user must own.
Does the explainer catch chmod a+rwx too?
Yes. It flags 777, 0777, a+rwx and ugo+rwx in RUN steps.