npq 3.19.6 → 3.21.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/README.md CHANGED
@@ -78,6 +78,16 @@ brew install npq
78
78
  npq install express
79
79
  ```
80
80
 
81
+ ### Custom registries
82
+
83
+ NPQ reads standard npm registry configuration, including default and scoped registries, authentication, proxies, and TLS settings. You can also select a registry on the command line; the option is shared with the package manager used for installation:
84
+
85
+ ```sh
86
+ npq install @company/tool --registry=https://artifactory.example.com/artifactory/api/npm/npm-virtual/
87
+ ```
88
+
89
+ See [Custom registries](docs/feature/custom-registry.md) for `.npmrc` examples, configuration precedence, private CA setup, skipped capability behavior, and NPQ's no-fallback privacy guarantee.
90
+
81
91
  ### Embed in your day to day
82
92
 
83
93
  Since `npq` is a pre-step to ensure that the npm package you're installing is safe, you can safely embed it in your day-to-day `npm` usage so there's no need to remember to run `npq` explicitly.
@@ -130,15 +140,15 @@ Note: `npq` by default will offload all commands and their arguments to the `npm
130
140
  | --- | --- | ---
131
141
  | age | Will show a warning for a package if its age on npm is less than 22 days | Checks a package creation date, not a specific version
132
142
  | author | Validates the resolved version’s publisher (`_npmUser`), flags a **new** maintainer on the package (first publish by that email within 21 days), **dormant maintainer** gaps (warning if over ~6 months since their last publish on that package, error if over ~9 months), and very **recent** publishes | See [docs/feature/author-marshall.md](docs/feature/author-marshall.md)
133
- | downloads | Will show a warning for a package if its download count in the last month is less than 20
143
+ | downloads | Will show a warning for a package if its download count in the last month is less than 20 | Reports `not evaluated` for custom-registry packages instead of querying the public npm downloads service
134
144
  | readme | Will show a warning if a package has no README or it has been detected as a security placeholder package by npm staff
135
145
  | repo | Will show a warning if a package has been found without a valid and working repository URL | Checks the latest version for a repository URL
136
146
  | scripts | Will show a warning if a package has a pre/post install script which could potentially be malicious
137
147
  | snyk | Will show a warning if a package has been found with vulnerabilities in Snyk's database | For Snyk to work you need to either have the `snyk` npm package installed with a valid API token, or make the token available in the `SNYK_TOKEN` environment variable, and npq will use it
138
148
  | license | Will show a warning if a package has been found without a license field | Checks the latest version for a license
139
149
  | expired domains | Will show a warning if a package has been found with one of its maintainers having an email address that includes an expired domain | Checks a dependency version for a maintainer with an expired domain
140
- | signatures | Will compare the package's signature as it shows on the registry's pakument with the keys published on the npmjs.com registry
141
- | provenance | Will verify the package's attestations of provenance metadata for the published package, and **error** on [provenance regression](docs/feature/provenance.md) (an older semver had registry provenance metadata but the version you install does not)
150
+ | signatures | Will compare the package's signature as it shows on the registry's packument with signing keys published by the selected registry | Reports `not evaluated` if the selected registry does not expose signing keys
151
+ | provenance | Will verify the package's attestations of provenance metadata for the published package, and **error** on [provenance regression](docs/feature/provenance.md) (an older semver had registry provenance metadata but the version you install does not) | Reports `not evaluated` if the selected registry does not expose signing keys or attestations
142
152
  | version-maturity | Will show a warning if the specific version being installed was published less than 7 days ago | Helps identify recently published versions that may not have been reviewed by the community yet
143
153
  | newBin | Will show a warning if the package version being installed introduces a new command-line binary (via the `bin` field in `package.json`) that was not present in its previous version. | Helps identify potentially unexpected new executables being added to your `node_modules/.bin/` directory.
144
154
  | typosquatting | Will show a warning if the package name is similar to a popular package name, which could indicate a potential typosquatting attack. | Helps identify packages that may be trying to trick users into installing them by mimicking popular package names.
@@ -257,6 +267,10 @@ When auto-continue is disabled, npq will always prompt for explicit confirmation
257
267
 
258
268
  * This is not telemetry. NPQ does not collect any usage data. When auditing a package, NPQ fetches the maintainers/authors of the dependency and checks their email addresses to verify they are valid and not associated with expired domains. Expired domains can be abused by attackers for account takeover (ATO) attacks to compromise packages with malicious versions. Hence, NPQ may make DNS requests to domains like `gmail.com` or personal domains found in maintainer emails. Additionally, NPQ makes HTTP requests to `osv.dev` to fetch security vulnerability data (or uses Snyk if configured, as a prioritized option).
259
269
 
270
+ ## Documentation
271
+
272
+ - [Project documentation](./docs/README.md) - development, testing, architecture, and conventions.
273
+
260
274
  ## Contributing
261
275
 
262
276
  Please consult the [CONTRIBUTING](CONTRIBUTING.md) for guidelines on contributing to this project
package/bin/npq-hero.js CHANGED
@@ -12,6 +12,8 @@ const cliPrompt = require('../lib/helpers/cliPrompt.js')
12
12
  const { reportResults } = require('../lib/helpers/reportResults')
13
13
  const { Spinner } = require('../lib/helpers/cliSpinner')
14
14
  const { promiseThrottleHelper } = require('../lib/helpers/promiseThrottler')
15
+ const RegistryConfig = require('../lib/helpers/registryConfig')
16
+ const RegistryClient = require('../lib/helpers/registryClient')
15
17
 
