From 767d4078a16a4a8178e71e152aab03e5039c54e9 Mon Sep 17 00:00:00 2001 From: Adam Richardson Date: Fri, 11 Jan 2019 11:38:57 -0500 Subject: [PATCH 1/7] implement markDevOnlyEntries in PackageHoister so HoistManifests can be marked as dev-only --- src/package-hoister.js | 67 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/src/package-hoister.js b/src/package-hoister.js index 7df285936f..40f616ce7f 100644 --- a/src/package-hoister.js +++ b/src/package-hoister.js @@ -33,6 +33,7 @@ export class HoistManifest { this.isDirectRequire = isDirectRequire; this.isRequired = isRequired; this.isIncompatible = isIncompatible; + this.isDevOnly = null; this.loc = loc; this.pkg = pkg; @@ -54,6 +55,7 @@ export class HoistManifest { isRequired: boolean; isIncompatible: boolean; isDirectRequire: boolean; + isDevOnly: ?boolean; pkg: Manifest; loc: string; parts: Parts; @@ -726,6 +728,71 @@ export default class PackageHoister { }); } + /** + * Given the list of top-level production dependencies, earmark any hoisted packages that + * are transitive production dependencies by setting isDevOnly = false, and earmark any + * non-prod dependencies with isDevOnly = true + */ + + markDevOnlyEntries(prodDepPatterns: Array) { + // a hoisted package is dev-only if it is not a transitive dependency of any top-level + // prod dependency; first, we mark all trees as dev-only, then we walk the trees starting + // from the top-level prod dependencies, marking any packages we encounter as non-dev-only + + for (const [_, info] of this.tree.entries()) { + info.isDevOnly = true; + } + + // queue of trees to visit + const toVisit: Array = []; + + // dedupe + prodDepPatterns = this.resolver.dedupePatterns(prodDepPatterns).sort(); + + // enumerate top-level production dependencies + for (const pattern of prodDepPatterns) { + const pkg = this.resolver.getStrictResolvedPattern(pattern); + const info = this.tree.get(pkg.name); + invariant(info && this._isTopPackage(info), 'expected a top-level dependency'); + + // mark and enqueue + info.isDevOnly = false; + info.addHistory(`Mark as a top-level production dependency`); + toVisit.push(info); + } + + while (toVisit.length > 0) { + const info = toVisit.shift(); + invariant(!info.isDevOnly, 'expected a (transitive) production dependency'); + + const ref = info.pkg._reference; + invariant(ref, 'expected reference'); + + // info is a transitive production dependency, and hence any of its non-dev + // dependencies are themselves transitive production dependencies + + for (const depPattern of ref.dependencies) { + const depinfo = this._lookupDependency(info, depPattern); + + if (!depinfo) { + continue; + } + + // skip depinfo if it has already been earmarked as a transitive production dependency + if (!depinfo.isDevOnly) { + continue; + } + + // earmark depinfo as a transitive production dependency + depinfo.isDevOnly = false; + depinfo.addHistory(`Mark as a production dependency, because it is dependend on by ${info.key}`); + + // enqueue depinfo so we can process its dependencies + toVisit.push(depinfo); + } + } + } + _getDependentWorkspaces( parent: HoistManifest, allowDevDeps: boolean = true, From 068e7133a93805f20ddb636eeffaa1319060223e Mon Sep 17 00:00:00 2001 From: Adam Richardson Date: Fri, 11 Jan 2019 11:40:11 -0500 Subject: [PATCH 2/7] implement plumbing for HoistedManifest isDevOnly in linker/hoisted tree builder --- src/hoisted-tree-builder.js | 5 ++++- src/package-hoister.js | 4 ++-- src/package-linker.js | 13 +++++++++++-- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/hoisted-tree-builder.js b/src/hoisted-tree-builder.js index e8f1b2c50a..9f6c46f537 100644 --- a/src/hoisted-tree-builder.js +++ b/src/hoisted-tree-builder.js @@ -11,6 +11,7 @@ export type HoistedTree = { version: string, manifest: HoistManifest, children?: HoistedTrees, + isDevOnly: boolean, }; export type HoistedTrees = Array; @@ -23,11 +24,12 @@ export async function buildTree( resolver: PackageResolver, linker: PackageLinker, patterns: Array, + devDepPatterns: Array, ignoreHoisted?: boolean, ): Promise { const treesByKey = {}; const trees = []; - const flatTree = await linker.getFlatHoistedTree(patterns); + const flatTree = await linker.getFlatHoistedTree(patterns, null, devDepPatterns); // If using workspaces, filter out the virtual manifest const {workspaceLayout} = resolver; @@ -61,6 +63,7 @@ export async function buildTree( version: info.pkg.version, children, manifest: info, + isDevOnly: info.isDevOnly, }; } diff --git a/src/package-hoister.js b/src/package-hoister.js index 40f616ce7f..88a71de6db 100644 --- a/src/package-hoister.js +++ b/src/package-hoister.js @@ -753,11 +753,11 @@ export default class PackageHoister { for (const pattern of prodDepPatterns) { const pkg = this.resolver.getStrictResolvedPattern(pattern); const info = this.tree.get(pkg.name); - invariant(info && this._isTopPackage(info), 'expected a top-level dependency'); + invariant(info, `expected ${pattern} to be present in the tree`); // mark and enqueue info.isDevOnly = false; - info.addHistory(`Mark as a top-level production dependency`); + info.addHistory('Mark as a top-level production dependency'); toVisit.push(info); } diff --git a/src/package-linker.js b/src/package-linker.js index 0a8a8931a7..3ee44c4846 100644 --- a/src/package-linker.js +++ b/src/package-linker.js @@ -204,14 +204,23 @@ export default class PackageLinker { getFlatHoistedTree( patterns: Array, - workspaceLayout?: WorkspaceLayout, + workspaceLayout: ?WorkspaceLayout, + devDepPatterns: ?Array, {ignoreOptional}: {ignoreOptional: ?boolean} = {}, ): HoistManifestTuples { const hoister = new PackageHoister(this.config, this.resolver, {ignoreOptional, workspaceLayout}); + hoister.seed(patterns); if (this.config.focus) { hoister.markShallowWorkspaceEntries(); } + + if (devDepPatterns && devDepPatterns.length > 0) { + const devDepPatternSet = new Set(devDepPatterns); + const prodDepPatterns = patterns.filter(pattern => !devDepPatternSet.has(pattern)); + hoister.markDevOnlyEntries(prodDepPatterns); + } + return hoister.init(); } @@ -220,7 +229,7 @@ export default class PackageLinker { workspaceLayout?: WorkspaceLayout, {linkDuplicates, ignoreOptional}: {linkDuplicates: ?boolean, ignoreOptional: ?boolean} = {}, ): Promise { - let flatTree = this.getFlatHoistedTree(patterns, workspaceLayout, {ignoreOptional}); + let flatTree = this.getFlatHoistedTree(patterns, workspaceLayout, null, {ignoreOptional}); // sorted tree makes file creation and copying not to interfere with each other flatTree = flatTree.sort(function(dep1, dep2): number { return dep1[0].localeCompare(dep2[0]); From 7e598c4b61ef1368613971bcf3f54bac71db8cbc Mon Sep 17 00:00:00 2001 From: Adam Richardson Date: Fri, 11 Jan 2019 11:40:45 -0500 Subject: [PATCH 3/7] distinguish dev-only from prod hoisted packages in audit --- src/cli/commands/audit.js | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/cli/commands/audit.js b/src/cli/commands/audit.js index ccb798d4cd..a1615a67c2 100644 --- a/src/cli/commands/audit.js +++ b/src/cli/commands/audit.js @@ -20,6 +20,7 @@ export type AuditNode = { integrity: ?string, requires: Object, dependencies: {[string]: AuditNode}, + dev: boolean, }; export type AuditTree = AuditNode & { @@ -121,6 +122,14 @@ export function hasWrapper(commander: Object, args: Array): boolean { return true; } +export function getDevDeps(manifest: Object): Array { + if (manifest.devDependencies) { + return Object.keys(manifest.devDependencies).map(key => `${key}@${manifest.devDependencies[key]}`); + } else { + return []; + } +} + export async function run(config: Config, reporter: Reporter, flags: Object, args: Array): Promise { const audit = new Audit(config, reporter); const lockfile = await Lockfile.fromDirectory(config.lockfileFolder, reporter); @@ -178,6 +187,7 @@ export default class Audit { integrity: pkg._remote ? pkg._remote.integrity || '' : '', requires, dependencies: {}, + dev: !!node.isDevOnly, }; if (node.children) { this._mapHoistedNodes(auditNode.dependencies[node.name], node.children); @@ -202,6 +212,7 @@ export default class Audit { ), integrity: undefined, dependencies: {}, + dev: false, }; this._mapHoistedNodes(auditTree, hoistedTrees); @@ -257,7 +268,7 @@ export default class Audit { patterns: Array, ): Promise { this._insertWorkspacePackagesIntoManifest(manifest, resolver); - const hoistedTrees = await hoistedTreeBuilder(resolver, linker, patterns); + const hoistedTrees = await hoistedTreeBuilder(resolver, linker, patterns, getDevDeps(manifest)); const auditTree = this._mapHoistedTreesToAuditTree(manifest, hoistedTrees); this.auditData = await this._fetchAudit(auditTree); return this.auditData.metadata.vulnerabilities; From f6b7ee0f2f797236311f52f033c381fe8b147934 Mon Sep 17 00:00:00 2001 From: Adam Richardson Date: Fri, 11 Jan 2019 13:33:13 -0500 Subject: [PATCH 4/7] fix audit specs --- __tests__/commands/audit.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/__tests__/commands/audit.js b/__tests__/commands/audit.js index d24436c1c5..5eb34e19f4 100644 --- a/__tests__/commands/audit.js +++ b/__tests__/commands/audit.js @@ -68,6 +68,7 @@ test.concurrent('sends correct dependency map to audit api for single dependency 'brace-expansion': '^1.0.0', }, dependencies: {}, + dev: false, }, 'brace-expansion': { version: '1.1.11', @@ -77,21 +78,25 @@ test.concurrent('sends correct dependency map to audit api for single dependency 'concat-map': '0.0.1', }, dependencies: {}, + dev: false, }, 'balanced-match': { version: '1.0.0', integrity: 'sha1-ibTRmasr7kneFk6gK4nORi1xt2c=', requires: {}, dependencies: {}, + dev: false, }, 'concat-map': { version: '0.0.1', integrity: 'sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=', requires: {}, dependencies: {}, + dev: false, }, }, version: '0.0.0', + dev: false, }; return runAudit([], {}, 'single-vulnerable-dep-installed', async config => { @@ -141,8 +146,10 @@ test.concurrent('sends correct dependency map to audit api for private package.' integrity: 'sha512-XI5MPzVNApjAyhQzphX8BkmKsKUxD4LdyK24iZeQGinBN9yTQT3bFlCBy/aVx2HrNcqQGsdot8ghrjyrvMCoEA==', requires: {}, dependencies: {}, + dev: false, }, }, + dev: false, }; return runAudit([], {}, 'private-package', async config => { @@ -212,12 +219,14 @@ test.concurrent('sends correct dependency map to audit api for workspaces.', () dependencies: { 'balanced-match': { dependencies: {}, + dev: false, integrity: 'sha1-ibTRmasr7kneFk6gK4nORi1xt2c=', requires: {}, version: '1.0.0', }, 'brace-expansion': { dependencies: {}, + dev: false, integrity: 'sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==', requires: { 'balanced-match': '^1.0.0', @@ -227,12 +236,14 @@ test.concurrent('sends correct dependency map to audit api for workspaces.', () }, 'concat-map': { dependencies: {}, + dev: false, integrity: 'sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=', requires: {}, version: '0.0.1', }, minimatch: { dependencies: {}, + dev: false, integrity: 'sha1-UjYVelHk8ATBd/s8Un/33Xjw74M=', requires: { 'brace-expansion': '^1.0.0', @@ -241,6 +252,7 @@ test.concurrent('sends correct dependency map to audit api for workspaces.', () }, prj1: { dependencies: {}, + dev: false, integrity: '', requires: { minimatch: '3.0.0', @@ -256,6 +268,7 @@ test.concurrent('sends correct dependency map to audit api for workspaces.', () prj1: '0.0.0', }, version: '1.0.0', + dev: false, }; return runAudit([], {}, 'workspace', async config => { From fc6ee1dc5b41784009987ded01bc3aea4ee0bef2 Mon Sep 17 00:00:00 2001 From: Adam Richardson Date: Fri, 11 Jan 2019 14:00:49 -0500 Subject: [PATCH 5/7] spec out yarn audit correctly distinguishing dev and prod vulnerabilities --- __tests__/commands/audit.js | 40 ++++++ .../audit-api-response.json | 132 ++++++++++++++++++ .../dev-and-prod-vulnerabilities/package.json | 10 ++ .../dev-and-prod-vulnerabilities/yarn.lock | 13 ++ 4 files changed, 195 insertions(+) create mode 100644 __tests__/fixtures/audit/dev-and-prod-vulnerabilities/audit-api-response.json create mode 100644 __tests__/fixtures/audit/dev-and-prod-vulnerabilities/package.json create mode 100644 __tests__/fixtures/audit/dev-and-prod-vulnerabilities/yarn.lock diff --git a/__tests__/commands/audit.js b/__tests__/commands/audit.js index 5eb34e19f4..b19d0d1e1b 100644 --- a/__tests__/commands/audit.js +++ b/__tests__/commands/audit.js @@ -173,6 +173,46 @@ test('calls reporter auditSummary with correct data for private package', () => }); }); +test.concurrent('distinguishes dev and prod transitive dependencies in audit request and result', () => { + const expectedApiPost = { + "name": "foo", + "version": "1.0.0", + "install": [], + "remove": [], + "metadata": {}, + "requires": { + "mime": "1.4.0", + "hoek": "4.2.0" + }, + "dependencies": { + "mime": { + "version": "1.4.0", + "integrity": "sha512-n9ChLv77+QQEapYz8lV+rIZAW3HhAPW2CXnzb1GN5uMkuczshwvkW7XPsbzU0ZQN3sP47Er2KVkp2p3KyqZKSQ==", + "requires": {}, + "dependencies": {}, + "dev": false + }, + "hoek": { + "version": "4.2.0", + "integrity": "sha512-v0XCLxICi9nPfYrS9RL8HbYnXi9obYAeLbSP00BmnZwCK9+Ih9WOjoZ8YoHCoav2csqn4FOz4Orldsy2dmDwmQ==", + "requires": {}, + "dependencies": {}, + "dev": true + } + }, + "dev": false + }; + + return runAudit([], {}, 'dev-and-prod-vulnerabilities', async (config, reporter) => { + const calledWithPipe = config.requestManager.request.mock.calls[0][0].body; + const calledWith = JSON.parse(await gunzip(calledWithPipe)); + expect(calledWith).toEqual(expectedApiPost); + + const apiResponse = getAuditResponse(config); + expect(reporter.auditSummary).toBeCalledWith(apiResponse.metadata); + }); +}); + describe('returns semantic exit codes', () => { beforeAll(() => { // mock unrelated stuff diff --git a/__tests__/fixtures/audit/dev-and-prod-vulnerabilities/audit-api-response.json b/__tests__/fixtures/audit/dev-and-prod-vulnerabilities/audit-api-response.json new file mode 100644 index 0000000000..70160e4fc6 --- /dev/null +++ b/__tests__/fixtures/audit/dev-and-prod-vulnerabilities/audit-api-response.json @@ -0,0 +1,132 @@ +{ + "actions": [ + { + "action": "install", + "module": "mime", + "target": "2.4.0", + "isMajor": true, + "resolves": [ + { + "id": 535, + "path": "mime", + "dev": false, + "optional": false, + "bundled": false + } + ] + }, + { + "action": "install", + "module": "hoek", + "target": "6.1.2", + "isMajor": true, + "resolves": [ + { + "id": 566, + "path": "hoek", + "dev": true, + "optional": false, + "bundled": false + } + ] + } + ], + "advisories": { + "535": { + "findings": [ + { + "version": "1.4.0", + "paths": [ + "mime" + ], + "dev": false, + "optional": false, + "bundled": false + } + ], + "id": 535, + "created": "2017-09-25T19:02:28.152Z", + "updated": "2018-04-09T00:38:22.785Z", + "deleted": null, + "title": "Regular Expression Denial of Service", + "found_by": { + "name": "Cristian-Alexandru Staicu" + }, + "reported_by": { + "name": "Cristian-Alexandru Staicu" + }, + "module_name": "mime", + "cves": [ + "CVE-2017-16138" + ], + "vulnerable_versions": "< 1.4.1 || > 2.0.0 < 2.0.3", + "patched_versions": ">= 1.4.1 < 2.0.0 || >= 2.0.3", + "overview": "Affected versions of `mime` are vulnerable to regular expression denial of service when a mime lookup is performed on untrusted user input.", + "recommendation": "Update to version 2.0.3 or later.", + "references": "[Issue #167](https://github.com/broofa/node-mime/issues/167)", + "access": "public", + "severity": "moderate", + "cwe": "CWE-400", + "metadata": { + "module_type": "Multi.Library", + "exploitability": 4, + "affected_components": "" + }, + "url": "https://npmjs.com/advisories/535" + }, + "566": { + "findings": [ + { + "version": "4.2.0", + "paths": [ + "hoek" + ], + "dev": true, + "optional": false, + "bundled": false + } + ], + "id": 566, + "created": "2018-04-20T21:25:58.421Z", + "updated": "2018-04-20T21:25:58.421Z", + "deleted": null, + "title": "Prototype pollution", + "found_by": { + "name": "HoLyVieR" + }, + "reported_by": { + "name": "HoLyVieR" + }, + "module_name": "hoek", + "cves": [], + "vulnerable_versions": "<= 4.2.0 || >= 5.0.0 < 5.0.3", + "patched_versions": "> 4.2.0 < 5.0.0 || >= 5.0.3", + "overview": "Versions of `hoek` prior to 4.2.1 and 5.0.3 are vulnerable to prototype pollution.\n\nThe `merge` function, and the `applyToDefaults` and `applyToDefaultsWithShallow` functions which leverage `merge` behind the scenes, are vulnerable to a prototype pollution attack when provided an _unvalidated_ payload created from a JSON string containing the `__proto__` property.\n\nThis can be demonstrated like so:\n\n```javascript\nvar Hoek = require('hoek');\nvar malicious_payload = '{\"__proto__\":{\"oops\":\"It works !\"}}';\n\nvar a = {};\nconsole.log(\"Before : \" + a.oops);\nHoek.merge({}, JSON.parse(malicious_payload));\nconsole.log(\"After : \" + a.oops);\n```\n\nThis type of attack can be used to overwrite existing properties causing a potential denial of service.", + "recommendation": "Update to version 4.2.1, 5.0.3 or later.", + "references": "", + "access": "public", + "severity": "moderate", + "cwe": "CWE-471", + "metadata": { + "module_type": "", + "exploitability": 5, + "affected_components": "" + }, + "url": "https://npmjs.com/advisories/566" + } + }, + "muted": [], + "metadata": { + "vulnerabilities": { + "info": 0, + "low": 0, + "moderate": 2, + "high": 0, + "critical": 0 + }, + "dependencies": 1, + "devDependencies": 1, + "optionalDependencies": 0, + "totalDependencies": 2 + } +} diff --git a/__tests__/fixtures/audit/dev-and-prod-vulnerabilities/package.json b/__tests__/fixtures/audit/dev-and-prod-vulnerabilities/package.json new file mode 100644 index 0000000000..f299785331 --- /dev/null +++ b/__tests__/fixtures/audit/dev-and-prod-vulnerabilities/package.json @@ -0,0 +1,10 @@ +{ + "name": "foo", + "version": "1.0.0", + "devDependencies": { + "hoek": "4.2.0" + }, + "dependencies": { + "mime": "1.4.0" + } +} diff --git a/__tests__/fixtures/audit/dev-and-prod-vulnerabilities/yarn.lock b/__tests__/fixtures/audit/dev-and-prod-vulnerabilities/yarn.lock new file mode 100644 index 0000000000..6acff70962 --- /dev/null +++ b/__tests__/fixtures/audit/dev-and-prod-vulnerabilities/yarn.lock @@ -0,0 +1,13 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +hoek@4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/hoek/-/hoek-4.2.0.tgz#72d9d0754f7fe25ca2d01ad8f8f9a9449a89526d" + integrity sha512-v0XCLxICi9nPfYrS9RL8HbYnXi9obYAeLbSP00BmnZwCK9+Ih9WOjoZ8YoHCoav2csqn4FOz4Orldsy2dmDwmQ== + +mime@1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/mime/-/mime-1.4.0.tgz#69e9e0db51d44f2a3b56e48b7817d7d137f1a343" + integrity sha512-n9ChLv77+QQEapYz8lV+rIZAW3HhAPW2CXnzb1GN5uMkuczshwvkW7XPsbzU0ZQN3sP47Er2KVkp2p3KyqZKSQ== From c09d940dab089f2fbfdff6c1873cd5fcb3aa6923 Mon Sep 17 00:00:00 2001 From: Adam Richardson Date: Fri, 11 Jan 2019 14:21:38 -0500 Subject: [PATCH 6/7] spec out package hoister markDevOnlyEntries behavior --- __tests__/package-hoister.js | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/__tests__/package-hoister.js b/__tests__/package-hoister.js index 1be7dbdc22..ab5b60d484 100644 --- a/__tests__/package-hoister.js +++ b/__tests__/package-hoister.js @@ -334,6 +334,34 @@ test('will hoist packages under subdirectories when they cannot hoist to root', expect(result).toContainPackage('d@1.0.0', atPath('a', 'node_modules', 'd')); }); +test('correctly labels dev-only hoisted packages with markDevOnlyEntries', () => { + const {packageHoister} = createTestFixture({ + 'foo@1.0.0': ['bar@1.0.0'], + 'bar@1.0.0': ['baz@1.0.0'], + 'bar@2.0.0': ['baz@2.0.0'], + 'baz@1.0.0': [], + 'baz@2.0.0': [] + }); + + packageHoister.seed(['foo@1.0.0', 'bar@2.0.0']); + packageHoister.markDevOnlyEntries(['foo@1.0.0']); + const result = packageHoister.init(); + + const isDevOnly = {}; + + result.forEach(tuple => { + const manifest = tuple[1]; + const pattern = manifest.pkg._reference.uid + isDevOnly[pattern] = manifest.isDevOnly; + }); + + expect(isDevOnly['foo@1.0.0']).toBe(false); + expect(isDevOnly['bar@1.0.0']).toBe(false); + expect(isDevOnly['baz@1.0.0']).toBe(false); + expect(isDevOnly['bar@2.0.0']).toBe(true); + expect(isDevOnly['baz@2.0.0']).toBe(true); +}); + describe('nohoist', () => { test('nohoist can be turned off by disable workspaces (workspaces-experimental)', () => { const {atPath, packageHoister, packageResolver} = createTestFixture( From a61f36eaf22acbc22775744e95bb4adadbc06330 Mon Sep 17 00:00:00 2001 From: Adam Richardson Date: Fri, 11 Jan 2019 14:54:45 -0500 Subject: [PATCH 7/7] eslint . --fix --- __tests__/commands/audit.js | 48 ++++++++++++++++++------------------ __tests__/package-hoister.js | 4 +-- 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/__tests__/commands/audit.js b/__tests__/commands/audit.js index b19d0d1e1b..bee69668bb 100644 --- a/__tests__/commands/audit.js +++ b/__tests__/commands/audit.js @@ -68,7 +68,7 @@ test.concurrent('sends correct dependency map to audit api for single dependency 'brace-expansion': '^1.0.0', }, dependencies: {}, - dev: false, + dev: false, }, 'brace-expansion': { version: '1.1.11', @@ -175,32 +175,32 @@ test('calls reporter auditSummary with correct data for private package', () => test.concurrent('distinguishes dev and prod transitive dependencies in audit request and result', () => { const expectedApiPost = { - "name": "foo", - "version": "1.0.0", - "install": [], - "remove": [], - "metadata": {}, - "requires": { - "mime": "1.4.0", - "hoek": "4.2.0" + name: 'foo', + version: '1.0.0', + install: [], + remove: [], + metadata: {}, + requires: { + mime: '1.4.0', + hoek: '4.2.0', }, - "dependencies": { - "mime": { - "version": "1.4.0", - "integrity": "sha512-n9ChLv77+QQEapYz8lV+rIZAW3HhAPW2CXnzb1GN5uMkuczshwvkW7XPsbzU0ZQN3sP47Er2KVkp2p3KyqZKSQ==", - "requires": {}, - "dependencies": {}, - "dev": false + dependencies: { + mime: { + version: '1.4.0', + integrity: 'sha512-n9ChLv77+QQEapYz8lV+rIZAW3HhAPW2CXnzb1GN5uMkuczshwvkW7XPsbzU0ZQN3sP47Er2KVkp2p3KyqZKSQ==', + requires: {}, + dependencies: {}, + dev: false, + }, + hoek: { + version: '4.2.0', + integrity: 'sha512-v0XCLxICi9nPfYrS9RL8HbYnXi9obYAeLbSP00BmnZwCK9+Ih9WOjoZ8YoHCoav2csqn4FOz4Orldsy2dmDwmQ==', + requires: {}, + dependencies: {}, + dev: true, }, - "hoek": { - "version": "4.2.0", - "integrity": "sha512-v0XCLxICi9nPfYrS9RL8HbYnXi9obYAeLbSP00BmnZwCK9+Ih9WOjoZ8YoHCoav2csqn4FOz4Orldsy2dmDwmQ==", - "requires": {}, - "dependencies": {}, - "dev": true - } }, - "dev": false + dev: false, }; return runAudit([], {}, 'dev-and-prod-vulnerabilities', async (config, reporter) => { diff --git a/__tests__/package-hoister.js b/__tests__/package-hoister.js index ab5b60d484..cdffa2e454 100644 --- a/__tests__/package-hoister.js +++ b/__tests__/package-hoister.js @@ -340,7 +340,7 @@ test('correctly labels dev-only hoisted packages with markDevOnlyEntries', () => 'bar@1.0.0': ['baz@1.0.0'], 'bar@2.0.0': ['baz@2.0.0'], 'baz@1.0.0': [], - 'baz@2.0.0': [] + 'baz@2.0.0': [], }); packageHoister.seed(['foo@1.0.0', 'bar@2.0.0']); @@ -351,7 +351,7 @@ test('correctly labels dev-only hoisted packages with markDevOnlyEntries', () => result.forEach(tuple => { const manifest = tuple[1]; - const pattern = manifest.pkg._reference.uid + const pattern = manifest.pkg._reference.uid; isDevOnly[pattern] = manifest.isDevOnly; });