renovate
Version:
Automated dependency updates. Flexible so you don't need to be.
175 lines • 8.4 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.getFixedVersionByDatasource = getFixedVersionByDatasource;
exports.detectVulnerabilityAlerts = detectVulnerabilityAlerts;
const tslib_1 = require("tslib");
const error_messages_1 = require("../../../constants/error-messages");
const logger_1 = require("../../../logger");
const crate_1 = require("../../../modules/datasource/crate");
const go_1 = require("../../../modules/datasource/go");
const maven_1 = require("../../../modules/datasource/maven");
const npm_1 = require("../../../modules/datasource/npm");
const nuget_1 = require("../../../modules/datasource/nuget");
const packagist_1 = require("../../../modules/datasource/packagist");
const pypi_1 = require("../../../modules/datasource/pypi");
const rubygems_1 = require("../../../modules/datasource/rubygems");
const platform_1 = require("../../../modules/platform");
const allVersioning = tslib_1.__importStar(require("../../../modules/versioning"));
const composerVersioning = tslib_1.__importStar(require("../../../modules/versioning/composer"));
const mavenVersioning = tslib_1.__importStar(require("../../../modules/versioning/maven"));
const npmVersioning = tslib_1.__importStar(require("../../../modules/versioning/npm"));
const pep440Versioning = tslib_1.__importStar(require("../../../modules/versioning/pep440"));
const rubyVersioning = tslib_1.__importStar(require("../../../modules/versioning/ruby"));
const semverVersioning = tslib_1.__importStar(require("../../../modules/versioning/semver"));
const markdown_1 = require("../../../util/markdown");
function getFixedVersionByDatasource(fixedVersion, datasource) {
if (datasource === maven_1.MavenDatasource.id || datasource === nuget_1.NugetDatasource.id) {
return `[${fixedVersion},)`;
}
// crates.io, Go, Hackage, Hex, npm, RubyGems, PyPI
return `>= ${fixedVersion}`;
}
// TODO can return `null` and `undefined` (#22198)
async function detectVulnerabilityAlerts(input) {
if (!input?.vulnerabilityAlerts) {
return input;
}
if (input.vulnerabilityAlerts.enabled === false) {
logger_1.logger.debug('Vulnerability alerts are disabled');
return input;
}
const alerts = await platform_1.platform.getVulnerabilityAlerts?.();
if (!alerts?.length) {
logger_1.logger.debug('No vulnerability alerts found');
if (input.vulnerabilityAlertsOnly) {
throw new Error(error_messages_1.NO_VULNERABILITY_ALERTS);
}
return input;
}
const config = { ...input };
const versionings = {
'github-tags': semverVersioning.id,
go: semverVersioning.id,
packagist: composerVersioning.id,
maven: mavenVersioning.id,
npm: npmVersioning.id,
nuget: semverVersioning.id,
pypi: pep440Versioning.id,
rubygems: rubyVersioning.id,
};
const combinedAlerts = {};
for (const alert of alerts) {
try {
if (alert.dismissed_reason) {
continue;
}
if (!alert.security_vulnerability?.first_patched_version) {
logger_1.logger.debug({ alert }, 'Vulnerability alert has no firstPatchedVersion - skipping');
continue;
}
const datasourceMapping = {
composer: packagist_1.PackagistDatasource.id,
go: go_1.GoDatasource.id,
maven: maven_1.MavenDatasource.id,
npm: npm_1.NpmDatasource.id,
nuget: nuget_1.NugetDatasource.id,
pip: pypi_1.PypiDatasource.id,
rubygems: rubygems_1.RubygemsDatasource.id,
rust: crate_1.CrateDatasource.id,
};
const datasource = datasourceMapping[alert.security_vulnerability.package.ecosystem];
const depName = alert.security_vulnerability.package.name;
const fileName = alert.dependency.manifest_path;
const fileType = fileName.split('/').pop();
const firstPatchedVersion = alert.security_vulnerability.first_patched_version.identifier;
const advisory = alert.security_advisory;
combinedAlerts[fileName] ??= {};
combinedAlerts[fileName][datasource] ??= {};
combinedAlerts[fileName][datasource][depName] ??= {
advisories: [],
};
const alertDetails = combinedAlerts[fileName][datasource][depName];
alertDetails.advisories.push(advisory);
const versioningApi = allVersioning.get(versionings[datasource]);
if (versioningApi.isVersion(firstPatchedVersion)) {
if (!alertDetails.firstPatchedVersion ||
versioningApi.isGreaterThan(firstPatchedVersion, alertDetails.firstPatchedVersion)) {
alertDetails.firstPatchedVersion = firstPatchedVersion;
}
}
else {
logger_1.logger.debug('Invalid firstPatchedVersion: ' + firstPatchedVersion);
}
alertDetails.fileType = fileType;
}
catch (err) {
logger_1.logger.warn({ err }, 'Error parsing vulnerability alert');
}
}
const alertPackageRules = [];
config.remediations = {};
for (const [fileName, files] of Object.entries(combinedAlerts)) {
for (const [datasource, dependencies] of Object.entries(files)) {
for (const [depName, val] of Object.entries(dependencies)) {
let prBodyNotes = [];
try {
prBodyNotes = ['### GitHub Vulnerability Alerts'].concat(val.advisories.map((advisory) => {
const identifiers = advisory.identifiers;
const description = advisory.description;
let content = '#### ';
let heading;
if (identifiers.some((id) => id.type === 'CVE')) {
heading = identifiers
.filter((id) => id.type === 'CVE')
.map((id) => id.value)
.join(' / ');
}
else {
heading = identifiers.map((id) => id.value).join(' / ');
}
if (advisory.references?.length) {
heading = `[${heading}](${advisory.references[0].url})`;
}
content += heading;
content += '\n\n';
content += (0, markdown_1.sanitizeMarkdown)(description);
return content;
}));
}
catch (err) /* istanbul ignore next */ {
logger_1.logger.warn({ err }, 'Error generating vulnerability PR notes');
}
// TODO: types (#22198)
const matchFileNames = datasource === go_1.GoDatasource.id
? [fileName.replace('go.sum', 'go.mod')]
: [fileName];
let matchRule = {
matchDatasources: [datasource],
matchPackageNames: [depName],
matchFileNames,
};
let matchCurrentVersion = `< ${val.firstPatchedVersion}`;
if (datasource === maven_1.MavenDatasource.id ||
datasource === nuget_1.NugetDatasource.id) {
matchCurrentVersion = `(,${val.firstPatchedVersion})`;
}
// Remediate only direct dependencies
matchRule = {
...matchRule,
matchCurrentVersion,
vulnerabilityFixVersion: val.firstPatchedVersion,
prBodyNotes,
isVulnerabilityAlert: true,
force: {
...config.vulnerabilityAlerts,
},
};
alertPackageRules.push(matchRule);
}
}
}
logger_1.logger.debug({ alertPackageRules }, 'alert package rules');
config.packageRules = (config.packageRules ?? []).concat(alertPackageRules);
return config;
}
//# sourceMappingURL=vulnerability.js.map