Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(audit) Report vulnerabilities in workspace package dependencies #6639

Merged
merged 3 commits into from Nov 7, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 5 additions & 1 deletion 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 All @@ -27,7 +31,7 @@ Please add one entry in this file for each change in Yarn's behavior. Use the sa
- Fixes an issue with how symlinks are setup into the cache on Windows

[#6621](https://github.com/yarnpkg/yarn/pull/6621) - [**Yoad Snapir**](https://github.com/yoadsn)

- Upgrades `inquirer`, fixing `upgrade-interactive` for users using both Node 10 and Windows

[#6635](https://github.com/yarnpkg/yarn/pull/6635) - [**Philipp Feigl**](https://github.com/pfeigl)
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,
);
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's too bad we have to hardcode the copy :(

}

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