https://github.com/alulsh/docker-npmrc-security
.npmrc files are often used insecurely in Docker images. Use multi-stage builds or Docker build secrets to protect your .nrpmc files.
https://github.com/alulsh/docker-npmrc-security
docker npm npmrc npmrc-files security
Last synced: 29 days ago
JSON representation
.npmrc files are often used insecurely in Docker images. Use multi-stage builds or Docker build secrets to protect your .nrpmc files.
- Host: GitHub
- URL: https://github.com/alulsh/docker-npmrc-security
- Owner: alulsh
- Created: 2018-06-23T12:51:06.000Z (almost 7 years ago)
- Default Branch: main
- Last Pushed: 2022-12-08T05:40:52.000Z (over 2 years ago)
- Last Synced: 2025-04-04T02:41:33.198Z (about 2 months ago)
- Topics: docker, npm, npmrc, npmrc-files, security
- Language: JavaScript
- Homepage: https://www.alexandraulsh.com/2018/06/25/docker-npmrc-security/
- Size: 24.4 KB
- Stars: 54
- Watchers: 1
- Forks: 5
- Open Issues: 2
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# Docker images and .npmrc security
This is a companion repo with code samples for https://www.alexandraulsh.com/2018/06/25/docker-npmrc-security/, a blog post I wrote about using `.npmrc` files securely in Docker images.
## Setup
To build these example Docker images you'll need git, Node.js, npm, an npm account, and Docker. You'll need to set an `NPM_TOKEN` environment variable so you can pass it as a build argument to Docker.
### Clone the repo
1. `git clone https://github.com/alulsh/docker-npmrc-security.git` or `git clone [email protected]:alulsh/docker-npmrc-security.git`
1. `cd docker-npmrc-security`### Npm
1. Install Node.js and npm. I recommend using [nvm](https://github.com/creationix/nvm).
1. [Sign up](https://www.npmjs.com/signup) for an account on npmjs.com.
1. Run `npm token create --read-only` to create a [read-only npm token](https://docs.npmjs.com/getting-started/working_with_tokens#how-to-create-a-new-read-only-token).
1. Run `export NPM_TOKEN=` to set your npm token as an environment variable.### Docker
[Download the version of Docker CE](https://docs.docker.com/install/) for your operating system. The BuildKit mode `--secret` flag requires Docker 18.09 and later.
## Insecure Dockerfiles
### #1 - Leaving `.npmrc` files in Docker containers
[`Dockerfile-insecure-1`](https://github.com/alulsh/docker-npmrc-security/blob/master/Dockerfile-insecure-1)
To build this image, run `docker build . -f Dockerfile-insecure-1 -t insecure-app-1 --build-arg NPM_TOKEN=$NPM_TOKEN`.
#### Problem
```
ARG NPM_TOKENRUN echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" > .npmrc
RUN npm install
```The `.npmrc` file is never deleted from this image. The `.npmrc` file is on the file system of any containers created from this image.
#### Exploitation
1. Run `docker run -it insecure-app-1 ash` to start the container. We need to use `ash` instead of `bash` since we're running Alpine Linux.
1. Run `ls -al`. You should see an `.npmrc` file in the `/private-app` directory.
1. Run `cat .npmrc`.### #2 - Leaving `.npmrc` files in Docker intermediate images
[`Dockerfile-insecure-2`](https://github.com/alulsh/docker-npmrc-security/blob/master/Dockerfile-insecure-2)
To build this image, run `docker build . -f Dockerfile-insecure-2 -t insecure-app-2 --build-arg NPM_TOKEN=$NPM_TOKEN`.
#### Problem
```
ARG NPM_TOKENRUN echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" > .npmrc
RUN npm install
RUN rm -f .npmrc
```The `.npmrc` file is deleted from this Docker image but in a separate `RUN` instruction. Each `RUN` instruction creates a new Docker layer (intermediate image). If an attacker has access to the Docker daemon or obtains a copy of our image then they can steal the `.npmrc` file from the layers of the Docker image.
#### Exploitation
1. Run `docker save insecure-app-2 -o ~/insecure-app-2.tar` to save the Docker image as a tarball.
1. Run `mkdir ~/insecure-app-2 && tar xf ~/insecure-app-2.tar -C ~/insecure-app-2` to untar to `~/insecure-app-2`.
1. Run `cd ~/insecure-app-2`.
1. Run `for layer in */layer.tar; do tar -tf $layer | grep -w .npmrc && echo $layer; done`. You should see a list of layers with `.npmrc` files.
1. Run `tar xf /layer.tar private-app/.npmrc` to extract `private-app/.npmrc` from the layer tarball.
1. Run `cat private-app/.npmrc` to view the `.npmrc` file and npm token.### #3 - Leaking npm tokens in the image commit history
[`Dockerfile-insecure-3`](https://github.com/alulsh/docker-npmrc-security/blob/master/Dockerfile-insecure-3)
To build this images, run `docker build . -f Dockerfile-insecure-3 -t insecure-app-3 --build-arg NPM_TOKEN=$NPM_TOKEN`.
#### Problem
```
ARG NPM_TOKENRUN echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" > .npmrc && \
npm install && \
rm -f .npmrc
```The `.npmrc` file is created, used, and deleted in the same `RUN` instruction and Docker layer. Since we passed in the npm token as a build argument (`ARG NPM_TOKEN`) our npm tokens are still leaked in the Docker image commit history. If the attacker gains access to the Docker daemon or obtains a copy of our Docker image then they can steal our npm tokens using [`docker history`](https://docs.docker.com/engine/reference/commandline/history/).
#### Exploitation
1. Run `docker history insecure-app-3`.
## Secure Dockerfiles
### Multi-stage builds
[`Dockerfile-secure-multistage`](https://github.com/alulsh/docker-npmrc-security/blob/master/Dockerfile-secure-multistage)
To build this image, run `docker build . -f Dockerfile-secure-multistage -t secure-app-multistage --build-arg NPM_TOKEN=$NPM_TOKEN`.
This `Dockerfile` uses [multi-stage builds](https://docs.docker.com/develop/develop-images/multistage-build/#use-an-external-image-as-a-stage) to protect our `.npmrc` file. In the first stage build, we create our `.npmrc`, run `npm install`, and delete our `.npmrc`. We then copy over our built Node application to our second stage build. We can use the same base image - `node:8.11.3-alpine` - for both stages of our build.
To verify that this Docker image does not leak our npm tokens, run `docker history secure-app-multistage`.
### Experimental BuildKit mode `--secret` flag
[`Dockerfile-secure-secrets`](https://github.com/alulsh/docker-npmrc-security/blob/master/Dockerfile-secure-secrets)
To build this image, run `DOCKER_BUILDKIT=1 docker build . -f Dockerfile-secure-secrets -t secure-app-secrets --secret id=npm,src=$HOME/.npmrc`. You can also run `export DOCKER_BUILDKIT=1` to enable BuildKit, then run `docker build . -f Dockerfile-secure-secrets -t secure-app-secrets --secret id=npm,src=$HOME/.npmrc`.
This `Dockerfile` uses the [`--secret` flag for `docker build`](https://docs.docker.com/develop/develop-images/build_enhancements/#new-docker-build-secret-information) released with [Docker 18.09](https://docs.docker.com/engine/release-notes/#18090). It uses the experimental [`RUN --mount=type=secret` syntax](https://github.com/moby/buildkit/blob/master/frontend/dockerfile/docs/experimental.md#run---mounttypesecret) from [the experimental Docker frontend for BuildKit](https://github.com/moby/buildkit/blob/master/frontend/dockerfile/docs/experimental.md#use-experimental-dockerfile-frontend). [This Docker CLI pull request](https://github.com/docker/cli/pull/1288) added support for `--secret` to `docker build` in August 2018.
To verify that this Docker image does not leak our npm tokens, run `docker history secure-app-secrets`.