fix: recognize allowScripts for local link targets#9490
Conversation
|
@JamieMagee So this looks valid to me for v11, if the user has added One thing I'd like your read on for v12 before this lands there: in rebuild.js the |
owlstronaut
left a comment
There was a problem hiding this comment.
This adds node.realpath and node.path to the spec list for every node. A registry-resolved package can't match a file policy key because matchFileOrDir short circuits. With this change a registry package like sharp@0.33.0 installed at proj/node_modules/sharp will match a k ey like file:/proj/node_modules/sharp": true.
| add(node.realpath) | ||
| add(node.path) |
There was a problem hiding this comment.
+1 to @owlstronaut. The guard on line 113 is always true since linksIn is always a Set, so these two lines add realpath/path for every node, not just link targets. A registry package's install path then becomes a match candidate for file:/directory keys. I checked locally: a registry node returns true for {"file:node_modules/<name>": true} where base returns null.
Can we gate the paths on the real link-target case, e.g. only add them when !node.resolved && node.linksIn.size > 0?
| // Denying always writes `"<name>": false`, regardless of `--allow-scripts-pin`, per the | ||
| // RFC's asymmetric-pin rule. | ||
|
|
||
| const primaryResolvedSource = (node) => resolvedSourceSpecs(node)[0] || '' |
There was a problem hiding this comment.
The same root cause leaks into the writer. If a link target has an empty linksIn (so resolved is null), resolvedSourceSpecs(node)[0] is node.realpath, an absolute path. versionedKeyFor/nameKeyFor then take the startsWith('/') branch and write something like /proj/node_modules/A into allowScripts instead of file:../A. Better to prefer a file: candidate over a bare path, or return null so we don't persist a machine-specific key. Fixing comment 1 with the size > 0 guard mostly covers this too.
| t.end() | ||
| }) | ||
|
|
||
| t.test('file path — link target matches incoming link source', t => { |
There was a problem hiding this comment.
Could you add a negative case here? A registry node (resolved = tarball URL, empty linksIn) shouldn't match a file: key by its install path: t.equal(isScriptAllowed(reg, { 'file:node_modules/<name>': true }), null). That pins down the boundary @owlstronaut flagged. Covering an empty linksIn Set and a link with resolved === null would help too.
Summary
allowScriptspolicy entries.approve-scripts/deny-scriptsderive file dependency policy keys.file:dependency link targets.Fixes #9488
Testing
node node_modules/tap/bin/run.js --no-coverage workspaces/arborist/test/script-allowed.js workspaces/arborist/test/unreviewed-scripts.js test/lib/utils/allow-scripts-writer.js test/lib/utils/check-allow-scripts.js test/lib/utils/resolve-allow-scripts.jsnode node_modules/eslint/bin/eslint.js lib/utils/allow-scripts-writer.js test/lib/utils/allow-scripts-writer.js workspaces/arborist/lib/script-allowed.js workspaces/arborist/test/script-allowed.js workspaces/arborist/test/unreviewed-scripts.jsgit diff --checkfile:dependency withallowScripts: { "file:../testdep": false }no longer emits anallow-scriptswarning;npm approve-scripts --allwritesfile:../testdep.