Skip to content

Commit

Permalink
fix(audit) Report vulnerabilities in workspace package dependencies (#…
Browse files Browse the repository at this point in the history
…6639)

* added failing test for #6625

* fix(audit): Add workspaceAggregator dependencies to root manifest to be audited.

This change takes the packages that are included as part of the workspace and adds them to what is
sent to the npm audit api.

fixes #6625

* update changelog for PR 6639
  • Loading branch information
rally25rs authored and arcanis committed Nov 7, 2018
1 parent 124a2ef commit f8e42c5
Show file tree
Hide file tree
Showing 7 changed files with 140 additions and 1 deletion.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Expand Up @@ -6,6 +6,10 @@ Please add one entry in this file for each change in Yarn's behavior. Use the sa

**Important:** This release contains a cache bump. It will cause the very first install following the upgrade to take slightly more time, especially if you don't use the [Offline Mirror](https://yarnpkg.com/blog/2016/11/24/offline-mirror/) feature. After that everything will be back to normal.

- Fixes an issue with `yarn audit` when using workspaces

[#6625](https://github.com/yarnpkg/yarn/pull/6639) - [**Jeff Valore**](https://twitter.com/codingwithspike)

- Uses `NODE_OPTIONS` to instruct Node to load the PnP hook, instead of raw CLI arguments

**Caveat:** This change might cause issues for PnP users having a space inside their cwd (cf [nodejs/node#24065](https://github.com/nodejs/node/pull/24065))
Expand Down
60 changes: 59 additions & 1 deletion __tests__/commands/audit.js
Expand Up @@ -105,7 +105,7 @@ test('calls reporter auditAdvisory with correct data', () => {
});
});

// *** Test temporarily removed due to inability to correctly puggest actions to the user.
// *** Test temporarily removed due to inability to correctly suggest actions to the user.
// test('calls reporter auditAction with correct data', () => {
// return runAudit([], {}, 'single-vulnerable-dep-installed', (config, reporter) => {
// const apiResponse = getAuditResponse(config);
Expand Down Expand Up @@ -162,3 +162,61 @@ test('calls reporter auditSummary with correct data for private package', () =>
expect(reporter.auditSummary).toBeCalledWith(apiResponse.metadata);
});
});

test.concurrent('sends correct dependency map to audit api for workspaces.', () => {
const expectedApiPost = {
dependencies: {
'balanced-match': {
dependencies: {},
integrity: 'sha1-ibTRmasr7kneFk6gK4nORi1xt2c=',
requires: {},
version: '1.0.0',
},
'brace-expansion': {
dependencies: {},
integrity: 'sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==',
requires: {
'balanced-match': '^1.0.0',
'concat-map': '0.0.1',
},
version: '1.1.11',
},
'concat-map': {
dependencies: {},
integrity: 'sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=',
requires: {},
version: '0.0.1',
},
minimatch: {
dependencies: {},
integrity: 'sha1-UjYVelHk8ATBd/s8Un/33Xjw74M=',
requires: {
'brace-expansion': '^1.0.0',
},
version: '3.0.0',
},
prj1: {
dependencies: {},
integrity: '',
requires: {
minimatch: '3.0.0',
},
version: '0.0.0',
},
},
install: [],
metadata: {},
name: 'yarn-test',
remove: [],
requires: {
prj1: '0.0.0',
},
version: '1.0.0',
};

return runAudit([], {}, 'workspace', async config => {
const calledWithPipe = config.requestManager.request.mock.calls[0][0].body;
const calledWith = JSON.parse(await gunzip(calledWithPipe));
expect(calledWith).toEqual(expectedApiPost);
});
});
18 changes: 18 additions & 0 deletions __tests__/fixtures/audit/workspace/audit-api-response.json
@@ -0,0 +1,18 @@
{
"actions": [],
"advisories": {},
"muted": [],
"metadata": {
"vulnerabilities": {
"info": 0,
"low": 0,
"moderate": 0,
"high": 0,
"critical": 0
},
"dependencies": 0,
"devDependencies": 0,
"optionalDependencies": 0,
"totalDependencies": 0
}
}
8 changes: 8 additions & 0 deletions __tests__/fixtures/audit/workspace/package.json
@@ -0,0 +1,8 @@
{
"name": "yarn-test",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"private": true,
"workspaces": ["packages/*"]
}
8 changes: 8 additions & 0 deletions __tests__/fixtures/audit/workspace/packages/prj1/package.json
@@ -0,0 +1,8 @@
{
"name": "prj1",
"private": true,
"version": "0.0.0",
"dependencies": {
"minimatch": "3.0.0"
}
}
28 changes: 28 additions & 0 deletions __tests__/fixtures/audit/workspace/yarn.lock
@@ -0,0 +1,28 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1


balanced-match@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c=

brace-expansion@^1.0.0:
version "1.1.11"
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==
dependencies:
balanced-match "^1.0.0"
concat-map "0.0.1"

concat-map@0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=

minimatch@3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.0.tgz#5236157a51e4f004c177fb3c527ff7dd78f0ef83"
integrity sha1-UjYVelHk8ATBd/s8Un/33Xjw74M=
dependencies:
brace-expansion "^1.0.0"
15 changes: 15 additions & 0 deletions src/cli/commands/audit.js
Expand Up @@ -229,12 +229,27 @@ export default class Audit {
return responseJson;
}

_insertWorkspacePackagesIntoManifest(manifest: Object, resolver: PackageResolver) {
if (resolver.workspaceLayout) {
const workspaceAggregatorName = resolver.workspaceLayout.virtualManifestName;
const workspaceManifest = resolver.workspaceLayout.workspaces[workspaceAggregatorName].manifest;

manifest.dependencies = Object.assign(manifest.dependencies || {}, workspaceManifest.dependencies);
manifest.devDependencies = Object.assign(manifest.devDependencies || {}, workspaceManifest.devDependencies);
manifest.optionalDependencies = Object.assign(
manifest.optionalDependencies || {},
workspaceManifest.optionalDependencies,
);
}
}

async performAudit(
manifest: Object,
resolver: PackageResolver,
linker: PackageLinker,
patterns: Array<string>,
): Promise<AuditVulnerabilityCounts> {
this._insertWorkspacePackagesIntoManifest(manifest, resolver);
const hoistedTrees = await hoistedTreeBuilder(resolver, linker, patterns);
const auditTree = this._mapHoistedTreesToAuditTree(manifest, hoistedTrees);
this.auditData = await this._fetchAudit(auditTree);
Expand Down

0 comments on commit f8e42c5

Please sign in to comment.