Skip to content

Commit de40f2a

Browse files
Merge branch 'master' into release-4-5-b
2 parents ebae048 + ace8016 commit de40f2a

File tree

5 files changed

+268
-76
lines changed

5 files changed

+268
-76
lines changed

utils/cves/index.js

Lines changed: 3 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,10 @@ const { escapeMDXSpecialChars } = require("../helpers/string");
88
const { generateMarkdownTable } = require("../helpers/affected-table");
99
const { generateRevisionHistory } = require("../helpers/revision-history");
1010
const { generateCVEOfficialDetailsUrl } = require("../helpers/urls");
11+
const { generateCVEMap } = require("../helpers/cveHelpers");
1112

1213
async function getSecurityBulletins(payload) {
13-
const limit = 100;
14+
const limit = 300;
1415
const maxIterations = 1000;
1516
let results = [];
1617

@@ -210,47 +211,7 @@ async function generateMarkdownForCVEs(GlobalCVEData) {
210211

211212
// To generate the Impact Product & Versions table we need to track all the instances of the same CVE
212213
// The following hashmap will store the data for each CVE and aggregate the impact data for each product
213-
const cveImpactMap = {};
214-
215-
for (const item of allCVEs) {
216-
// Let's add the CVE to the map if it doesn't exist
217-
// We can take all of the values from the first instance of the CVE
218-
// Future instances will update the values if they are true
219-
if (!cveImpactMap[item.metadata.cve]) {
220-
cveImpactMap[item.metadata.cve] = {
221-
versions: item.spec.impact.impactedVersions,
222-
impactsPaletteEnterprise: item.spec.impact.impactedProducts.palette,
223-
impactsPaletteEnterpriseAirgap: item.spec.impact.impactedDeployments.airgap,
224-
impactsVerteX: item.spec.impact.impactedProducts.vertex,
225-
impactsVerteXAirgap: item.spec.impact.impactedDeployments.airgap,
226-
};
227-
}
228-
229-
// If the CVE already exists in the map, we need to update the values
230-
// But only if the value is true. If the value is false, we don't need to update it.
231-
if (cveImpactMap[item.metadata.cve]) {
232-
cveImpactMap[item.metadata.cve].versions = [
233-
...cveImpactMap[item.metadata.cve].versions,
234-
...item.spec.impact.impactedVersions,
235-
];
236-
237-
if (item.spec.impact.impactedProducts.palette) {
238-
cveImpactMap[item.metadata.cve].impactsPaletteEnterprise = true;
239-
}
240-
241-
if (item.spec.impact.impactedDeployments.airgap) {
242-
cveImpactMap[item.metadata.cve].impactsPaletteEnterpriseAirgap = true;
243-
}
244-
245-
if (item.spec.impact.impactedProducts.vertex) {
246-
cveImpactMap[item.metadata.cve].impactsVerteX = true;
247-
}
248-
249-
if (item.spec.impact.impactedDeployments.airgap) {
250-
cveImpactMap[item.metadata.cve].impactsVerteXAirgap = true;
251-
}
252-
}
253-
}
214+
const cveImpactMap = generateCVEMap(allCVEs);
254215

255216
const markdownPromises = allCVEs.map((item) =>
256217
createCveMarkdown(item, cveImpactMap[item.metadata.cve], "docs/docs-content/security-bulletins/reports/")

utils/helpers/affected-table.js

Lines changed: 34 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -5,43 +5,60 @@ function generateMarkdownTable(cveImpactMap) {
55
throw new Error("Invalid input: cveImpactMap must be an object.");
66
}
77

8+
// Extract impact data and ensure consistency
89
const impactData = {
9-
"Palette Enterprise": cveImpactMap.impactsPaletteEnterprise,
10-
"Palette Enterprise Airgap": cveImpactMap.impactsPaletteEnterpriseAirgap,
11-
VerteX: cveImpactMap.impactsVerteX,
12-
"VerteX Airgap": cveImpactMap.impactsVerteXAirgap,
10+
"Palette Enterprise": cveImpactMap.palette,
11+
"Palette Enterprise Airgap": cveImpactMap.paletteAirgap,
12+
VerteX: cveImpactMap.vertex,
13+
"VerteX Airgap": cveImpactMap.vertexAirgap,
1314
};
1415

15-
const allProductsFalse = Object.values(impactData).every((value) => value === false);
16+
// Check if all products are not impacted
17+
const allProductsFalse = Object.values(impactData).every((product) => product.impacts === false);
1618
if (allProductsFalse) {
17-
return "Investigation is ongoing to determine how this vulnerability affects our products";
19+
return "Investigation is ongoing to determine how this vulnerability affects our products.";
1820
}
1921

20-
const anyProductTrue = Object.values(impactData).some((value) => value === true);
21-
if (anyProductTrue && (!cveImpactMap.versions || cveImpactMap.versions.length === 0)) {
22+
// Check for any product impacted but no versions provided
23+
const anyProductTrueNoVersions = Object.values(impactData).some(
24+
(product) => product.impacts && (!product.versions || product.versions.length === 0)
25+
);
26+
if (anyProductTrueNoVersions) {
2227
throw new Error("Error: Data inconsistency - Products impacted but no versions provided.");
2328
}
2429

25-
// Create the header row with the specified order
30+
// Collect all unique versions across all products
31+
const allVersions = Object.values(impactData)
32+
.flatMap((product) => product.versions || [])
33+
.filter((version) => semver.valid(version));
34+
const uniqueVersions = Array.from(new Set(allVersions)).sort(semver.rcompare);
35+
36+
// Create the header row
2637
const header = `| Version | Palette Enterprise | Palette Enterprise Airgap | VerteX | VerteX Airgap |\n`;
2738
const separator = `| - | -------- | -------- | -------- | -------- |\n`;
2839

29-
// const uniqueVersions = Array.from(new Set(cveImpactMap.versions)).sort((a, b) => b.localeCompare(a));
30-
const uniqueVersions = Array.from(new Set(cveImpactMap.versions)).sort(semver.rcompare);
31-
40+
// Create rows for each version
3241
const rows = uniqueVersions
3342
.map((version) => {
3443
const row = [
3544
`| ${version}`,
36-
impactData["Palette Enterprise"] ? "Impacted" : "No Impact",
37-
impactData["Palette Enterprise Airgap"] ? "Impacted" : "No Impact",
38-
impactData["VerteX"] ? "Impacted" : "No Impact",
39-
impactData["VerteX Airgap"] ? "Impacted" : "No Impact",
45+
impactData["Palette Enterprise"].impacts && impactData["Palette Enterprise"].versions.includes(version)
46+
? "⚠️ Impacted"
47+
: "✅ No Impact",
48+
impactData["Palette Enterprise Airgap"].impacts &&
49+
impactData["Palette Enterprise Airgap"].versions.includes(version)
50+
? "⚠️ Impacted"
51+
: "✅ No Impact",
52+
impactData["VerteX"].impacts && impactData["VerteX"].versions.includes(version)
53+
? "⚠️ Impacted"
54+
: "✅ No Impact",
55+
impactData["VerteX Airgap"].impacts && impactData["VerteX Airgap"].versions.includes(version)
56+
? "⚠️ Impacted"
57+
: "✅ No Impact",
4058
].join(" | ");
4159
return row + " |";
4260
})
4361
.join("\n");
44-
4562
return header + separator + rows;
4663
}
4764

utils/helpers/affected-table.test.js

Lines changed: 14 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,14 @@ const { generateMarkdownTable } = require("./affected-table");
33
describe("generateMarkdownTable", () => {
44
it("should generate a markdown table for two products with mixed impact", () => {
55
const cveImpactMap = {
6-
versions: ["4.4.20", "4.5.3"],
7-
impactsPaletteEnterprise: true,
8-
impactsPaletteEnterpriseAirgap: false,
9-
impactsVerteX: false,
10-
impactsVerteXAirgap: false,
6+
palette: { impacts: true, versions: ["4.4.20", "4.5.3"] },
7+
paletteAirgap: { impacts: false, versions: [] },
8+
vertex: { impacts: false, versions: [] },
9+
vertexAirgap: { impacts: false, versions: [] },
1110
};
1211

1312
const expectedTable = `| Version | Palette Enterprise | Palette Enterprise Airgap | VerteX | VerteX Airgap |
14-
|-|--------|--------|--------|--------|
13+
| - | -------- | -------- | -------- | -------- |
1514
| 4.5.3 | Impacted | No Impact | No Impact | No Impact |
1615
| 4.4.20 | Impacted | No Impact | No Impact | No Impact |`;
1716

@@ -20,24 +19,22 @@ describe("generateMarkdownTable", () => {
2019

2120
it("should return investigation message when all products are not impacted", () => {
2221
const cveImpactMap = {
23-
versions: ["4.4.20", "4.5.3"],
24-
impactsPaletteEnterprise: false,
25-
impactsPaletteEnterpriseAirgap: false,
26-
impactsVerteX: false,
27-
impactsVerteXAirgap: false,
22+
palette: { impacts: false, versions: [] },
23+
paletteAirgap: { impacts: false, versions: [] },
24+
vertex: { impacts: false, versions: [] },
25+
vertexAirgap: { impacts: false, versions: [] },
2826
};
2927

30-
const expectedMessage = "Investigation is ongoing to determine how this vulnerability affects our products";
28+
const expectedMessage = "Investigation is ongoing to determine how this vulnerability affects our products.";
3129
expect(generateMarkdownTable(cveImpactMap)).toBe(expectedMessage);
3230
});
3331

3432
it("should throw an error when products are impacted but no versions are provided", () => {
3533
const cveImpactMap = {
36-
versions: [],
37-
impactsPaletteEnterprise: true,
38-
impactsPaletteEnterpriseAirgap: false,
39-
impactsVerteX: false,
40-
impactsVerteXAirgap: false,
34+
palette: { impacts: true, versions: [] },
35+
paletteAirgap: { impacts: false, versions: [] },
36+
vertex: { impacts: false, versions: [] },
37+
vertexAirgap: { impacts: false, versions: [] },
4138
};
4239

4340
expect(() => generateMarkdownTable(cveImpactMap)).toThrow(

utils/helpers/cveHelpers.js

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
// generates a map of CVEs. Each CVE entry contains information about the impact of the CVE on different products and versions.
2+
function generateCVEMap(cveData) {
3+
const cveImpactMap = {};
4+
5+
for (const item of cveData) {
6+
// Let's create a CVE entry in the map if it doesn't exist.
7+
// By default, let's initailize all values to false or empty array.
8+
if (!cveImpactMap[item.metadata.cve]) {
9+
cveImpactMap[item.metadata.cve] = {
10+
palette: {
11+
impacts: false,
12+
versions: [],
13+
},
14+
paletteAirgap: {
15+
impacts: false,
16+
versions: [],
17+
},
18+
vertex: {
19+
impacts: false,
20+
versions: [],
21+
},
22+
vertexAirgap: {
23+
impacts: false,
24+
versions: [],
25+
},
26+
};
27+
}
28+
29+
// Palette Enterprise logic
30+
if (item.spec.impact.impactedProducts.palette && !item.spec.impact.impactedDeployments.airgap) {
31+
cveImpactMap[item.metadata.cve].palette.impacts = true;
32+
cveImpactMap[item.metadata.cve].palette.versions = item.spec.impact.impactedVersions;
33+
}
34+
35+
// Palette Enterprise Airgap logic
36+
if (item.spec.impact.impactedProducts.palette && item.spec.impact.impactedDeployments.airgap) {
37+
cveImpactMap[item.metadata.cve].paletteAirgap.impacts = true;
38+
cveImpactMap[item.metadata.cve].paletteAirgap.versions = item.spec.impact.impactedVersions;
39+
}
40+
41+
// Palette VerteX logic
42+
if (item.spec.impact.impactedProducts.vertex && !item.spec.impact.impactedDeployments.airgap) {
43+
cveImpactMap[item.metadata.cve].vertex.impacts = true;
44+
cveImpactMap[item.metadata.cve].vertex.versions = item.spec.impact.impactedVersions;
45+
}
46+
47+
// Palette VerteX Airgap logic
48+
if (item.spec.impact.impactedProducts.vertex && item.spec.impact.impactedDeployments.airgap) {
49+
cveImpactMap[item.metadata.cve].vertexAirgap.impacts = true;
50+
cveImpactMap[item.metadata.cve].vertexAirgap.versions = item.spec.impact.impactedVersions;
51+
}
52+
}
53+
54+
return cveImpactMap;
55+
}
56+
57+
module.exports = { generateCVEMap };

0 commit comments

Comments
 (0)