Search code examples
javascriptnode.jsdockersingle-page-applicationyarnpkg

Why are there zombie packages in my yarn.lock file?


We deploy all of our applications as Docker containers, and, as part of the build process, run them through a container scan to block deployments that include vulnerabilities with known fixes.

I'm currently getting failures in the security scan because my yarn.lock contains cacache@^12.0.2. But as far as I can tell, there is absolutely no reason for that to be in the lock file. For example, if I run yarn why it seems to have no reason to include the package:

/app # yarn why cacache@^12.0.2
yarn why v1.22.4
[1/4] Why do we have the module "cacache@^12.0.2"...?
[2/4] Initialising dependency graph...
[3/4] Finding dependency...
error We couldn't find a match!
Done in 1.30s.

How do I get rid of these insecure and unnecessary dependencies?

I've tried wiping the lock file and rebuilding from scratch. After doing that, the problematic 12.0.2 version is still there. I've also tried running the autoclean command, which does remove a substantial amount of unnecessary heft, but does not remove these apparently redundant and definitely insecure dependencies.

Update: as requested, here is part of the package file with the dependencies listed:

{
  ... redacted
  "dependencies": {
    "@nuxtjs/axios": "^5.3.6",
    "@sentry/browser": "^5.29.0",
    "@sentry/integrations": "^5.29.0",
    "@sentry/tracing": "^5.29.0",
    "@sentry/vue": "^5.29.0",
    "amplitude-js": "^7.4.1",
    "buefy": "^0.9.3",
    "cacache": "^15.0.6",
    "element-ui": "^2.14.0",
    "file-saver": "^2.0.2",
    "idle-vue": "^2.0.5",
    "is-svg": "^4.2.2",
    "js-cookie": "^2.2.1",
    "launchdarkly-js-client-sdk": "^2.19.1",
    "lodash": "^4.17.15",
    "logrocket": "^1.0.7",
    "logrocket-vuex": "^0.0.3",
    "moment": "^2.26.0",
    "nuxt": "^2.0.0",
    "view-design": "^4.4.0",
    "vue-feather-icons": "^5.1.0",
    "vue-resize-directive": "^1.2.0",
    "vuex-persistedstate": "^3.0.1"
  },
  "devDependencies": {
    "@olavoparno/jest-badges-readme": "^1.5.1",
    "@vue/test-utils": "^1.0.0-beta.27",
    "babel-core": "^7.0.0-bridge.0",
    "babel-jest": "^24.1.0",
    "clipboardy": "^2.3.0",
    "coffee-loader": "^1.0.0",
    "coffeescript": "^2.5.1",
    "cypress": "^6.8.0",
    "jest": "^26.0.0",
    "node-sass": "^4.14.1",
    "pug": "^3.0.1",
    "pug-plain-loader": "^1.0.0",
    "sass-loader": "^8.0.2",
    "vue-jest": "^4.0.0-rc.0"
  }
}

Solution

  • ➜ yarn why cacache
    yarn why v1.21.1
    [1/4] 🤔  Why do we have the module "cacache"...?
    [2/4] 🚚  Initialising dependency graph...
    [3/4] 🔍  Finding dependency...
    [4/4] 🚡  Calculating file sizes...
    => Found "[email protected]"
    info Has been hoisted to "cacache"
    info Reasons this module exists
       - Specified in "dependencies"
       - Hoisted from "nuxt#@nuxt#webpack#terser-webpack-plugin#cacache"
    => Found "webpack#[email protected]"
    info Reasons this module exists
       - "nuxt#@nuxt#webpack#webpack#terser-webpack-plugin" depends on it
       - Hoisted from "nuxt#@nuxt#webpack#webpack#terser-webpack-plugin#cacache"
    

    (Posted as an answer because this would make a terrible comment.)

    Then follow up with yarn why terser-webpack-plugin of course.