From 0034661058817dabaee7c2a92233a681c5ec7df0 Mon Sep 17 00:00:00 2001 From: Rhys Arkins Date: Sun, 15 Sep 2024 06:38:19 +0200 Subject: [PATCH 1/8] refactor: use vulnerabilityFixVersion for github alerts --- lib/config/validation.ts | 1 + .../__snapshots__/vulnerability.spec.ts.snap | 6 +- lib/workers/repository/init/vulnerability.ts | 6 +- .../repository/process/lookup/index.spec.ts | 67 +++++++++++++++++++ .../repository/process/lookup/index.ts | 34 ++++++++++ .../repository/process/lookup/types.ts | 2 + 6 files changed, 108 insertions(+), 8 deletions(-) diff --git a/lib/config/validation.ts b/lib/config/validation.ts index 620cbe190d5242..fdcf487a20a52f 100644 --- a/lib/config/validation.ts +++ b/lib/config/validation.ts @@ -64,6 +64,7 @@ const ignoredNodes = [ 'vulnerabilityAlertsOnly', 'vulnerabilityAlert', 'isVulnerabilityAlert', + 'vulnerabilityFixVersion', // not intended to be used by end users but may be by Mend apps 'copyLocalLibs', // deprecated - functionality is now enabled by default 'prBody', // deprecated 'minimumConfidence', // undocumented feature flag diff --git a/lib/workers/repository/init/__snapshots__/vulnerability.spec.ts.snap b/lib/workers/repository/init/__snapshots__/vulnerability.spec.ts.snap index ae46fd5e4c4f06..d42cf0cd1f76ab 100644 --- a/lib/workers/repository/init/__snapshots__/vulnerability.spec.ts.snap +++ b/lib/workers/repository/init/__snapshots__/vulnerability.spec.ts.snap @@ -3,7 +3,6 @@ exports[`workers/repository/init/vulnerability detectVulnerabilityAlerts() returns go alerts 1`] = ` [ { - "allowedVersions": "1.8.3", "force": { "branchTopic": "{{{datasource}}}-{{{depNameSanitized}}}-vulnerability", "commitMessageSuffix": "[SECURITY]", @@ -30,6 +29,7 @@ exports[`workers/repository/init/vulnerability detectVulnerabilityAlerts() retur go", ], + "vulnerabilityFixVersion": "1.8.3", }, ] `; @@ -37,7 +37,6 @@ go", exports[`workers/repository/init/vulnerability detectVulnerabilityAlerts() returns maven alerts 1`] = ` [ { - "allowedVersions": "2.7.9.4", "force": { "branchTopic": "{{{datasource}}}-{{{depNameSanitized}}}-vulnerability", "commitMessageSuffix": "[SECURITY]", @@ -64,6 +63,7 @@ exports[`workers/repository/init/vulnerability detectVulnerabilityAlerts() retur An issue was discovered in FasterXML jackson-databind prior to 2.7.9.4, 2.8.11.2, and 2.9.6. When Default Typing is enabled (either globally or for a specific property), the service has the Jodd-db jar (for database access for the Jodd framework) in the classpath, and an attacker can provide an LDAP service to access, it is possible to make the service execute a malicious payload.", ], + "vulnerabilityFixVersion": "2.7.9.4", }, ] `; @@ -71,7 +71,6 @@ An issue was discovered in FasterXML jackson-databind prior to 2.7.9.4, 2.8.11.2 exports[`workers/repository/init/vulnerability detectVulnerabilityAlerts() returns pip alerts 1`] = ` [ { - "allowedVersions": "==2.2.1.0", "force": { "branchTopic": "{{{datasource}}}-{{{depNameSanitized}}}-vulnerability", "commitMessageSuffix": "[SECURITY]", @@ -113,6 +112,7 @@ Ansible before version 2.2.0 fails to properly sanitize fact variables sent from Ansible before versions 2.1.4, 2.2.1 is vulnerable to an improper input validation in Ansible's handling of data sent from client systems. An attacker with control over a client system being managed by Ansible and the ability to send facts back to the Ansible server could use this flaw to execute arbitrary code on the Ansible server using the Ansible server privileges.", ], + "vulnerabilityFixVersion": "2.2.1.0", }, ] `; diff --git a/lib/workers/repository/init/vulnerability.ts b/lib/workers/repository/init/vulnerability.ts index dbf8b04c6a7689..13f796020c9fe6 100644 --- a/lib/workers/repository/init/vulnerability.ts +++ b/lib/workers/repository/init/vulnerability.ts @@ -174,10 +174,6 @@ export async function detectVulnerabilityAlerts( logger.warn({ err }, 'Error generating vulnerability PR notes'); } // TODO: types (#22198) - const allowedVersions = - datasource === PypiDatasource.id - ? `==${val.firstPatchedVersion!}` - : val.firstPatchedVersion; const matchFileNames = datasource === GoDatasource.id ? [fileName.replace('go.sum', 'go.mod')] @@ -191,7 +187,7 @@ export async function detectVulnerabilityAlerts( // Remediate only direct dependencies matchRule = { ...matchRule, - allowedVersions, + vulnerabilityFixVersion: val.firstPatchedVersion, prBodyNotes, isVulnerabilityAlert: true, force: { diff --git a/lib/workers/repository/process/lookup/index.spec.ts b/lib/workers/repository/process/lookup/index.spec.ts index 3c67849975f522..56d4b740c693c3 100644 --- a/lib/workers/repository/process/lookup/index.spec.ts +++ b/lib/workers/repository/process/lookup/index.spec.ts @@ -818,6 +818,73 @@ describe('workers/repository/process/lookup/index', () => { ]); }); + it('uses vulnerabilityFixVersion', async () => { + config.currentValue = '1.0.0'; + config.isVulnerabilityAlert = true; + config.vulnerabilityFixVersion = '1.1.0'; + config.packageName = 'q'; + config.datasource = NpmDatasource.id; + httpMock.scope('https://registry.npmjs.org').get('/q').reply(200, qJson); + + const { updates } = await Result.wrap( + lookup.lookupUpdates(config), + ).unwrapOrThrow(); + + expect(updates).toEqual([ + { + bucket: 'non-major', + newMajor: 1, + newMinor: 1, + newPatch: 0, + newValue: '1.1.0', + newVersion: '1.1.0', + releaseTimestamp: expect.any(String), + updateType: 'minor', + }, + ]); + }); + + it('ignores vulnerabilityFixVersion if not a version', async () => { + config.currentValue = '1.0.0'; + config.isVulnerabilityAlert = true; + config.vulnerabilityFixVersion = '1.1'; + config.packageName = 'q'; + config.datasource = NpmDatasource.id; + httpMock.scope('https://registry.npmjs.org').get('/q').reply(200, qJson); + + const { updates } = await Result.wrap( + lookup.lookupUpdates(config), + ).unwrapOrThrow(); + + expect(updates).toEqual([ + { + bucket: 'non-major', + newMajor: 1, + newMinor: 0, + newPatch: 1, + newValue: '1.0.1', + newVersion: '1.0.1', + releaseTimestamp: expect.any(String), + updateType: 'patch', + }, + ]); + }); + + it('returns no results if vulnerabilityFixVersion is too high', async () => { + config.currentValue = '1.0.0'; + config.isVulnerabilityAlert = true; + config.vulnerabilityFixVersion = '5.1.0'; + config.packageName = 'q'; + config.datasource = NpmDatasource.id; + httpMock.scope('https://registry.npmjs.org').get('/q').reply(200, qJson); + + const { updates } = await Result.wrap( + lookup.lookupUpdates(config), + ).unwrapOrThrow(); + + expect(updates).toBeEmptyArray(); + }); + it('supports minor and major upgrades for ranged versions', async () => { config.currentValue = '~0.4.0'; config.rangeStrategy = 'pin'; diff --git a/lib/workers/repository/process/lookup/index.ts b/lib/workers/repository/process/lookup/index.ts index c4167937ac1fd1..9b4ecc3a24a81d 100644 --- a/lib/workers/repository/process/lookup/index.ts +++ b/lib/workers/repository/process/lookup/index.ts @@ -372,6 +372,40 @@ export async function lookupUpdates( ); let shrinkedViaVulnerability = false; if (config.isVulnerabilityAlert) { + if (config.vulnerabilityFixVersion) { + res.vulnerabilityFixVersion = config.vulnerabilityFixVersion; + if (versioning.isVersion(config.vulnerabilityFixVersion)) { + // Filter out versions if the vulnerabilityFixVersion is higher + const fixedFilteredReleases = filteredReleases.filter( + (r) => + !versioning.isGreaterThan( + config.vulnerabilityFixVersion!, + r.version, + ), + ); + // Warn if this filtering results caused zero releases + if (fixedFilteredReleases.length === 0 && filteredReleases.length) { + logger.warn( + { + releases: filteredReleases, + vulnerabilityFixVersion: config.vulnerabilityFixVersion, + packageName: config.packageName, + }, + 'No releases satisfy vulnerabilityFixVersion', + ); + } + // Use the additionally filtered releases + filteredReleases = fixedFilteredReleases; + } else { + logger.warn( + { + vulnerabilityFixVersion: config.vulnerabilityFixVersion, + packageName: config.packageName, + }, + 'vulnerabilityFixVersion is not a version', + ); + } + } filteredReleases = filteredReleases.slice(0, 1); shrinkedViaVulnerability = true; logger.debug( diff --git a/lib/workers/repository/process/lookup/types.ts b/lib/workers/repository/process/lookup/types.ts index ed944ea253d5e9..aaec2a405d532e 100644 --- a/lib/workers/repository/process/lookup/types.ts +++ b/lib/workers/repository/process/lookup/types.ts @@ -49,6 +49,7 @@ export interface LookupUpdateConfig replacementNameTemplate?: string; replacementVersion?: string; extractVersion?: string; + vulnerabilityFixVersion?: string; } export interface UpdateResult { @@ -68,4 +69,5 @@ export interface UpdateResult { warnings: ValidationMessage[]; versioning?: string; currentVersionTimestamp?: string; + vulnerabilityFixVersion?: string; } From 0ba1edaebd85e36a0a328d5cb48e0d77ec18a4ba Mon Sep 17 00:00:00 2001 From: Rhys Arkins Date: Mon, 16 Sep 2024 06:06:02 +0200 Subject: [PATCH 2/8] handle vulnerabilityFixVersion as version or range --- .../repository/process/lookup/index.spec.ts | 56 ++++++++++++++++++- .../repository/process/lookup/index.ts | 25 ++++++--- 2 files changed, 71 insertions(+), 10 deletions(-) diff --git a/lib/workers/repository/process/lookup/index.spec.ts b/lib/workers/repository/process/lookup/index.spec.ts index 56d4b740c693c3..b129d8a4b89c29 100644 --- a/lib/workers/repository/process/lookup/index.spec.ts +++ b/lib/workers/repository/process/lookup/index.spec.ts @@ -818,7 +818,7 @@ describe('workers/repository/process/lookup/index', () => { ]); }); - it('uses vulnerabilityFixVersion', async () => { + it('uses vulnerabilityFixVersion when a version', async () => { config.currentValue = '1.0.0'; config.isVulnerabilityAlert = true; config.vulnerabilityFixVersion = '1.1.0'; @@ -844,10 +844,62 @@ describe('workers/repository/process/lookup/index', () => { ]); }); + it('takes a later release when vulnerabilityFixVersion does not exist', async () => { + config.currentValue = '1.0.0'; + config.isVulnerabilityAlert = true; + config.vulnerabilityFixVersion = '1.0.2'; + config.packageName = 'q'; + config.datasource = NpmDatasource.id; + httpMock.scope('https://registry.npmjs.org').get('/q').reply(200, qJson); + + const { updates } = await Result.wrap( + lookup.lookupUpdates(config), + ).unwrapOrThrow(); + + expect(updates).toEqual([ + { + bucket: 'non-major', + newMajor: 1, + newMinor: 1, + newPatch: 0, + newValue: '1.1.0', + newVersion: '1.1.0', + releaseTimestamp: expect.any(String), + updateType: 'minor', + }, + ]); + }); + + it('uses vulnerabilityFixVersion when a range', async () => { + config.currentValue = '1.0.0'; + config.isVulnerabilityAlert = true; + config.vulnerabilityFixVersion = '>= 1.1.0'; + config.packageName = 'q'; + config.datasource = NpmDatasource.id; + httpMock.scope('https://registry.npmjs.org').get('/q').reply(200, qJson); + + const { updates } = await Result.wrap( + lookup.lookupUpdates(config), + ).unwrapOrThrow(); + + expect(updates).toEqual([ + { + bucket: 'non-major', + newMajor: 1, + newMinor: 1, + newPatch: 0, + newValue: '1.1.0', + newVersion: '1.1.0', + releaseTimestamp: expect.any(String), + updateType: 'minor', + }, + ]); + }); + it('ignores vulnerabilityFixVersion if not a version', async () => { config.currentValue = '1.0.0'; config.isVulnerabilityAlert = true; - config.vulnerabilityFixVersion = '1.1'; + config.vulnerabilityFixVersion = 'abc'; config.packageName = 'q'; config.datasource = NpmDatasource.id; httpMock.scope('https://registry.npmjs.org').get('/q').reply(200, qJson); diff --git a/lib/workers/repository/process/lookup/index.ts b/lib/workers/repository/process/lookup/index.ts index 9b4ecc3a24a81d..69cdc2016c552b 100644 --- a/lib/workers/repository/process/lookup/index.ts +++ b/lib/workers/repository/process/lookup/index.ts @@ -374,15 +374,24 @@ export async function lookupUpdates( if (config.isVulnerabilityAlert) { if (config.vulnerabilityFixVersion) { res.vulnerabilityFixVersion = config.vulnerabilityFixVersion; - if (versioning.isVersion(config.vulnerabilityFixVersion)) { + if (versioning.isValid(config.vulnerabilityFixVersion)) { // Filter out versions if the vulnerabilityFixVersion is higher - const fixedFilteredReleases = filteredReleases.filter( - (r) => - !versioning.isGreaterThan( - config.vulnerabilityFixVersion!, - r.version, - ), - ); + const fixedFilteredReleases = versioning.isVersion( + config.vulnerabilityFixVersion, + ) + ? filteredReleases.filter( + (r) => + !versioning.isGreaterThan( + config.vulnerabilityFixVersion!, + r.version, + ), + ) + : filteredReleases.filter((r) => + versioning.matches( + r.version, + config.vulnerabilityFixVersion!, + ), + ); // Warn if this filtering results caused zero releases if (fixedFilteredReleases.length === 0 && filteredReleases.length) { logger.warn( From bd1ac7199f0e1579f101e8fa99f2da1439fa94a0 Mon Sep 17 00:00:00 2001 From: Rhys Arkins Date: Mon, 16 Sep 2024 08:17:07 +0200 Subject: [PATCH 3/8] rename vulnerabilityFixVersion -> vulnerabilityFix --- lib/config/validation.ts | 2 +- .../__snapshots__/vulnerability.spec.ts.snap | 6 ++--- lib/workers/repository/init/vulnerability.ts | 2 +- .../repository/process/lookup/index.spec.ts | 20 +++++++-------- .../repository/process/lookup/index.ts | 25 ++++++++----------- .../repository/process/lookup/types.ts | 4 +-- 6 files changed, 28 insertions(+), 31 deletions(-) diff --git a/lib/config/validation.ts b/lib/config/validation.ts index fdcf487a20a52f..015806bcee561e 100644 --- a/lib/config/validation.ts +++ b/lib/config/validation.ts @@ -64,7 +64,7 @@ const ignoredNodes = [ 'vulnerabilityAlertsOnly', 'vulnerabilityAlert', 'isVulnerabilityAlert', - 'vulnerabilityFixVersion', // not intended to be used by end users but may be by Mend apps + 'vulnerabilityFix', // not intended to be used by end users but may be by Mend apps 'copyLocalLibs', // deprecated - functionality is now enabled by default 'prBody', // deprecated 'minimumConfidence', // undocumented feature flag diff --git a/lib/workers/repository/init/__snapshots__/vulnerability.spec.ts.snap b/lib/workers/repository/init/__snapshots__/vulnerability.spec.ts.snap index d42cf0cd1f76ab..6a26f542b7c776 100644 --- a/lib/workers/repository/init/__snapshots__/vulnerability.spec.ts.snap +++ b/lib/workers/repository/init/__snapshots__/vulnerability.spec.ts.snap @@ -29,7 +29,7 @@ exports[`workers/repository/init/vulnerability detectVulnerabilityAlerts() retur go", ], - "vulnerabilityFixVersion": "1.8.3", + "vulnerabilityFix": "1.8.3", }, ] `; @@ -63,7 +63,7 @@ exports[`workers/repository/init/vulnerability detectVulnerabilityAlerts() retur An issue was discovered in FasterXML jackson-databind prior to 2.7.9.4, 2.8.11.2, and 2.9.6. When Default Typing is enabled (either globally or for a specific property), the service has the Jodd-db jar (for database access for the Jodd framework) in the classpath, and an attacker can provide an LDAP service to access, it is possible to make the service execute a malicious payload.", ], - "vulnerabilityFixVersion": "2.7.9.4", + "vulnerabilityFix": "2.7.9.4", }, ] `; @@ -112,7 +112,7 @@ Ansible before version 2.2.0 fails to properly sanitize fact variables sent from Ansible before versions 2.1.4, 2.2.1 is vulnerable to an improper input validation in Ansible's handling of data sent from client systems. An attacker with control over a client system being managed by Ansible and the ability to send facts back to the Ansible server could use this flaw to execute arbitrary code on the Ansible server using the Ansible server privileges.", ], - "vulnerabilityFixVersion": "2.2.1.0", + "vulnerabilityFix": "2.2.1.0", }, ] `; diff --git a/lib/workers/repository/init/vulnerability.ts b/lib/workers/repository/init/vulnerability.ts index 13f796020c9fe6..581adf874041e5 100644 --- a/lib/workers/repository/init/vulnerability.ts +++ b/lib/workers/repository/init/vulnerability.ts @@ -187,7 +187,7 @@ export async function detectVulnerabilityAlerts( // Remediate only direct dependencies matchRule = { ...matchRule, - vulnerabilityFixVersion: val.firstPatchedVersion, + vulnerabilityFix: val.firstPatchedVersion, prBodyNotes, isVulnerabilityAlert: true, force: { diff --git a/lib/workers/repository/process/lookup/index.spec.ts b/lib/workers/repository/process/lookup/index.spec.ts index b129d8a4b89c29..7d8eea9a249e55 100644 --- a/lib/workers/repository/process/lookup/index.spec.ts +++ b/lib/workers/repository/process/lookup/index.spec.ts @@ -818,10 +818,10 @@ describe('workers/repository/process/lookup/index', () => { ]); }); - it('uses vulnerabilityFixVersion when a version', async () => { + it('uses vulnerabilityFix when a version', async () => { config.currentValue = '1.0.0'; config.isVulnerabilityAlert = true; - config.vulnerabilityFixVersion = '1.1.0'; + config.vulnerabilityFix = '1.1.0'; config.packageName = 'q'; config.datasource = NpmDatasource.id; httpMock.scope('https://registry.npmjs.org').get('/q').reply(200, qJson); @@ -844,10 +844,10 @@ describe('workers/repository/process/lookup/index', () => { ]); }); - it('takes a later release when vulnerabilityFixVersion does not exist', async () => { + it('takes a later release when vulnerabilityFix does not exist', async () => { config.currentValue = '1.0.0'; config.isVulnerabilityAlert = true; - config.vulnerabilityFixVersion = '1.0.2'; + config.vulnerabilityFix = '1.0.2'; config.packageName = 'q'; config.datasource = NpmDatasource.id; httpMock.scope('https://registry.npmjs.org').get('/q').reply(200, qJson); @@ -870,10 +870,10 @@ describe('workers/repository/process/lookup/index', () => { ]); }); - it('uses vulnerabilityFixVersion when a range', async () => { + it('uses vulnerabilityFix when a range', async () => { config.currentValue = '1.0.0'; config.isVulnerabilityAlert = true; - config.vulnerabilityFixVersion = '>= 1.1.0'; + config.vulnerabilityFix = '>= 1.1.0'; config.packageName = 'q'; config.datasource = NpmDatasource.id; httpMock.scope('https://registry.npmjs.org').get('/q').reply(200, qJson); @@ -896,10 +896,10 @@ describe('workers/repository/process/lookup/index', () => { ]); }); - it('ignores vulnerabilityFixVersion if not a version', async () => { + it('ignores vulnerabilityFix if not a version', async () => { config.currentValue = '1.0.0'; config.isVulnerabilityAlert = true; - config.vulnerabilityFixVersion = 'abc'; + config.vulnerabilityFix = 'abc'; config.packageName = 'q'; config.datasource = NpmDatasource.id; httpMock.scope('https://registry.npmjs.org').get('/q').reply(200, qJson); @@ -922,10 +922,10 @@ describe('workers/repository/process/lookup/index', () => { ]); }); - it('returns no results if vulnerabilityFixVersion is too high', async () => { + it('returns no results if vulnerabilityFix is too high', async () => { config.currentValue = '1.0.0'; config.isVulnerabilityAlert = true; - config.vulnerabilityFixVersion = '5.1.0'; + config.vulnerabilityFix = '5.1.0'; config.packageName = 'q'; config.datasource = NpmDatasource.id; httpMock.scope('https://registry.npmjs.org').get('/q').reply(200, qJson); diff --git a/lib/workers/repository/process/lookup/index.ts b/lib/workers/repository/process/lookup/index.ts index 69cdc2016c552b..ffeec0853a8413 100644 --- a/lib/workers/repository/process/lookup/index.ts +++ b/lib/workers/repository/process/lookup/index.ts @@ -372,35 +372,32 @@ export async function lookupUpdates( ); let shrinkedViaVulnerability = false; if (config.isVulnerabilityAlert) { - if (config.vulnerabilityFixVersion) { - res.vulnerabilityFixVersion = config.vulnerabilityFixVersion; - if (versioning.isValid(config.vulnerabilityFixVersion)) { - // Filter out versions if the vulnerabilityFixVersion is higher + if (config.vulnerabilityFix) { + res.vulnerabilityFix = config.vulnerabilityFix; + if (versioning.isValid(config.vulnerabilityFix)) { + // Filter out versions if the vulnerabilityFix is higher const fixedFilteredReleases = versioning.isVersion( - config.vulnerabilityFixVersion, + config.vulnerabilityFix, ) ? filteredReleases.filter( (r) => !versioning.isGreaterThan( - config.vulnerabilityFixVersion!, + config.vulnerabilityFix!, r.version, ), ) : filteredReleases.filter((r) => - versioning.matches( - r.version, - config.vulnerabilityFixVersion!, - ), + versioning.matches(r.version, config.vulnerabilityFix!), ); // Warn if this filtering results caused zero releases if (fixedFilteredReleases.length === 0 && filteredReleases.length) { logger.warn( { releases: filteredReleases, - vulnerabilityFixVersion: config.vulnerabilityFixVersion, + vulnerabilityFix: config.vulnerabilityFix, packageName: config.packageName, }, - 'No releases satisfy vulnerabilityFixVersion', + 'No releases satisfy vulnerabilityFix', ); } // Use the additionally filtered releases @@ -408,10 +405,10 @@ export async function lookupUpdates( } else { logger.warn( { - vulnerabilityFixVersion: config.vulnerabilityFixVersion, + vulnerabilityFix: config.vulnerabilityFix, packageName: config.packageName, }, - 'vulnerabilityFixVersion is not a version', + 'vulnerabilityFix is not valid', ); } } diff --git a/lib/workers/repository/process/lookup/types.ts b/lib/workers/repository/process/lookup/types.ts index aaec2a405d532e..32de0dd3560b24 100644 --- a/lib/workers/repository/process/lookup/types.ts +++ b/lib/workers/repository/process/lookup/types.ts @@ -49,7 +49,7 @@ export interface LookupUpdateConfig replacementNameTemplate?: string; replacementVersion?: string; extractVersion?: string; - vulnerabilityFixVersion?: string; + vulnerabilityFix?: string; } export interface UpdateResult { @@ -69,5 +69,5 @@ export interface UpdateResult { warnings: ValidationMessage[]; versioning?: string; currentVersionTimestamp?: string; - vulnerabilityFixVersion?: string; + vulnerabilityFix?: string; } From 6ab5539eba9711c81f33e4935d866481d6fd2a60 Mon Sep 17 00:00:00 2001 From: Rhys Arkins Date: Tue, 17 Sep 2024 06:59:30 +0200 Subject: [PATCH 4/8] Rename back --- lib/config/validation.ts | 2 +- .../__snapshots__/vulnerability.spec.ts.snap | 6 ++--- lib/workers/repository/init/vulnerability.ts | 2 +- .../repository/process/lookup/index.spec.ts | 20 +++++++-------- .../repository/process/lookup/index.ts | 25 +++++++++++-------- .../repository/process/lookup/types.ts | 4 +-- 6 files changed, 31 insertions(+), 28 deletions(-) diff --git a/lib/config/validation.ts b/lib/config/validation.ts index 015806bcee561e..fdcf487a20a52f 100644 --- a/lib/config/validation.ts +++ b/lib/config/validation.ts @@ -64,7 +64,7 @@ const ignoredNodes = [ 'vulnerabilityAlertsOnly', 'vulnerabilityAlert', 'isVulnerabilityAlert', - 'vulnerabilityFix', // not intended to be used by end users but may be by Mend apps + 'vulnerabilityFixVersion', // not intended to be used by end users but may be by Mend apps 'copyLocalLibs', // deprecated - functionality is now enabled by default 'prBody', // deprecated 'minimumConfidence', // undocumented feature flag diff --git a/lib/workers/repository/init/__snapshots__/vulnerability.spec.ts.snap b/lib/workers/repository/init/__snapshots__/vulnerability.spec.ts.snap index 6a26f542b7c776..d42cf0cd1f76ab 100644 --- a/lib/workers/repository/init/__snapshots__/vulnerability.spec.ts.snap +++ b/lib/workers/repository/init/__snapshots__/vulnerability.spec.ts.snap @@ -29,7 +29,7 @@ exports[`workers/repository/init/vulnerability detectVulnerabilityAlerts() retur go", ], - "vulnerabilityFix": "1.8.3", + "vulnerabilityFixVersion": "1.8.3", }, ] `; @@ -63,7 +63,7 @@ exports[`workers/repository/init/vulnerability detectVulnerabilityAlerts() retur An issue was discovered in FasterXML jackson-databind prior to 2.7.9.4, 2.8.11.2, and 2.9.6. When Default Typing is enabled (either globally or for a specific property), the service has the Jodd-db jar (for database access for the Jodd framework) in the classpath, and an attacker can provide an LDAP service to access, it is possible to make the service execute a malicious payload.", ], - "vulnerabilityFix": "2.7.9.4", + "vulnerabilityFixVersion": "2.7.9.4", }, ] `; @@ -112,7 +112,7 @@ Ansible before version 2.2.0 fails to properly sanitize fact variables sent from Ansible before versions 2.1.4, 2.2.1 is vulnerable to an improper input validation in Ansible's handling of data sent from client systems. An attacker with control over a client system being managed by Ansible and the ability to send facts back to the Ansible server could use this flaw to execute arbitrary code on the Ansible server using the Ansible server privileges.", ], - "vulnerabilityFix": "2.2.1.0", + "vulnerabilityFixVersion": "2.2.1.0", }, ] `; diff --git a/lib/workers/repository/init/vulnerability.ts b/lib/workers/repository/init/vulnerability.ts index 581adf874041e5..13f796020c9fe6 100644 --- a/lib/workers/repository/init/vulnerability.ts +++ b/lib/workers/repository/init/vulnerability.ts @@ -187,7 +187,7 @@ export async function detectVulnerabilityAlerts( // Remediate only direct dependencies matchRule = { ...matchRule, - vulnerabilityFix: val.firstPatchedVersion, + vulnerabilityFixVersion: val.firstPatchedVersion, prBodyNotes, isVulnerabilityAlert: true, force: { diff --git a/lib/workers/repository/process/lookup/index.spec.ts b/lib/workers/repository/process/lookup/index.spec.ts index 7d8eea9a249e55..b129d8a4b89c29 100644 --- a/lib/workers/repository/process/lookup/index.spec.ts +++ b/lib/workers/repository/process/lookup/index.spec.ts @@ -818,10 +818,10 @@ describe('workers/repository/process/lookup/index', () => { ]); }); - it('uses vulnerabilityFix when a version', async () => { + it('uses vulnerabilityFixVersion when a version', async () => { config.currentValue = '1.0.0'; config.isVulnerabilityAlert = true; - config.vulnerabilityFix = '1.1.0'; + config.vulnerabilityFixVersion = '1.1.0'; config.packageName = 'q'; config.datasource = NpmDatasource.id; httpMock.scope('https://registry.npmjs.org').get('/q').reply(200, qJson); @@ -844,10 +844,10 @@ describe('workers/repository/process/lookup/index', () => { ]); }); - it('takes a later release when vulnerabilityFix does not exist', async () => { + it('takes a later release when vulnerabilityFixVersion does not exist', async () => { config.currentValue = '1.0.0'; config.isVulnerabilityAlert = true; - config.vulnerabilityFix = '1.0.2'; + config.vulnerabilityFixVersion = '1.0.2'; config.packageName = 'q'; config.datasource = NpmDatasource.id; httpMock.scope('https://registry.npmjs.org').get('/q').reply(200, qJson); @@ -870,10 +870,10 @@ describe('workers/repository/process/lookup/index', () => { ]); }); - it('uses vulnerabilityFix when a range', async () => { + it('uses vulnerabilityFixVersion when a range', async () => { config.currentValue = '1.0.0'; config.isVulnerabilityAlert = true; - config.vulnerabilityFix = '>= 1.1.0'; + config.vulnerabilityFixVersion = '>= 1.1.0'; config.packageName = 'q'; config.datasource = NpmDatasource.id; httpMock.scope('https://registry.npmjs.org').get('/q').reply(200, qJson); @@ -896,10 +896,10 @@ describe('workers/repository/process/lookup/index', () => { ]); }); - it('ignores vulnerabilityFix if not a version', async () => { + it('ignores vulnerabilityFixVersion if not a version', async () => { config.currentValue = '1.0.0'; config.isVulnerabilityAlert = true; - config.vulnerabilityFix = 'abc'; + config.vulnerabilityFixVersion = 'abc'; config.packageName = 'q'; config.datasource = NpmDatasource.id; httpMock.scope('https://registry.npmjs.org').get('/q').reply(200, qJson); @@ -922,10 +922,10 @@ describe('workers/repository/process/lookup/index', () => { ]); }); - it('returns no results if vulnerabilityFix is too high', async () => { + it('returns no results if vulnerabilityFixVersion is too high', async () => { config.currentValue = '1.0.0'; config.isVulnerabilityAlert = true; - config.vulnerabilityFix = '5.1.0'; + config.vulnerabilityFixVersion = '5.1.0'; config.packageName = 'q'; config.datasource = NpmDatasource.id; httpMock.scope('https://registry.npmjs.org').get('/q').reply(200, qJson); diff --git a/lib/workers/repository/process/lookup/index.ts b/lib/workers/repository/process/lookup/index.ts index ffeec0853a8413..67aa57d5ecf031 100644 --- a/lib/workers/repository/process/lookup/index.ts +++ b/lib/workers/repository/process/lookup/index.ts @@ -372,32 +372,35 @@ export async function lookupUpdates( ); let shrinkedViaVulnerability = false; if (config.isVulnerabilityAlert) { - if (config.vulnerabilityFix) { - res.vulnerabilityFix = config.vulnerabilityFix; - if (versioning.isValid(config.vulnerabilityFix)) { - // Filter out versions if the vulnerabilityFix is higher + if (config.vulnerabilityFixVersion) { + res.vulnerabilityFixVersion = config.vulnerabilityFixVersion; + if (versioning.isValid(config.vulnerabilityFixVersion)) { + // Filter out versions if the vulnerabilityFixVersion is higher const fixedFilteredReleases = versioning.isVersion( - config.vulnerabilityFix, + config.vulnerabilityFixVersion, ) ? filteredReleases.filter( (r) => !versioning.isGreaterThan( - config.vulnerabilityFix!, + config.vulnerabilityFixVersion!, r.version, ), ) : filteredReleases.filter((r) => - versioning.matches(r.version, config.vulnerabilityFix!), + versioning.matches( + r.version, + config.vulnerabilityFixVersion!, + ), ); // Warn if this filtering results caused zero releases if (fixedFilteredReleases.length === 0 && filteredReleases.length) { logger.warn( { releases: filteredReleases, - vulnerabilityFix: config.vulnerabilityFix, + vulnerabilityFixVersion: config.vulnerabilityFixVersion, packageName: config.packageName, }, - 'No releases satisfy vulnerabilityFix', + 'No releases satisfy vulnerabilityFixVersion', ); } // Use the additionally filtered releases @@ -405,10 +408,10 @@ export async function lookupUpdates( } else { logger.warn( { - vulnerabilityFix: config.vulnerabilityFix, + vulnerabilityFixVersion: config.vulnerabilityFixVersion, packageName: config.packageName, }, - 'vulnerabilityFix is not valid', + 'vulnerabilityFixVersion is not valid', ); } } diff --git a/lib/workers/repository/process/lookup/types.ts b/lib/workers/repository/process/lookup/types.ts index 32de0dd3560b24..aaec2a405d532e 100644 --- a/lib/workers/repository/process/lookup/types.ts +++ b/lib/workers/repository/process/lookup/types.ts @@ -49,7 +49,7 @@ export interface LookupUpdateConfig replacementNameTemplate?: string; replacementVersion?: string; extractVersion?: string; - vulnerabilityFix?: string; + vulnerabilityFixVersion?: string; } export interface UpdateResult { @@ -69,5 +69,5 @@ export interface UpdateResult { warnings: ValidationMessage[]; versioning?: string; currentVersionTimestamp?: string; - vulnerabilityFix?: string; + vulnerabilityFixVersion?: string; } From 2377c5a0aa0fdb3eb2e6b7aa1fd53c1294cd823d Mon Sep 17 00:00:00 2001 From: Rhys Arkins Date: Tue, 17 Sep 2024 07:11:42 +0200 Subject: [PATCH 5/8] add extra type --- lib/config/types.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/config/types.ts b/lib/config/types.ts index fc26ae82b380de..2575c6f91b25f7 100644 --- a/lib/config/types.ts +++ b/lib/config/types.ts @@ -383,6 +383,7 @@ export interface PackageRule matchUpdateTypes?: UpdateType[]; registryUrls?: string[] | null; vulnerabilitySeverity?: string; + vulnerabilityFixVersion?: string; } export interface ValidationMessage { From e74e433a9cd91ef751287abb5b49b06b8bfb0afb Mon Sep 17 00:00:00 2001 From: Rhys Arkins Date: Tue, 17 Sep 2024 07:11:53 +0200 Subject: [PATCH 6/8] refactor/improve after Churro suggestion --- .../repository/process/lookup/index.ts | 26 ++++++++----------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/lib/workers/repository/process/lookup/index.ts b/lib/workers/repository/process/lookup/index.ts index 67aa57d5ecf031..f4fd09de75f114 100644 --- a/lib/workers/repository/process/lookup/index.ts +++ b/lib/workers/repository/process/lookup/index.ts @@ -376,22 +376,18 @@ export async function lookupUpdates( res.vulnerabilityFixVersion = config.vulnerabilityFixVersion; if (versioning.isValid(config.vulnerabilityFixVersion)) { // Filter out versions if the vulnerabilityFixVersion is higher - const fixedFilteredReleases = versioning.isVersion( - config.vulnerabilityFixVersion, - ) - ? filteredReleases.filter( - (r) => - !versioning.isGreaterThan( - config.vulnerabilityFixVersion!, - r.version, - ), - ) - : filteredReleases.filter((r) => - versioning.matches( - r.version, + const filterCondition = (release: Release): boolean => + versioning.isVersion(config.vulnerabilityFixVersion) + ? !versioning.isGreaterThan( config.vulnerabilityFixVersion!, - ), - ); + release.version, + ) + : versioning.matches( + release.version, + config.vulnerabilityFixVersion!, + ); + const fixedFilteredReleases = + filteredReleases.filter(filterCondition); // Warn if this filtering results caused zero releases if (fixedFilteredReleases.length === 0 && filteredReleases.length) { logger.warn( From 9ee228e53156eb24b1ff86a75a4e971870395dbd Mon Sep 17 00:00:00 2001 From: Rhys Arkins Date: Wed, 18 Sep 2024 09:23:44 +0200 Subject: [PATCH 7/8] rewrite for simplicity --- .../repository/process/lookup/index.ts | 28 +++++++++++-------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/lib/workers/repository/process/lookup/index.ts b/lib/workers/repository/process/lookup/index.ts index f4fd09de75f114..1bc354ea3099f1 100644 --- a/lib/workers/repository/process/lookup/index.ts +++ b/lib/workers/repository/process/lookup/index.ts @@ -375,19 +375,25 @@ export async function lookupUpdates( if (config.vulnerabilityFixVersion) { res.vulnerabilityFixVersion = config.vulnerabilityFixVersion; if (versioning.isValid(config.vulnerabilityFixVersion)) { - // Filter out versions if the vulnerabilityFixVersion is higher - const filterCondition = (release: Release): boolean => - versioning.isVersion(config.vulnerabilityFixVersion) - ? !versioning.isGreaterThan( + let fixedFilteredReleases; + if (versioning.isVersion(config.vulnerabilityFixVersion)) { + // Retain only releases greater than or equal to the fix version + fixedFilteredReleases = filteredReleases.filter( + (release) => + !versioning.isGreaterThan( config.vulnerabilityFixVersion!, release.version, - ) - : versioning.matches( - release.version, - config.vulnerabilityFixVersion!, - ); - const fixedFilteredReleases = - filteredReleases.filter(filterCondition); + ), + ); + } else { + // Retain only releases which max the fix constaraint + fixedFilteredReleases = filteredReleases.filter((release) => + versioning.matches( + release.version, + config.vulnerabilityFixVersion!, + ), + ); + } // Warn if this filtering results caused zero releases if (fixedFilteredReleases.length === 0 && filteredReleases.length) { logger.warn( From d8a496621cab5590d163d70704ea2d28b3fd126b Mon Sep 17 00:00:00 2001 From: Michael Kriese Date: Wed, 18 Sep 2024 12:06:33 +0200 Subject: [PATCH 8/8] Update lib/workers/repository/process/lookup/index.ts --- lib/workers/repository/process/lookup/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/workers/repository/process/lookup/index.ts b/lib/workers/repository/process/lookup/index.ts index 1bc354ea3099f1..a76163eeeda2be 100644 --- a/lib/workers/repository/process/lookup/index.ts +++ b/lib/workers/repository/process/lookup/index.ts @@ -386,7 +386,7 @@ export async function lookupUpdates( ), ); } else { - // Retain only releases which max the fix constaraint + // Retain only releases which max the fix constraint fixedFilteredReleases = filteredReleases.filter((release) => versioning.matches( release.version,