Skip to content

Commit d585e77

Browse files
authored
Merge pull request #6029 from snyk/fix/UNIFY-667_unmanaged_json_ignores
fix: unmanaged json output to use ignores file
2 parents 3f3e0d4 + fa808c1 commit d585e77

File tree

8 files changed

+635
-80
lines changed

8 files changed

+635
-80
lines changed

src/lib/ecosystems/resolve-test-facts.ts

Lines changed: 75 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,37 @@
1-
import { AuthFailedError } from '../errors';
2-
import { Options, PolicyOptions } from '../types';
31
import { spinner } from '../../lib/spinner';
2+
import { sleep } from '../common';
3+
import { AuthFailedError } from '../errors';
4+
import { findAndLoadPolicy } from '../policy';
5+
import {
6+
createDepGraph,
7+
getDepGraph,
8+
getIssues,
9+
pollingTestWithTokenUntilDone,
10+
requestTestPollingToken,
11+
} from '../polling/polling-test';
12+
import { SEVERITY } from '../snyk-test/common';
13+
import { Issue, IssueDataUnmanaged } from '../snyk-test/legacy';
14+
import { Options, PolicyOptions, SupportedProjectTypes } from '../types';
15+
import { extractAndApplyPluginAnalytics } from './plugin-analytics';
16+
import { filterIgnoredIssues } from './policy';
417
import {
518
Ecosystem,
19+
FileSignaturesDetails,
620
ScanResult,
721
TestResult,
8-
FileSignaturesDetails,
922
} from './types';
1023
import {
24+
Attributes,
1125
CreateDepGraphResponse,
12-
GetIssuesResponse,
1326
FileHashes,
14-
Attributes,
27+
GetIssuesResponse,
1528
} from './unmanaged/types';
16-
import {
17-
requestTestPollingToken,
18-
pollingTestWithTokenUntilDone,
19-
createDepGraph,
20-
getDepGraph,
21-
getIssues,
22-
} from '../polling/polling-test';
23-
import { extractAndApplyPluginAnalytics } from './plugin-analytics';
24-
import { findAndLoadPolicy } from '../policy';
25-
import { filterIgnoredIssues } from './policy';
26-
import { IssueDataUnmanaged, Issue } from '../snyk-test/legacy';
2729
import {
2830
convertDepGraph,
2931
convertMapCasing,
3032
convertToCamelCase,
3133
getOrg,
3234
} from './unmanaged/utils';
33-
import { sleep } from '../common';
34-
import { SEVERITY } from '../snyk-test/common';
3535

3636
export async function resolveAndTestFacts(
3737
ecosystem: Ecosystem,
@@ -152,6 +152,21 @@ async function fetchIssues(
152152
};
153153
}
154154

