T08 · Insecure Dependencies
Warning
- Location
- scripts/bootstrap-npm-tooling.sh:15
- Finding
- Unpinned Global npm Package Installation Creates a Supply-Chain Risk<![CDATA[ ## Vulnerability Details **File Location**: `scripts/bootstrap-npm-tooling.sh:15-27` **Vulnerability Type**: Unpinned third-party dependencies installed globally **Risk Level**: Medium ### Vulnerable Code ```bash prefix="$(npm prefix -g)" if [ ! -w "$prefix" ]; then prefix="$HOME/.local" mkdir -p "$prefix" npm config set prefix "$prefix" >/dev/null fi npm install -g browser-sync concurrently npm-check-updates vite echo echo "npm global prefix: $(npm prefix -g)" echo "Installed tooling:" npm list -g --depth=0 | egrep 'browser-sync|concurrently|npm-check-updates|vite' || true ``` ### Technical Analysis The script installs four packages from the npm registry without specifying exact versions, using a lockfile, or verifying package integrity. Consequently, the code installed by the script is determined by mutable npm registry state at execution time rather than by the audited Skill contents. npm packages can execute lifecycle scripts during installation. If one of the named packages or any transitive dependency is compromised, the malicious release can execute code with the privileges of the user running this bootstrap script. Global installation also makes the affected tools available outside this project and increases the duration and scope of exposure. The script attempts to use a writable global prefix and otherwise changes the user's npm global prefix to `$HOME/.local`. Under the documented workflow, compromise would ordinarily obtain the invoking user's privileges rather than root privileges. The impact would be greater if an operator independently ran the script through `sudo`, although the project does not instruct the operator to do so. ### Attack Path 1. An attacker compromises one of the named npm packages, a transitive dependency, or its publishing account. 2. The attacker publishes a malicious release or dependency update containing an install-time lifecycle script or malicious runtime behavior. 3. An operator runs `scripts/b ...[truncated 1050 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Pin every direct dependency to an exact, reviewed version rather than relying on npm's current latest release: ```bash npm install --save-exact \ browser-sync@REVIEWED_VERSION \ concurrently@REVIEWED_VERSION \ npm-check-updates@REVIEWED_VERSION \ vite@REVIEWED_VERSION ``` 2. Install tooling in a project-local package rather than globally. 3. Commit `package.json` and `package-lock.json`, and use `npm ci` so dependency resolution is reproducible. 4. Review and update the lockfile through a controlled dependency-update process. 5. Use `npm ci --ignore-scripts` when lifecycle scripts are unnecessary. If lifecycle scripts are required, explicitly review the packages that use them. 6. Run package provenance, integrity, and vulnerability checks in CI before accepting dependency updates. 7. Avoid running npm bootstrap operations through `sudo`. 8. Do not change the user's persistent global npm configuration merely to support this project; use a project-local tool directory or invoke tools through package scripts. ]]>
