CVE-2018-7408 (JavaScript, published 2018-02-22T18:29Z)
Description: value: An issue was discovered in an npm 5.7.0 2018-02-21 pre-release (marked as "next: 5.7.0" and therefore automatically installed by an "npm upgrade -g npm" command, and also announced in the vendor's blog without mention of pre-release status). It might allow local users to bypass intended filesystem access restrictions because ownerships of /etc and /usr directories are being changed unexpectedly, related to a "correctMkdir" issue.
Severity: MEDIUM (CVSS v3 base score: 7.8)
Weakness: CWE-732 \u2014 Incorrect Permission Assignment for Critical Resource
The product specifies permissions for a security-critical resource in a way that allows that resource to be read or modified by unintended actors.
Repository: https://github.com/npm/npm
Files changed:
lib/config/core.js
lib/config/set-user.js
lib/install.js
lib/install/action/extract.js
lib/install/action/finalize.js
lib/install/action/move.js
lib/install/action/remove.js
lib/utils/completion/file-completion.js
lib/utils/correct-mkdir.js
Commit message: Revert "*: Switch from mkdirp to correctMkdir to preserve perms and owners"

This reverts commit 94227e15eeced836b3d7b3d2b5e5cc41d4959cff.

Fixes: #19883


Vulnerable code:
var correctMkdir = require('../utils/correct-mkdir.js')
      correctMkdir(etc, function () {
      correctMkdir(this.prefix, cb)
    correctMkdir(path.dirname(target.path), function (er) {
var correctMkdir = require('../utils/correct-mkdir.js')
  correctMkdir(prefix, function (er) {
var correctMkdir = require('./utils/correct-mkdir.js')
    correctMkdir(self.where, iferr(cb, function () {
  correctMkdir(this.where, iferr(cb, function () {
const correctMkdir = BB.promisify(require('../../utils/correct-mkdir'))
    return correctMkdir(path.dirname(stageTo)).then(() => {
const correctMkdir = Bluebird.promisify(require('../../utils/correct-mkdir.js'))
    return correctMkdir(path.dirname(dir))
      return correctMkdir(path.join(pkg.realpath, 'node_modules')).then(() => Bluebird.map(modules, (file) => {
var correctMkdir = require('../../utils/correct-mkdir')
      correctMkdir(path.resolve(to, '..'), iferr(done, moveNodeModules(next)))
      correctMkdir(from, iferr(done, function () {
var correctMkdir = require('../../utils/correct-mkdir')
    correctMkdir(path.join(pkg.path, 'node_modules'), function (mkdirEr) { moveModules(mkdirEr, files) })
var correctMkdir = require('../correct-mkdir.js')
  correctMkdir(root, function (er) {
    return log.silly('correctMkdir', path, 'correctMkdir already in flight; waiting')
    log.silly('correctMkdir', path, 'correctMkdir not in flight; initializing')
  var stats = {}
    if (er) return makeDirectory(path, stats, cb)
function makeDirectory (path, stats, cb) {
    return log.silly('makeDirectory', path, 'creation already in flight; waiting')
    log.silly('makeDirectory', path, 'creation not in flight; initializing')

Fixed code:
var mkdirp = require('mkdirp')
      mkdirp(etc, function () {
      mkdirp(this.prefix, cb)
    mkdirp(path.dirname(target.path), function (er) {
var mkdirp = require('mkdirp')
  mkdirp(prefix, function (er) {
var mkdirp = require('mkdirp')
    mkdirp(self.where, iferr(cb, function () {
  mkdirp(this.where, iferr(cb, function () {
const mkdirp = BB.promisify(require('mkdirp'))
    return mkdirp(path.dirname(stageTo)).then(() => {
const mkdirp = Bluebird.promisify(require('mkdirp'))
    return mkdirp(path.dirname(dir))
      return mkdirp(path.join(pkg.realpath, 'node_modules')).then(() => Bluebird.map(modules, (file) => {
var mkdirp = require('mkdirp')
      mkdirp(path.resolve(to, '..'), iferr(done, moveNodeModules(next)))
      mkdirp(from, iferr(done, function () {
var mkdirp = require('mkdirp')
    mkdirp(path.join(pkg.path, 'node_modules'), function (mkdirEr) { moveModules(mkdirEr, files) })
var mkdir = require('mkdirp')
  mkdir(root, function (er) {
var stats = {}
    return log.verbose('correctMkdir', path, 'correctMkdir already in flight; waiting')
    log.verbose('correctMkdir', path, 'correctMkdir not in flight; initializing')
    if (er) return makeDirectory(path, cb)
function makeDirectory (path, cb) {
    return log.verbose('makeDirectory', path, 'creation already in flight; waiting')
    log.verbose('makeDirectory', path, 'creation not in flight; initializing')