155+
function buildVulnerabilityFromIssue(
156+
issueData: IssueDataUnmanaged,
157+
issue: Issue,
158+
packageManager: SupportedProjectTypes,
159+
): IssueDataUnmanaged {
160+
const pkgCoordinate = `${issue.pkgName}@${issue.pkgVersion}`;
161+
issueData.from = [pkgCoordinate];
162+
issueData.name = pkgCoordinate;
163+
issueData.packageManager = packageManager;
164+
issueData.version = issue.pkgVersion || '';
165+
issueData.upgradePath = [false];
166+
issueData.isPatchable = false;
167+
return issueData;
168+
}
169+
155170
export async function resolveAndTestFactsUnmanagedDeps(
156171
scans: {
157172
[dir: string]: ScanResult[];
@@ -203,25 +218,11 @@ export async function resolveAndTestFactsUnmanagedDeps(
203218
orgId,
204219
);
205220

206-
const issuesMap: Map<string, Issue> = new Map();
221+
const issuesMap = new Map<string, Issue>();
207222
issues.forEach((i) => {
208-
issuesMap[i.issueId] = i;
223+
issuesMap.set(i.issueId, i);
209224
});
210225

211-
const vulnerabilities: IssueDataUnmanaged[] = [];
212-
for (const issuesDataKey in issuesData) {
213-
const pkgCoordinate = `${issuesMap[issuesDataKey]?.pkgName}@${issuesMap[issuesDataKey]?.pkgVersion}`;
214-
const issueData = issuesData[issuesDataKey];
215-
216-
issueData.from = [pkgCoordinate];
217-
issueData.name = pkgCoordinate;
218-
issueData.packageManager = packageManager;
219-
issueData.version = issuesMap[issuesDataKey]?.pkgVersion;
220-
issueData.upgradePath = [false];
221-
issueData.isPatchable = false;
222-
vulnerabilities.push(issueData);
223-
}
224-
225226
const policy = await findAndLoadPolicy(path, 'cpp', options);
226227

227228
const [issuesFiltered, issuesDataFiltered] = filterIgnoredIssues(
@@ -230,6 +231,37 @@ export async function resolveAndTestFactsUnmanagedDeps(
230231
policy,
231232
);
232233

234+
// Build vulnerabilities array from filtered data.
235+
const vulnerabilities: IssueDataUnmanaged[] = [];
236+
for (const issuesDataKey in issuesDataFiltered) {
237+
const issue = issuesMap.get(issuesDataKey);
238+
if (issue) {
239+
const issueData = issuesDataFiltered[
240+
issuesDataKey
241+
] as IssueDataUnmanaged;
242+
vulnerabilities.push(
243+
buildVulnerabilityFromIssue(issueData, issue, packageManager),
244+
);
245+
}
246+
}
247+
248+
// Build filtered.ignore array with ignored vulnerabilities
249+
const filteredIgnore: IssueDataUnmanaged[] = [];
250+
for (const issuesDataKey in issuesData) {
251+
// If the issue was in the original data but not in the filtered data, it was ignored
252+
if (!(issuesDataKey in issuesDataFiltered)) {
253+
const issue = issuesMap.get(issuesDataKey);
254+
if (issue) {
255+
const issueData = {
256+
...issuesData[issuesDataKey],
257+
} as IssueDataUnmanaged;
258+
filteredIgnore.push(
259+
buildVulnerabilityFromIssue(issueData, issue, packageManager),
260+
);
261+
}
262+
}
263+
}
264+
233265
extractAndApplyPluginAnalytics([
234266
{
235267
name: 'packageManager',
@@ -256,6 +288,9 @@ export async function resolveAndTestFactsUnmanagedDeps(
256288
dependencyCount,
257289
packageManager,
258290
displayTargetFile,
291+
filtered: {
292+
ignore: filteredIgnore,
293+
},
259294
});
260295
} catch (error) {
261296
const hasStatusCodeError = error.code >= 400 && error.code <= 500;
@@ -312,20 +347,21 @@ export async function resolveAndTestFactsRegistry(
312347
policy,
313348
);
314349

315-
const issuesMap: Map<string, Issue> = new Map();
350+
const issuesMap = new Map<string, Issue>();
316351
response.issues.forEach((i) => {
317-
issuesMap[i.issueId] = i;
352+
issuesMap.set(i.issueId, i);
318353
});
319354

320355
const vulnerabilities: IssueDataUnmanaged[] = [];
321356
for (const issuesDataKey in response.issuesData) {
322-
if (issuesMap[issuesDataKey]) {
357+
const issue = issuesMap.get(issuesDataKey);
358+
if (issue) {
323359
const issueData = response.issuesData[issuesDataKey];
324-
const pkgCoordinate = `${issuesMap[issuesDataKey].pkgName}@${issuesMap[issuesDataKey].pkgVersion}`;
360+
const pkgCoordinate = `${issue.pkgName}@${issue.pkgVersion}`;
325361
issueData.from = [pkgCoordinate];
326362
issueData.name = pkgCoordinate;
327363
issueData.packageManager = packageManager;
328-
issueData.version = issuesMap[issuesDataKey]?.pkgVersion;
364+
issueData.version = issue.pkgVersion || '';
329365
issueData.upgradePath = [false];
330366
issueData.isPatchable = false;
331367
vulnerabilities.push(issueData);

test/acceptance/fake-server.ts

Lines changed: 84 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@ import * as express from 'express';
33
import * as fs from 'fs';
44
import * as http from 'http';
55
import * as https from 'https';
6-
import * as path from 'path';
76
import * as net from 'net';
8-
import { getFixturePath } from '../jest/util/getFixturePath';
97
import * as os from 'os';
8+
import * as path from 'path';
9+
import { getFixturePath } from '../jest/util/getFixturePath';
1010

1111
const featureFlagDefaults = (): Map<string, boolean> => {
1212
return new Map([
@@ -285,6 +285,88 @@ export const fakeServer = (basePath: string, snykToken: string): FakeServer => {
285285
res.send(defaultResponse);
286286
});
287287

288+
app.post('/hidden/orgs/:orgId/unmanaged_ecosystem/depgraphs', (req, res) => {
289+
res.status(201);
290+
res.send({
291+
jsonapi: { version: '1.0' },
292+
links: { self: req.url },
293+
data: {
294+
id: 'test-dep-graph-id',
295+
type: 'unmanaged-dep-graph',
296+
location: `/orgs/${req.params.orgId}/unmanaged_ecosystem/depgraphs/test-dep-graph-id`,
297+
},
298+
});
299+
});
300+
301+
app.get(
302+
'/hidden/orgs/:orgId/unmanaged_ecosystem/depgraphs/:id',
303+
(req, res) => {
304+
const result = customResponse?.result as any;
305+
const depGraphData = result?.depGraphData || {};
306+
307+
res.status(200);
308+
res.send({
309+
jsonapi: { version: '1.0' },
310+
links: { self: req.url },
311+
data: {
312+
id: req.params.id,
313+
type: 'unmanaged-dep-graph',
314+
attributes: {
315+
start_time: Date.now(),
316+
in_progress: false,
317+
dep_graph_data: depGraphData,
318+
component_details: {},
319+
},
320+
},
321+
});
322+
},
323+
);
324+
325+
app.post('/hidden/orgs/:orgId/unmanaged_ecosystem/issues', (req, res) => {
326+
if (customResponse && customResponse.result) {
327+
// Convert camelCase fixture format to snake_case API format
328+
const result = customResponse.result as any;
329+
330+
const apiResult: any = {
331+
start_time: Date.now(),
332+
issues: result.issues || [],
333+
issues_data: result.issuesData || {},
334+
dep_graph: result.depGraphData || {},
335+
deps_file_paths: result.depsFilePaths || {},
336+
file_signatures_details: result.fileSignaturesDetails || {},
337+
type: 'unmanaged',
338+
};
339+
340+
res.status(200);
341+
res.send({
342+
jsonapi: { version: '1.0' },
343+
links: { self: req.url },
344+
data: {
345+
id: 'test-issues-id',
346+
result: apiResult,
347+
},
348+
});
349+
return;
350+
}
351+
res.status(200);
352+
res.send({
353+
jsonapi: { version: '1.0' },
354+
links: { self: req.url },
355+
data: {
356+
id: 'test-issues-id',
357+
result: {
358+
start_time: Date.now(),
359+
issues: [],
360+
issues_data: {},
361+
dep_graph: {},
362+
deps_file_paths: {},
363+
file_signatures_details: {},
364+
type: 'unmanaged',
365+
},
366+
},
367+
});
368+
});
369+
288370
app.get(basePath + '/vuln/:registry/:module', (req, res) => {
289371
try {
290372
// Use one of the fixtures if it exists.
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
{
2+
"result": {
3+
"issues": [
4+
{
5+
"issueId": "SNYK-UNMANAGED-CPIO-2319543",
6+
"pkgName": "https://ftp.gnu.org|cpio",
7+
"pkgVersion": "2.12",
8+
"fixInfo": {
9+
"isPatchable": false,
10+
"nearestFixedInVersion": "",
11+
"upgradePaths": []
12+
}
13+
}
14+
],
15+
"issuesData": {
16+
"SNYK-UNMANAGED-CPIO-2319543": {
17+
"id": "SNYK-UNMANAGED-CPIO-2319543",
18+
"packageManager": "Unmanaged (C/C++)",
19+
"packageName": "https://ftp.gnu.org|cpio",
20+
"severity": "medium",
21+
"isIgnored": true,
22+
"name": "https://ftp.gnu.org|[email protected]",
23+
"version": "2.12",
24+
"from": [
25+
"https://ftp.gnu.org|[email protected]"
26+
],
27+
"upgradePath": [
28+
false
29+
],
30+
"ignoreReasons": [
31+
{
32+
"reason": "Test ignore",
33+
"created": "2024-01-01T00:00:00.000Z",
34+
"expires": "2026-01-01T00:00:00.000Z"
35+
}
36+
]
37+
}
38+
},
39+
"depGraphData": {
40+
"schemaVersion": "1.2.0",
41+
"pkgManager": {
42+
"name": "unmanaged",
43+
"repositories": []
44+
},
45+
"pkgs": [
46+
{
47+
"id": "https://ftp.gnu.org|[email protected]",
48+
"info": {
49+
"name": "https://ftp.gnu.org|cpio",
50+
"version": "2.12"
51+
}
52+
}
53+
],
54+
"graph": {
55+
"rootNodeId": "root-node",
56+
"nodes": [
57+
{
58+
"nodeId": "root-node",
59+
"pkgId": "https://ftp.gnu.org|[email protected]",
60+
"deps": []
61+
}
62+
]
63+
}
64+
},
65+
"depsFilePaths": {
66+
"https://ftp.gnu.org|[email protected]": [
67+
"deps/cpio-2.12/src/cpio.c"
68+
]
69+
},
70+
"fileSignaturesDetails": {
71+
"https://ftp.gnu.org|[email protected]": {
72+
"filePaths": [
73+
"deps/cpio-2.12/src/cpio.c"
74+
],
75+
"confidence": 1
76+
}
77+
},
78+
"vulnerabilities": [],
79+
"filtered": {
80+
"ignore": [
81+
{
82+
"id": "SNYK-UNMANAGED-CPIO-2319543",
83+
"packageManager": "Unmanaged (C/C++)",
84+
"name": "https://ftp.gnu.org|[email protected]",
85+
"version": "2.12",
86+
"from": [
87+
"https://ftp.gnu.org|[email protected]"
88+
],
89+
"upgradePath": [
90+
false
91+
],
92+
"isPatchable": false,
93+
"ignoreReasons": [
94+
{
95+
"reason": "Test ignore",
96+
"created": "2024-01-01T00:00:00.000Z",
97+
"expires": "2026-01-01T00:00:00.000Z"
98+
}
99+
]
100+
}
101+
]
102+
},
103+
"dependencyCount": 1
104+
},
105+
"meta": {
106+
"org": "test-org",
107+
"isPrivate": false
108+
}
109+
}

0 commit comments

Comments
 (0)