Let’s say you are running a linter like HTMLhint. It has 27 dependencies, any of those could be malicious. So, when you do npm install -g htmlhint, you are taking a huge risk. And this is not a theoretical risk.
Even big companies like Amazon are falling for it.
A linter, for example, needs just read-only access to the all the files that you want to lint.
- It does not need access to files outside the current directory
- It does not need Internet access
- It does not need to modify any files either, read-only access is sufficient
So, run it inside Docker to mitigate the risk.
Using Docker, you can enforce the following restrictions:
- ✅ No ability to send data over the Internet
- ✅ No access to any files outside the current directory
- ✅ Read-only access to files inside the current directory
| 1 2 3 4 5 6 7 8 9 10 | # network=none => no network access # -v ${PWD}:${PWD} => mount current directory to the same path inside the container # ro => read-only filesystem access # Build: # docker build -t htmlhint . # Run: # docker run --rm --network=none -v ${PWD}:${PWD}:ro htmlhint ${PWD} FROM node:24-alpine3.21 RUN npm install -g htmlhint ENTRYPOINT ["htmlhint"] |
This drastically reduces the attack surface of the code.
You can do this with pretty much any tool.
Consider golangci-lint, the famous meta-linter for Go language.
You can run it inside docker with the following command.
| 1 2 3 | $ docker run --rm --network=none -v ${PWD}:${PWD}:ro --workdir=${PWD} golangci/golangci-lint:latest-alpine golangci-lint run ... |
Or you can do a read/write mount for a formatting tool to let it format/modify the files.
| 1 2 3 | $ docker run --rm --network=none -v ${PWD}:${PWD} --workdir=${PWD} golangci/golangci-lint:latest-alpine golangci-lint run --fix ... |
I even recommend this technique for running tools on GitHub Actions and have started using this extensively in GitHub Actions Boilerplate Generator.
.png)

