{"id":19491898,"url":"https://github.com/alulsh/docker-npmrc-security","last_synced_at":"2025-04-25T19:32:23.516Z","repository":{"id":149789315,"uuid":"138400715","full_name":"alulsh/docker-npmrc-security","owner":"alulsh","description":".npmrc files are often used insecurely in Docker images. Use multi-stage builds or Docker build secrets to protect your .nrpmc files.","archived":false,"fork":false,"pushed_at":"2022-12-08T05:40:52.000Z","size":25,"stargazers_count":54,"open_issues_count":2,"forks_count":5,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-04T02:41:33.198Z","etag":null,"topics":["docker","npm","npmrc","npmrc-files","security"],"latest_commit_sha":null,"homepage":"https://www.alexandraulsh.com/2018/06/25/docker-npmrc-security/","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/alulsh.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-06-23T12:51:06.000Z","updated_at":"2024-11-30T05:58:04.000Z","dependencies_parsed_at":"2023-06-02T15:30:32.304Z","dependency_job_id":null,"html_url":"https://github.com/alulsh/docker-npmrc-security","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alulsh%2Fdocker-npmrc-security","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alulsh%2Fdocker-npmrc-security/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alulsh%2Fdocker-npmrc-security/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alulsh%2Fdocker-npmrc-security/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/alulsh","download_url":"https://codeload.github.com/alulsh/docker-npmrc-security/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250882637,"owners_count":21502341,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["docker","npm","npmrc","npmrc-files","security"],"created_at":"2024-11-10T21:18:40.813Z","updated_at":"2025-04-25T19:32:23.510Z","avatar_url":"https://github.com/alulsh.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Docker images and .npmrc security\n\nThis 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.\n\n## Setup\n\nTo 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.\n\n### Clone the repo\n\n1. `git clone https://github.com/alulsh/docker-npmrc-security.git` or `git clone git@github.com:alulsh/docker-npmrc-security.git`\n1. `cd docker-npmrc-security`\n\n### Npm\n\n1. Install Node.js and npm. I recommend using [nvm](https://github.com/creationix/nvm).\n1. [Sign up](https://www.npmjs.com/signup) for an account on npmjs.com.\n1. 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).\n1. Run `export NPM_TOKEN=\u003cnpm token\u003e` to set your npm token as an environment variable.\n\n### Docker\n\n[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.\n\n## Insecure Dockerfiles\n\n### #1 - Leaving `.npmrc` files in Docker containers\n\n[`Dockerfile-insecure-1`](https://github.com/alulsh/docker-npmrc-security/blob/master/Dockerfile-insecure-1)\n\nTo build this image, run `docker build . -f Dockerfile-insecure-1 -t insecure-app-1 --build-arg NPM_TOKEN=$NPM_TOKEN`.\n\n#### Problem\n\n```\nARG NPM_TOKEN\n\nRUN echo \"//registry.npmjs.org/:_authToken=$NPM_TOKEN\" \u003e .npmrc\nRUN npm install\n```\n\nThe `.npmrc` file is never deleted from this image. The `.npmrc` file is on the file system of any containers created from this image.\n\n#### Exploitation\n\n1. 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.\n1. Run `ls -al`. You should see an `.npmrc` file in the `/private-app` directory.\n1. Run `cat .npmrc`.\n\n### #2 - Leaving `.npmrc` files in Docker intermediate images\n\n[`Dockerfile-insecure-2`](https://github.com/alulsh/docker-npmrc-security/blob/master/Dockerfile-insecure-2)\n\nTo build this image, run `docker build . -f Dockerfile-insecure-2 -t insecure-app-2 --build-arg NPM_TOKEN=$NPM_TOKEN`.\n\n#### Problem\n\n```\nARG NPM_TOKEN\n\nRUN echo \"//registry.npmjs.org/:_authToken=$NPM_TOKEN\" \u003e .npmrc\nRUN npm install\nRUN rm -f .npmrc\n```\n\nThe `.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.\n\n#### Exploitation\n\n1. Run `docker save insecure-app-2 -o ~/insecure-app-2.tar` to save the Docker image as a tarball.\n1. Run `mkdir ~/insecure-app-2 \u0026\u0026 tar xf ~/insecure-app-2.tar -C ~/insecure-app-2` to untar to `~/insecure-app-2`.\n1. Run `cd ~/insecure-app-2`.\n1. Run `for layer in */layer.tar; do tar -tf $layer | grep -w .npmrc \u0026\u0026 echo $layer; done`. You should see a list of layers with `.npmrc` files.\n1. Run `tar xf \u003clayer id\u003e/layer.tar private-app/.npmrc` to extract `private-app/.npmrc` from the layer tarball.\n1. Run `cat private-app/.npmrc` to view the `.npmrc` file and npm token.\n\n### #3 - Leaking npm tokens in the image commit history\n\n[`Dockerfile-insecure-3`](https://github.com/alulsh/docker-npmrc-security/blob/master/Dockerfile-insecure-3)\n\nTo build this images, run `docker build . -f Dockerfile-insecure-3 -t insecure-app-3 --build-arg NPM_TOKEN=$NPM_TOKEN`.\n\n#### Problem\n\n```\nARG NPM_TOKEN\n\nRUN echo \"//registry.npmjs.org/:_authToken=$NPM_TOKEN\" \u003e .npmrc \u0026\u0026 \\\n    npm install \u0026\u0026 \\\n    rm -f .npmrc\n```\n\nThe `.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/).\n\n#### Exploitation\n\n1. Run `docker history insecure-app-3`.\n\n## Secure Dockerfiles\n\n### Multi-stage builds\n\n[`Dockerfile-secure-multistage`](https://github.com/alulsh/docker-npmrc-security/blob/master/Dockerfile-secure-multistage)\n\nTo build this image, run `docker build . -f Dockerfile-secure-multistage -t secure-app-multistage --build-arg NPM_TOKEN=$NPM_TOKEN`.\n\nThis `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.\n\nTo verify that this Docker image does not leak our npm tokens, run `docker history secure-app-multistage`.\n\n### Experimental BuildKit mode `--secret` flag\n\n[`Dockerfile-secure-secrets`](https://github.com/alulsh/docker-npmrc-security/blob/master/Dockerfile-secure-secrets)\n\nTo 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`.\n\nThis `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.\n\nTo verify that this Docker image does not leak our npm tokens, run `docker history secure-app-secrets`.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falulsh%2Fdocker-npmrc-security","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Falulsh%2Fdocker-npmrc-security","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falulsh%2Fdocker-npmrc-security/lists"}