Skip to content

Commit

Permalink
refactor: file-based alert aggregation
Browse files Browse the repository at this point in the history
  • Loading branch information
rarkins committed Feb 21, 2021
1 parent e86bddd commit 4b62acc
Showing 1 changed file with 89 additions and 90 deletions.
179 changes: 89 additions & 90 deletions lib/workers/repository/init/vulnerability.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,21 @@ import * as semverVersioning from '../../../versioning/semver';
type Datasource = string;
type DependencyName = string;
type FileName = string;
type VulnerableRequirements = string;

type CombinedAlert = Record<
Datasource,
FileName,
Record<
DependencyName,
Datasource,
Record<
FileName,
{
advisories: SecurityAdvisory[];
firstPatchedVersion?: string;
vulnerableRequirements?: string;
}
DependencyName,
Record<
VulnerableRequirements,
{
advisories: SecurityAdvisory[];
firstPatchedVersion?: string;
}
>
>
>
>;
Expand Down Expand Up @@ -88,35 +91,36 @@ export async function detectVulnerabilityAlerts(
const firstPatchedVersion =
alert.securityVulnerability.firstPatchedVersion.identifier;
const advisory = alert.securityAdvisory;
const { vulnerableRequirements } = alert;
if (!combinedAlerts[datasource]) {
combinedAlerts[datasource] = {};
}
if (!combinedAlerts[datasource][depName]) {
combinedAlerts[datasource][depName] = {};
}
if (!combinedAlerts[datasource][depName][fileName]) {
combinedAlerts[datasource][depName][fileName] = {
advisories: [],
};
let { vulnerableRequirements } = alert;
// istanbul ignore if
if (!vulnerableRequirements.length) {
if (datasource === datasourceMaven.id) {
vulnerableRequirements = `(,${firstPatchedVersion})`;
} else {
vulnerableRequirements = `< ${firstPatchedVersion}`;
}
}
const alertDetails = combinedAlerts[datasource][depName][fileName];
combinedAlerts[fileName] ||= {};
combinedAlerts[fileName][datasource] ||= {};
combinedAlerts[fileName][datasource][depName] ||= {};
combinedAlerts[fileName][datasource][depName][
vulnerableRequirements
] ||= {
advisories: [],
};
const alertDetails =
combinedAlerts[fileName][datasource][depName][vulnerableRequirements];
alertDetails.advisories.push(advisory);
const version = allVersioning.get(versionings[datasource]);
if (version.isVersion(firstPatchedVersion)) {
if (alertDetails.firstPatchedVersion) {
if (
version.isGreaterThan(
firstPatchedVersion,
alertDetails.firstPatchedVersion
)
) {
alertDetails.firstPatchedVersion = firstPatchedVersion;
alertDetails.vulnerableRequirements = vulnerableRequirements;
}
} else {
if (
!alertDetails.firstPatchedVersion ||
version.isGreaterThan(
firstPatchedVersion,
alertDetails.firstPatchedVersion
)
) {
alertDetails.firstPatchedVersion = firstPatchedVersion;
alertDetails.vulnerableRequirements = vulnerableRequirements;
}
} else {
logger.debug('Invalid firstPatchedVersion: ' + firstPatchedVersion);
Expand All @@ -126,66 +130,61 @@ export async function detectVulnerabilityAlerts(
}
}
const alertPackageRules = [];
for (const [datasource, dependencies] of Object.entries(combinedAlerts)) {
for (const [depName, files] of Object.entries(dependencies)) {
for (const [fileName, val] of Object.entries(files)) {
let prBodyNotes: string[] = [];
try {
prBodyNotes = ['### GitHub Vulnerability Alerts'].concat(
val.advisories.map((advisory) => {
let content = '#### ';
let heading: string;
if (advisory.identifiers.some((id) => id.type === 'CVE')) {
heading = advisory.identifiers
.filter((id) => id.type === 'CVE')
.map((id) => id.value)
.join(' / ');
} else {
heading = advisory.identifiers
.map((id) => id.value)
.join(' / ');
}
if (advisory.references.length) {
heading = `[${heading}](${advisory.references[0].url})`;
}
content += heading;
content += '\n\n';
// eslint-disable-next-line no-loop-func
content += sanitizeMarkdown(advisory.description);
return content;
})
);
} catch (err) /* istanbul ignore next */ {
logger.warn({ err }, 'Error generating vulnerability PR notes');
}
let matchCurrentVersion = val.vulnerableRequirements;
// istanbul ignore if
if (!matchCurrentVersion) {
if (datasource === datasourceMaven.id) {
matchCurrentVersion = `(,${val.firstPatchedVersion})`;
} else {
matchCurrentVersion = `< ${val.firstPatchedVersion}`;
for (const [fileName, files] of Object.entries(combinedAlerts)) {
for (const [datasource, dependencies] of Object.entries(files)) {
for (const [depName, currentValues] of Object.entries(dependencies)) {
for (const [vulnerableRequirements, val] of Object.entries(
currentValues
)) {
let prBodyNotes: string[] = [];
try {
prBodyNotes = ['### GitHub Vulnerability Alerts'].concat(
val.advisories.map((advisory) => {
let content = '#### ';
let heading: string;
if (advisory.identifiers.some((id) => id.type === 'CVE')) {
heading = advisory.identifiers
.filter((id) => id.type === 'CVE')
.map((id) => id.value)
.join(' / ');
} else {
heading = advisory.identifiers
.map((id) => id.value)
.join(' / ');
}
if (advisory.references.length) {
heading = `[${heading}](${advisory.references[0].url})`;
}
content += heading;
content += '\n\n';
// eslint-disable-next-line no-loop-func
content += sanitizeMarkdown(advisory.description);
return content;
})
);
} catch (err) /* istanbul ignore next */ {
logger.warn({ err }, 'Error generating vulnerability PR notes');
}
const allowedVersions =
datasource === datasourcePypi.id
? `==${val.firstPatchedVersion}`
: val.firstPatchedVersion;
const matchRule: PackageRule = {
matchDatasources: [datasource],
matchPackageNames: [depName],
matchCurrentVersion: vulnerableRequirements,
allowedVersions,
prBodyNotes,
force: {
...config.vulnerabilityAlerts,
vulnerabilityAlert: true,
branchTopic: `${datasource}-${depName}-vulnerability`,
prCreation: 'immediate',
},
};
matchRule.matchFiles = [fileName];
alertPackageRules.push(matchRule);
}
const allowedVersions =
datasource === datasourcePypi.id
? `==${val.firstPatchedVersion}`
: val.firstPatchedVersion;
const matchRule: PackageRule = {
matchDatasources: [datasource],
matchPackageNames: [depName],
matchCurrentVersion,
allowedVersions,
prBodyNotes,
force: {
...config.vulnerabilityAlerts,
vulnerabilityAlert: true,
branchTopic: `${datasource}-${depName}-vulnerability`,
prCreation: 'immediate',
},
};
matchRule.matchFiles = [fileName];
alertPackageRules.push(matchRule);
}
}
}
Expand Down

0 comments on commit 4b62acc

Please sign in to comment.