Skip to content

[BUG] Some git commands are executed under destination directory's owner account #14

Closed
@x-yuri

Description

@x-yuri

What / Why

It might so happen that root installs packages into a directory owned by another user. Consider a case where you launch an app with docker-compose and bind mount the host directory with source code (.) into the container (/app) for changes to source code to automatically propagate into the container. Under this circumstances we get root user and /app owned by uid 1000. During fetch-package-metadata phase it succeeds, since nothing says it has to impersonate:

[email protected] started to run commands under cwd's owner. But some files are to be created in ~/.npm/_cacache/tmp (e.g. cloning repositories when installing from github). When a process (npm) user doesn't match the cwd user, process user's cache is still used. So git clone is executed under cwd user to clone to the process user's tmp dir, which apparently fails. That can happen under docker when a non-root's directory is bind-mounted into a container. It's not owned by root in the container either, but the processes in the container are running under root (unless explicitly started as another user).

The issue doesn't reveal itself on the fetch-package-metadata phase:

https://github.com/npm/cli/blob/v6.12.1/lib/fetch-package-metadata.js#L59-L65
https://github.com/npm/pacote/blob/v9.5.8/manifest.js#L25
https://github.com/npm/pacote/blob/v9.5.8/lib/finalize-manifest.js#L49
https://github.com/npm/pacote/blob/v9.5.8/lib/finalize-manifest.js#L154
https://github.com/npm/pacote/blob/v9.5.8/lib/fetch.js#L33
https://github.com/npm/pacote/blob/v9.5.8/lib/fetchers/git.js#L71-L73
https://github.com/npm/pacote/blob/v9.5.8/lib/fetchers/git.js#L176

But on the extract phase it switches to non-root and fails:

https://github.com/npm/cli/blob/v6.12.1/lib/install/action/extract.js#L90
https://github.com/npm/pacote/blob/v9.5.8/extract.js#L42
https://github.com/npm/pacote/blob/v9.5.8/lib/with-tarball-stream.js#L96
https://github.com/npm/pacote/blob/v9.5.8/lib/fetch.js#L28
https://github.com/npm/pacote/blob/v9.5.8/lib/fetchers/git.js#L44
https://github.com/npm/pacote/blob/v9.5.8/lib/fetchers/git.js#L71-L73
https://github.com/npm/pacote/blob/v9.5.8/lib/fetchers/git.js#L176

When

  • When installing packages from GitHub.

Where

  • n/a

How

Current Behavior

  • An error occurs:
npm ERR! code 128
npm ERR! Command failed: git clone --mirror -q git://github.com/kevva/is-positive.git /root/.npm/_cacache/tmp/git-clone-d80b8730/.git
npm ERR! fatal: could not create leading directories of '/root/.npm/_cacache/tmp/git-clone-d80b8730/.git'

Steps to Reproduce

Under non-root user:

1.sh:

#!/bin/sh
set -eux
npm --version
apk add git
npm i kevva/is-positive || cat /root/.npm/_logs/*.log
$ docker run --rm -itv $PWD:/app -w /app node:10.17.0-alpine3.10 ./1.sh
+ npm --version
6.11.3
...
+ npm i kevva/is-positive
...
npm ERR! Command failed: git clone --mirror -q git://github.com/kevva/is-positive.git /root/.npm/_cac
ache/tmp/git-clone-87fa5e82/.git
npm ERR! fatal: could not create leading directories of '/root/.npm/_cacache/tmp/git-clone-87fa5e82/.
git'
...

Or under root in a non-root dir:

$ npm i kevva/is-positive

Expected Behavior

  • It either succeeds in both cases (extract, fetch-package-metadata), or fails. Preferably the former.

Who

  • n/a

References

More info

Introduced in npm-6.11.0, pacote-9.5.5. Fixed in npm-6.13.6, pacote-9.5.12.
Affects node@^10.17.0 (npm-6.11.3), node >= 12.11.0 (npm-6.11.3), node < 13.7.0 (npm-6.13.6). More on it here.

Old steps to reproduce

Create files based on the following gist and do docker-compose up:

docker-compose.yml:

version: '3'

services:
  app:
    build: .
    # entrypoint: sleep 10000000
    # ports:
      # - 9229:9229
    volumes:
      - ./:/app

Dockerfile:

FROM node:12.13.0-alpine

RUN apk add git vim
WORKDIR /app

ENTRYPOINT ["./entrypoint.sh"]

entrypoint.sh:

#!/bin/sh
set -eu
npm i || true
cat /root/.npm/_logs/*.log
$ chmod u+x entrypoint.sh
$ docker-compose up

As you might guess the issue was discovered in a docker container. Alternatively,

# useradd -m u1
# cd /home/u1
# echo '{"dependencies": {"is-positive": "kevva/is-positive"}}' > package.json
# npm i

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions