libnpmexec 10.2.9 → 10.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/index.js CHANGED
@@ -4,6 +4,7 @@ const { dirname, join, resolve } = require('node:path')
4
4
  const crypto = require('node:crypto')
5
5
  const { mkdir } = require('node:fs/promises')
6
6
  const Arborist = require('@npmcli/arborist')
7
+ const strictAllowScriptsPreflight = require('./strict-allow-scripts-preflight.js')
7
8
  const ciInfo = require('ci-info')
8
9
  const { log, input } = require('proc-log')
9
10
  const npa = require('npm-package-arg')
@@ -86,6 +87,9 @@ const missingFromTree = async ({ spec, tree, flatOptions, isNpxTree, shallow })
86
87
  }
87
88
  }
88
89
 
90
+ // Strict-mode pre-flight for `npm exec` / `npx` lives in
91
+ // ./strict-allow-scripts-preflight.js
92
+
89
93
  // see if the package.json at `path` has an entry that matches `cmd`
90
94
  // the path is a known-local directory, not a user-supplied dep, so
91
95
  // allow-directory must not gate this introspection
@@ -301,11 +305,16 @@ const exec = async (opts) => {
301
305
  }
302
306
  }
303
307
  }
304
- await withLock(lockPath, () => npxArb.reify({
305
- ...flatOptions,
306
- save: true,
307
- add,
308
- }))
308
+ await withLock(lockPath, async () => {
309
+ // Hard-fail before reify if --strict-allow-scripts is set and
310
+ // any node has install scripts not covered by allowScripts.
311
+ await strictAllowScriptsPreflight(npxArb, { ...flatOptions, add })
312
+ await npxArb.reify({
313
+ ...flatOptions,
314
+ save: true,
315
+ add,
316
+ })
317
+ })
309
318
  }
310
319
  binPaths.push(resolve(installDir, 'node_modules/.bin'))
311
320
  const pkgJson = await PackageJson.load(installDir)
package/lib/run-script.js CHANGED
@@ -19,7 +19,9 @@ const run = async ({
19
19
  // necessary for preventing bash/cmd keywords from overriding
20
20
  if (!isWindowsShell) {
21
21
  if (args.length > 0) {
22
- args[0] = '"' + args[0] + '"'
22
+ // single-quote so shell metacharacters in the executable name are taken
23
+ // literally; double quotes still expand $(), backticks, $var and "
24
+ args[0] = `'${args[0].replace(/'/g, `'\\''`)}'`
23
25
  }
24
26
  }
25
27
 
@@ -0,0 +1,40 @@
1
+ const { collectUnreviewedScripts, strictAllowScriptsError } = require('@npmcli/arborist/lib/unreviewed-scripts.js')
2
+
3
+ // Strict-mode pre-flight for `npm exec` / `npx`. When
4
+ // `--strict-allow-scripts` is set, build the npx-cache ideal tree and
5
+ // throw before reify if any node has install scripts not covered by
6
+ // the resolved `allowScripts` policy. The arborist gate already
7
+ // silently skips those scripts; this turns the silent skip into a
8
+ // hard failure for CI. Bypassed by `--ignore-scripts` and
9
+ // `--dangerously-allow-all-scripts`.
10
+ const strictAllowScriptsPreflight = async (arb, opts) => {
11
+ if (!opts.strictAllowScripts) {
12
+ return
13
+ }
14
+ if (opts.ignoreScripts || opts.dangerouslyAllowAllScripts) {
15
+ return
16
+ }
17
+
18
+ if (!arb.idealTree) {
19
+ await arb.buildIdealTree(opts)
20
+ }
21
+
22
+ const unreviewed = await collectUnreviewedScripts({
23
+ tree: arb.idealTree,
24
+ policy: opts.allowScripts || null,
25
+ ignoreScripts: opts.ignoreScripts,
26
+ dangerouslyAllowAllScripts: opts.dangerouslyAllowAllScripts,
27
+ })
28
+
29
+ if (unreviewed.length === 0) {
30
+ return
31
+ }
32
+
33
+ throw strictAllowScriptsError(unreviewed, {
34
+ remediation:
35
+ 'Pass --allow-scripts=<pkg> for one-off approval, or bypass this ' +
36
+ 'check with --dangerously-allow-all-scripts.',
37
+ })
38
+ }
39
+
40
+ module.exports = strictAllowScriptsPreflight
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "libnpmexec",
3
- "version": "10.2.9",
3
+ "version": "10.3.0",
4
4
  "files": [
5
5
  "bin/",
6
6
  "lib/"
@@ -61,7 +61,7 @@
61
61
  },
62
62
  "dependencies": {
63
63
  "@gar/promise-retry": "^1.0.0",
64
- "@npmcli/arborist": "^9.7.0",
64
+ "@npmcli/arborist": "^9.8.0",
65
65
  "@npmcli/package-json": "^7.0.0",
66
66
  "@npmcli/run-script": "^10.0.0",
67
67
  "ci-info": "^4.0.0",