An open API service indexing awesome lists of open source software.

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.

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_TOKEN

RUN 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_TOKEN

RUN 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_TOKEN

RUN 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`.