16
18
  const PACKAGE_MANAGER_TOOL = process.env.NPQ_PKG_MGR
17
19
  const DISABLE_AUTO_CONTINUE = process.env.NPQ_DISABLE_AUTO_CONTINUE === 'true'
@@ -27,14 +29,17 @@ if (spinner) {
27
29
  spinner.start()
28
30
  }
29
31
 
30
- const marshall = new Marshall({
31
- pkgs: cliArgs.packages,
32
- progressManager: spinner,
33
- promiseThrottleHelper
34
- })
35
-
36
- marshall
37
- .process()
32
+ RegistryConfig.load({ argv: cliArgs.registryConfigArgs || [] })
33
+ .then((registryConfig) => {
34
+ const registryClient = new RegistryClient(registryConfig)
35
+ const marshall = new Marshall({
36
+ pkgs: cliArgs.packages,
37
+ registryClient,
38
+ progressManager: spinner,
39
+ promiseThrottleHelper
40
+ })
41
+ return marshall.process()
42
+ })
38
43
  .then((marshallResults) => {
39
44
  if (spinner) {
40
45
  spinner.stop()
@@ -46,12 +51,20 @@ marshall
46
51
  Object.hasOwn(results, 'countErrors') &&
47
52
  Object.hasOwn(results, 'countWarnings')
48
53
  ) {
49
- const { countErrors, countWarnings, useRichFormatting } = results
50
- const isErrors = countErrors > 0 || countWarnings > 0
54
+ const {
55
+ countErrors,
56
+ countWarnings,
57
+ countNotEvaluated = 0,
58
+ useRichFormatting
59
+ } = results
60
+ const hasFindings = countErrors > 0 || countWarnings > 0
61
+ const hasReportableResults = hasFindings || countNotEvaluated > 0
51
62
 
52
- if (isErrors) {
63
+ if (hasReportableResults) {
53
64
  console.log()
54
- console.log('Packages with issues found:')
65
+ console.log(
66
+ hasFindings ? 'Packages with issues found:' : 'Package checks not evaluated:'
67
+ )
55
68
 
56
69
  if (useRichFormatting) {
57
70
  console.log(results.resultsForPrettyPrint)
@@ -63,9 +76,10 @@ marshall
63
76
  }
64
77
 
65
78
  return {
66
- anyIssues: isErrors,
79
+ anyIssues: hasFindings,
67
80
  countErrors,
68
- countWarnings
81
+ countWarnings,
82
+ countNotEvaluated
69
83
  }
70
84
  }
71
85
  return undefined
package/bin/npq.js CHANGED
@@ -15,6 +15,8 @@ const cliPrompt = require('../lib/helpers/cliPrompt.js')
15
15
  const { reportResults } = require('../lib/helpers/reportResults')
16
16
  const { Spinner } = require('../lib/helpers/cliSpinner')
17
17
  const { promiseThrottleHelper } = require('../lib/helpers/promiseThrottler')
18
+ const RegistryConfig = require('../lib/helpers/registryConfig')
19
+ const RegistryClient = require('../lib/helpers/registryClient')
18
20
 
19
21
  const debug = util.debuglog('npq')
20
22
 
@@ -27,7 +29,12 @@ if (spinner) {
27
29
  spinner.start()
28
30
  }
29
31
 
30
- Promise.resolve()
32
+ let registryClient
33
+
34
+ RegistryConfig.load({ argv: cliArgs.registryConfigArgs || [] })
35
+ .then((registryConfig) => {
36
+ registryClient = new RegistryClient(registryConfig)
37
+ })
31
38
  .then(() => {
32
39
  if (cliArgs.packages.length === 0) {
33
40
  debug('\nNo packages specified, using project packages from package.json')
@@ -48,6 +55,7 @@ Promise.resolve()
48
55
 
49
56
  const marshall = new Marshall({
50
57
  pkgs: packages,
58
+ registryClient,
51
59
  progressManager: spinner,
52
60
  promiseThrottleHelper
53
61
  })
@@ -65,12 +73,20 @@ Promise.resolve()
65
73
  Object.hasOwn(results, 'countErrors') &&
66
74
  Object.hasOwn(results, 'countWarnings')
67
75
  ) {
68
- const { countErrors, countWarnings, useRichFormatting } = results
69
- const isErrors = countErrors > 0 || countWarnings > 0
70
-
71
- if (isErrors) {
76
+ const {
77
+ countErrors,
78
+ countWarnings,
79
+ countNotEvaluated = 0,
80
+ useRichFormatting
81
+ } = results
82
+ const hasFindings = countErrors > 0 || countWarnings > 0
83
+ const hasReportableResults = hasFindings || countNotEvaluated > 0
84
+
85
+ if (hasReportableResults) {
72
86
  console.log()
73
- console.log('Packages with issues found:')
87
+ console.log(
88
+ hasFindings ? 'Packages with issues found:' : 'Package checks not evaluated:'
89
+ )
74
90
 
75
91
  if (useRichFormatting) {
76
92
  console.log(results.resultsForPrettyPrint)
@@ -82,9 +98,10 @@ Promise.resolve()
82
98
  }
83
99
 
84
100
  return {
85
- anyIssues: isErrors,
101
+ anyIssues: hasFindings,
86
102
  countErrors,
87
- countWarnings
103
+ countWarnings,
104
+ countNotEvaluated
88
105
  }
89
106
  }
90
107
  return undefined