(npm, { skipProjectConfig = false } = {})
| 105 | // install run from a workspace sub-directory still picks up the project |
| 106 | // root's policy. |
| 107 | const resolveAllowScripts = async (npm, { skipProjectConfig = false } = {}) => { |
| 108 | // Independently probe each RFC layer. |
| 109 | const cliPolicy = policyFromSources(npm, ['cli', 'env']) |
| 110 | const npmrcPolicy = policyFromSources(npm, ['project', 'user', 'global', 'builtin']) |
| 111 | |
| 112 | // The --allow-scripts CLI flag is intended for one-off and global |
| 113 | // contexts (npm exec, npx, npm install -g). In a project-scoped install, |
| 114 | // team policy belongs in package.json or .npmrc, so reject the flag |
| 115 | // outright to avoid the "works on my machine" footgun. |
| 116 | if (cliPolicy && !npm.global && !skipProjectConfig) { |
| 117 | throw Object.assign( |
| 118 | new Error( |
| 119 | '--allow-scripts is not allowed in project-scoped installs. ' + |
| 120 | 'Add the entries to the "allowScripts" field in package.json, ' + |
| 121 | 'or to .npmrc, instead.' |
| 122 | ), |
| 123 | { code: 'EALLOWSCRIPTS' } |
| 124 | ) |
| 125 | } |
| 126 | |
| 127 | // Project package.json is consulted only when the caller is operating |
| 128 | // inside a real project (not -g, not npx). |
| 129 | let pkgPolicy = null |
| 130 | if (!npm.global && !skipProjectConfig) { |
| 131 | try { |
| 132 | const { content } = await pkgJson.normalize(npm.prefix) |
| 133 | if (content?.allowScripts && typeof content.allowScripts === 'object') { |
| 134 | const entries = Object.entries(content.allowScripts) |
| 135 | if (entries.length > 0) { |
| 136 | pkgPolicy = Object.fromEntries(entries) |
| 137 | } |
| 138 | } |
| 139 | } catch (err) { |
| 140 | log.silly('allow-scripts', 'no package.json at prefix', err.message) |
| 141 | } |
| 142 | } |
| 143 | |
| 144 | // Validate each candidate layer: drop forbidden ranges, warn the user. |
| 145 | const cli = validatePolicy(cliPolicy, 'CLI flag') |
| 146 | const pkg = validatePolicy(pkgPolicy, 'package.json') |
| 147 | const rc = validatePolicy(npmrcPolicy, '.npmrc') |
| 148 | |
| 149 | // Apply RFC precedence. |
| 150 | if (cli) { |
| 151 | // Note: `pkg` is never set alongside `cli` here. Project package.json is |
| 152 | // only read when `!npm.global && !skipProjectConfig`, but in that same |
| 153 | // case a CLI policy throws above. With `npm.global` or skipProjectConfig |
| 154 | // set, package.json is never consulted. |
| 155 | if (rc) { |
| 156 | log.warn( |
| 157 | 'allow-scripts', |
| 158 | '.npmrc allow-scripts setting is being ignored because --allow-scripts was passed on the command line' |
| 159 | ) |
| 160 | } |
| 161 | return { policy: cli, source: 'cli' } |
| 162 | } |
| 163 | |
| 164 | if (pkg) { |
no test coverage detected
searching dependent graphs…