T08 · Insecure Dependencies
- Location
scripts/init-project.js:51- Finding
Automatic Installation of Unpinned npm Dependencies
- Content
View full analysis
Vulnerability Details
File Location:
scripts/init-project.js:51-70,scripts/init-project.js:104-121, andscripts/export.js:51-64, 152-156
Vulnerability Type: Supply-chain exposure through mutable, unpinned npm dependencies
Risk Level: MediumThe project automatically installs third-party packages without specifying exact versions or using a reviewed lockfile. Exporting a presentation can also initiate an installation without a distinct dependency-installation confirmation.
Vulnerable Code
From
scripts/init-project.js:51-70:js function ensureDeps(projectDir, packages) { const pkg = readPackageJson(projectDir); const installed = { ...(pkg.dependencies || {}), ...(pkg.devDependencies || {}), }; const missing = packages.filter((name) => !installed[name]); if (missing.length === 0) { return; } console.log(`Installing dependencies: ${missing.join(', ')}`); execFileSync('npm', ['i', '-D', ...missing], { cwd: projectDir, stdio: 'inherit', }); }From
scripts/init-project.js:104-121:js const baseDeps = ['@slidev/cli']; const officialThemes = [ '@slidev/theme-default', '@slidev/theme-seriph', '@slidev/theme-apple-basic', '@slidev/theme-bricks', '@slidev/theme-shibainu', ]; ensureDeps( projectDir, options.installAllOfficialThemes ? [...baseDeps, ...officialThemes] : baseDeps, ); if (options.withExportDeps) { ensureDeps(projectDir, ['playwright-chromium']); }From
scripts/export.js:51-64:js function ensureProjectDep(name) { const pkg = JSON.parse(fs.readFileSync('package.json', 'utf8')); const installed = { ...(pkg.dependencies || {}), ...(pkg.devDependencies || {}), }; if (installed[name]) { return; } console.log(`Missing dependency ${name}, installing into project...`); execFileSync('npm', ['i', '-D', name], { stdio: 'inhe ...[truncated 2591 chars]- Remediation
View remediation
Remediation Suggestions
-
Pin every directly installed dependency to an exact, reviewed version, for example:
js const baseDeps = ['@slidev/cli@<reviewed-version>'];Apply exact versions to all themes and
playwright-chromium. -
Provide a maintained project template with a committed
package-lock.json, and install it using:bash npm ciThis ensures package versions and integrity hashes match reviewed dependency state.
-
Avoid automatically installing dependencies during export. If an export dependency is missing, stop and display the exact proposed package and version, then require explicit user confirmation.
-
Use
--ignore-scriptswhere lifecycle scripts are not required:bash npm ci --ignore-scriptsIf Playwright requires a browser installation step, perform that step separately and explicitly after validating the package and version.
-
Validate the npm registry before installation and document the expected trusted registry. Consider enforcing it through a project-local
.npmrc. -
Add automated dependency review, vulnerability scanning, and lockfile-integrity checks to the release process. Review version updates before changing the pinned dependency set.
-
Document that initialization and export may access the network and execute third-party installation code so operators can run the process in an appropriately restricted environment.
-
