Skip to content

Commit

Permalink
feat(query): add :vuln pseudo selector
Browse files Browse the repository at this point in the history
  • Loading branch information
wraithgar committed Feb 6, 2024
1 parent 343d47a commit 737e54f
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 1 deletion.
7 changes: 6 additions & 1 deletion docs/lib/content/using-npm/dependency-selectors.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ The [`npm query`](/commands/npm-query) command exposes a new dependency selector
- Unlocks the ability to answer complex, multi-faceted questions about dependencies, their relationships & associative metadata
- Consolidates redundant logic of similar query commands in `npm` (ex. `npm fund`, `npm ls`, `npm outdated`, `npm audit` ...)

### Dependency Selector Syntax `v1.0.0`
### Dependency Selector Syntax

#### Overview:

Expand Down Expand Up @@ -62,6 +62,7 @@ The [`npm query`](/commands/npm-query) command exposes a new dependency selector
- `:path(<path>)` [glob](https://www.npmjs.com/package/glob) matching based on dependencies path relative to the project
- `:type(<type>)` [based on currently recognized types](https://github.com/npm/npm-package-arg#result-object)
- `:outdated(<type>)` when a dependency is outdated
- `:vuln` when a dependency has a known vulnerability

##### `:semver(<spec>, [selector], [function])`

Expand Down Expand Up @@ -101,6 +102,10 @@ Some examples:
- `:root > :outdated(major)` returns every direct dependency that has a new semver major release
- `.prod:outdated(in-range)` returns production dependencies that have a new release that satisfies at least one of its edges in

##### `:vuln`

The `:vuln` pseudo selector retrieves data from the registry and returns information about which if your dependencies has a known vulnerability. Only dependencies whose current version matches a vulnerability will be returned. For example if you have `[email protected]` in your tree, a vulnerability for `semver` which affects versions `<=6.3.1` will not match.

#### [Attribute Selectors](https://developer.mozilla.org/en-US/docs/Web/CSS/Attribute_selectors)

The attribute selector evaluates the key/value pairs in `package.json` if they are `String`s.
Expand Down
38 changes: 38 additions & 0 deletions workspaces/arborist/lib/query-selector-all.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ const { minimatch } = require('minimatch')
const npa = require('npm-package-arg')
const pacote = require('pacote')
const semver = require('semver')
const fetch = require('npm-registry-fetch')

// handle results for parsed query asts, results are stored in a map that has a
// key that points to each ast selector node and stores the resulting array of
Expand Down Expand Up @@ -432,6 +433,43 @@ class Results {
return this.initialItems.filter(node => node.target.edgesIn.size > 1)
}

async vulnPseudo () {

Check failure on line 436 in workspaces/arborist/lib/query-selector-all.js

View workflow job for this annotation

GitHub Actions / Lint

Block must not be padded by blank lines

if (!this.initialItems.length) {
return this.initialItems
}
const packages = {}
// We have to map the items twice, once to get the request, and a second time to filter off the results of that request
this.initialItems.map((node) => {
if (node.isProjectRoot || node.package.private) {
return
}
if (!packages[node.name]) {
packages[node.name] = []
}
if (!packages[node.name].includes(node.version)) {
packages[node.name].push(node.version)
}
})
const res = await fetch('/-/npm/v1/security/advisories/bulk', {
...this.flatOptions,
registry: this.flatOptions.auditRegistry || this.flatOptions.registry,
method: 'POST',
gzip: true,
body: packages,
})
const advisories = await res.json()
return this.initialItems.filter(item => {
if (advisories[item.name]) {
item.queryContext = {
advisories: advisories[item.name]

Check failure on line 465 in workspaces/arborist/lib/query-selector-all.js

View workflow job for this annotation

GitHub Actions / Lint

Missing trailing comma
}
return true
}
return false
})
}

async outdatedPseudo () {
const { outdatedKind = 'any' } = this.currentAstNode

Expand Down
9 changes: 9 additions & 0 deletions workspaces/arborist/test/query-selector-all.js
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,11 @@ t.test('query-selector-all', async t => {
nock.enableNetConnect()
})

nock('https://registry.npmjs.org')
.post('/-/npm/v1/security/advisories/bulk')
.reply(200, {
foo: [{ id: 'test-vuln' }]

Check failure on line 105 in workspaces/arborist/test/query-selector-all.js

View workflow job for this annotation

GitHub Actions / Lint

Missing trailing comma
})
for (const [pkg, versions] of Object.entries(packumentStubs)) {
nock('https://registry.npmjs.org')
.persist()
Expand Down Expand Up @@ -842,6 +847,10 @@ t.test('query-selector-all', async t => {
], { before: yesterday }],
[':outdated(nonsense)', [], { before: yesterday }], // again, no results here ever

// vuln pseudo
[':vuln', ['[email protected]']],
['#nomatch:vuln', []], // no network requests are made if the result set is empty

// attr pseudo
[':attr([name=dasher])', ['[email protected]']],
[':attr(dependencies, [bar="^1.0.0"])', ['[email protected]']],
Expand Down

0 comments on commit 737e54f

Please sign in to comment.