diff --git a/src/cli/args.ts b/src/cli/args.ts index 8d74ecf25f..b962f635f3 100644 --- a/src/cli/args.ts +++ b/src/cli/args.ts @@ -181,6 +181,7 @@ export function args(rawArgv: string[]): Args { 'scan-all-unmanaged', 'fail-on', 'all-projects', + 'detection-depth', ]) { if (argv[dashedArg]) { const camelCased = dashToCamelCase(dashedArg); diff --git a/src/cli/commands/test/formatters/format-test-meta.ts b/src/cli/commands/test/formatters/format-test-meta.ts index eb84012dba..ec26b3aa97 100644 --- a/src/cli/commands/test/formatters/format-test-meta.ts +++ b/src/cli/commands/test/formatters/format-test-meta.ts @@ -9,7 +9,7 @@ export function formatTestMeta( ): string { const padToLength = 19; // chars to align const packageManager = res.packageManager || options.packageManager; - const targetFile = res.targetFile || options.file; + const targetFile = res.targetFile || res.displayTargetFile || options.file; const openSource = res.isPrivate ? 'no' : 'yes'; const meta = [ chalk.bold(rightPadWithSpaces('Organization: ', padToLength)) + res.org, diff --git a/src/cli/commands/test/index.ts b/src/cli/commands/test/index.ts index e4aac72508..aa6525f7db 100644 --- a/src/cli/commands/test/index.ts +++ b/src/cli/commands/test/index.ts @@ -24,7 +24,6 @@ import { } from '../../../lib/package-managers'; import * as analytics from '../../../lib/analytics'; -import { isFeatureFlagSupportedForOrg } from '../../../lib/feature-flags'; import { FailOnError } from '../../../lib/errors/fail-on-error.ts'; import { summariseVulnerableResults, diff --git a/src/cli/index.ts b/src/cli/index.ts index 6b590aae77..be9ce55fe6 100755 --- a/src/cli/index.ts +++ b/src/cli/index.ts @@ -158,18 +158,31 @@ async function main() { ]); } - if ( - (args.options['project-name'] || - args.options.file || - args.options.packageManager || - args.options.docker) && - args.options.allProjects - ) { + if (args.options['project-name'] && args.options.allProjects) { + throw new UnsupportedOptionCombinationError([ + 'project-name', + 'all-projects', + ]); + } + if (args.options.file && args.options.allProjects) { + throw new UnsupportedOptionCombinationError(['file', 'all-projects']); + } + if (args.options.packageManager && args.options.allProjects) { throw new UnsupportedOptionCombinationError([ - 'project-name or file or package-manager or docker', + 'package-manager', 'all-projects', ]); } + if (args.options.docker && args.options.allProjects) { + throw new UnsupportedOptionCombinationError(['docker', 'all-projects']); + } + if (args.options.allSubProjects && args.options.allProjects) { + throw new UnsupportedOptionCombinationError([ + 'all-sub-projects', + 'all-projects', + ]); + } + if ( args.options.file && typeof args.options.file === 'string' && diff --git a/src/lib/plugins/get-deps-from-plugin.ts b/src/lib/plugins/get-deps-from-plugin.ts index cb617bc832..5a68af5de9 100644 --- a/src/lib/plugins/get-deps-from-plugin.ts +++ b/src/lib/plugins/get-deps-from-plugin.ts @@ -24,7 +24,7 @@ export async function getDepsFromPlugin( let inspectRes: pluginApi.InspectResult; if (options.allProjects) { - const levelsDeep = 1; // TODO: auto-detect only one-level deep for now + const levelsDeep = options.detectionDepth || 1; // default to 1 level deep const targetFiles = await find(root, [], AUTO_DETECTABLE_FILES, levelsDeep); debug( `auto detect manifest files, found ${targetFiles.length}`, diff --git a/src/lib/plugins/get-multi-plugin-result.ts b/src/lib/plugins/get-multi-plugin-result.ts index 2f66ffb5fe..f56657b4bc 100644 --- a/src/lib/plugins/get-multi-plugin-result.ts +++ b/src/lib/plugins/get-multi-plugin-result.ts @@ -26,9 +26,9 @@ export async function getMultiPluginResult( const allResults: ScannedProjectCustom[] = []; for (const targetFile of targetFiles) { const optionsClone = _.cloneDeep(options); - optionsClone.file = path.basename(targetFile); + optionsClone.file = path.relative(root, targetFile); optionsClone.packageManager = detectPackageManagerFromFile( - optionsClone.file, + path.basename(targetFile), ); try { const inspectRes = await getSinglePluginResult( diff --git a/src/lib/snyk-test/index.js b/src/lib/snyk-test/index.js index 03a44241a2..eed58c3aff 100644 --- a/src/lib/snyk-test/index.js +++ b/src/lib/snyk-test/index.js @@ -27,19 +27,20 @@ async function test(root, options, callback) { function executeTest(root, options) { try { - const packageManager = detect.detectPackageManager(root, options); - options.packageManager = packageManager; + if (!options.allProjects) { + options.packageManager = detect.detectPackageManager(root, options); + } return run(root, options).then((results) => { for (const res of results) { if (!res.packageManager) { - res.packageManager = packageManager; + res.packageManager = options.packageManager; } } if (results.length === 1) { // Return only one result if only one found as this is the default usecase return results[0]; } - // For gradle and yarnWorkspaces we may be returning more than one result + // For gradle, yarnWorkspaces, allProjects we may be returning more than one result return results; }); } catch (error) { @@ -49,7 +50,13 @@ function executeTest(root, options) { function run(root, options) { const packageManager = options.packageManager; - if (!(options.docker || pm.SUPPORTED_PACKAGE_MANAGER_NAME[packageManager])) { + if ( + !( + options.docker || + options.allProjects || + pm.SUPPORTED_PACKAGE_MANAGER_NAME[packageManager] + ) + ) { throw new UnsupportedPackageManagerError(packageManager); } return runTest(packageManager, root, options); diff --git a/src/lib/snyk-test/legacy.ts b/src/lib/snyk-test/legacy.ts index fda5c2d1f2..5c6ced7568 100644 --- a/src/lib/snyk-test/legacy.ts +++ b/src/lib/snyk-test/legacy.ts @@ -150,6 +150,7 @@ export interface BaseImageRemediationAdvice { export interface TestResult extends LegacyVulnApiResult { targetFile?: string; projectName?: string; + displayTargetFile?: string; // used for display only } interface UpgradePathItem { diff --git a/src/lib/snyk-test/run-test.ts b/src/lib/snyk-test/run-test.ts index dcb688b8ff..073febd9fb 100644 --- a/src/lib/snyk-test/run-test.ts +++ b/src/lib/snyk-test/run-test.ts @@ -58,6 +58,7 @@ interface PayloadBody { originalProjectName?: string; // used only for display foundProjectCount?: number; // used only for display docker?: any; + displayTargetFile?: string; target?: GitTarget | null; } @@ -93,6 +94,8 @@ async function runTest( _.get(payload, 'body.projectNameOverride') || _.get(payload, 'body.originalProjectName'); const foundProjectCount = _.get(payload, 'body.foundProjectCount'); + const displayTargetFile = _.get(payload, 'body.displayTargetFile'); + let dockerfilePackages; if ( payload.body && @@ -190,6 +193,7 @@ async function runTest( targetFile, projectName, foundProjectCount, + displayTargetFile, }; results.push(result); } @@ -277,7 +281,9 @@ async function assembleLocalPayloads( root, options: Options & TestOptions, ): Promise { - const analysisType = options.docker ? 'docker' : options.packageManager; + // For --all-projects packageManager is yet undefined here. Use 'all' + const analysisType = + (options.docker ? 'docker' : options.packageManager) || 'all'; const spinnerLbl = 'Analyzing ' + analysisType + @@ -344,14 +350,17 @@ async function assembleLocalPayloads( } // todo: normalize what target file gets used across plugins and functions - const targetFile = scannedProject.targetFile || deps.plugin.targetFile; + const targetFile = + scannedProject.targetFile || deps.plugin.targetFile || options.file; let body: PayloadBody = { - targetFile, + // WARNING: be careful changing this as it affects project uniqueness + targetFile: deps.plugin.targetFile, projectNameOverride: options.projectName, originalProjectName: pkg.name, policy: policy && policy.toString(), foundProjectCount: getSubProjectCount(deps), + displayTargetFile: targetFile, docker: pkg.docker, hasDevDependencies: (pkg as any).hasDevDependencies, target: await projectMetadata.getInfo(pkg, options), diff --git a/src/lib/types.ts b/src/lib/types.ts index f98eb19f3b..881afa0eed 100644 --- a/src/lib/types.ts +++ b/src/lib/types.ts @@ -30,7 +30,6 @@ export interface TestOptions { 'prune-repeated-subdependencies'?: boolean; showVulnPaths: ShowVulnPaths; failOn?: FailOn; - allProjects?: boolean; } export interface ProtectOptions { loose: boolean; @@ -64,6 +63,8 @@ export interface Options { 'print-deps'?: boolean; 'remote-repo-url'?: string; scanAllUnmanaged?: boolean; + allProjects?: boolean; + detectionDepth?: number; } // TODO(kyegupov): catch accessing ['undefined-properties'] via noImplicitAny @@ -78,8 +79,6 @@ export interface MonitorOptions { 'print-deps'?: boolean; 'experimental-dep-graph'?: boolean; scanAllUnmanaged?: boolean; - allProjects?: boolean; - // An experimental flag to allow monitoring of bigtrees (with degraded deps info and remediation advice). 'prune-repeated-subdependencies'?: boolean; } diff --git a/test/acceptance/cli-args.test.ts b/test/acceptance/cli-args.test.ts index 8de7eff22f..9a0e5892e6 100644 --- a/test/acceptance/cli-args.test.ts +++ b/test/acceptance/cli-args.test.ts @@ -78,64 +78,36 @@ test('`test --file=blah --scan-all-unmanaged`', (t) => { }); }); -test('`test --file=blah and --all-projects`', (t) => { - t.plan(1); - exec(`node ${main} test --file=blah --all-projects`, (err, stdout) => { - if (err) { - throw err; - } - t.match( - stdout.trim(), - 'The following option combination is not currently supported: project-name or file or package-manager or docker + all-projects', - 'correct error output', - ); - }); -}); +const argsNotAllowedWithAllProjects = [ + 'file', + 'package-manager', + 'project-name', + 'docker', + 'all-sub-projects', +]; -test('`test --package-manager and --all-projects`', (t) => { - t.plan(1); - exec( - `node ${main} test --package-manager=npm --all-projects`, - (err, stdout) => { +argsNotAllowedWithAllProjects.forEach((arg) => { + test(`using --${arg} and --all-projects throws exception`, (t) => { + t.plan(2); + exec(`node ${main} test --${arg} --all-projects`, (err, stdout) => { if (err) { throw err; } t.match( stdout.trim(), - 'The following option combination is not currently supported: project-name or file or package-manager or docker + all-projects', - 'correct error output', + `The following option combination is not currently supported: ${arg} + all-projects`, + 'when using test', ); - }, - ); -}); - -test('`test --project-name and --all-projects`', (t) => { - t.plan(1); - exec( - `node ${main} test --project-name=my-monorepo --all-projects`, - (err, stdout) => { + }); + exec(`node ${main} monitor --${arg} --all-projects`, (err, stdout) => { if (err) { throw err; } t.match( stdout.trim(), - 'The following option combination is not currently supported: project-name or file or package-manager or docker + all-projects', - 'correct error output', + `The following option combination is not currently supported: ${arg} + all-projects`, + 'when using monitor', ); - }, - ); -}); - -test('`test --docker and --all-projects`', (t) => { - t.plan(1); - exec(`node ${main} test --docker --all-projects`, (err, stdout) => { - if (err) { - throw err; - } - t.match( - stdout.trim(), - 'The following option combination is not currently supported: project-name or file or package-manager or docker + all-projects', - 'correct error output', - ); + }); }); }); diff --git a/test/acceptance/cli-monitor/cli-monitor.acceptance.test.ts b/test/acceptance/cli-monitor/cli-monitor.acceptance.test.ts index 11866e460a..8212ff0bed 100644 --- a/test/acceptance/cli-monitor/cli-monitor.acceptance.test.ts +++ b/test/acceptance/cli-monitor/cli-monitor.acceptance.test.ts @@ -8,6 +8,8 @@ import { fakeServer } from '../fake-server'; import * as subProcess from '../../../src/lib/sub-process'; import * as version from '../../../src/lib/version'; import * as userConfig from '../../../src/lib/user-config'; +import { chdirWorkspaces, getWorkspaceJSON } from '../workspace-helper'; +import * as _ from 'lodash'; // ensure this is required *after* the demo server, since this will // configure our fake configuration too @@ -31,7 +33,6 @@ const after = tap.runOnly ? only : test; // Should be after `process.env` setup. import * as plugins from '../../../src/lib/plugins/index'; -import { chdirWorkspaces } from '../workspace-helper'; // @later: remove this config stuff. // Was copied straight from ../src/cli-server.js @@ -1419,6 +1420,38 @@ test('`monitor foo:latest --docker` with custom policy path', async (t) => { t.deepEqual(policyString, expected, 'sends correct policy'); }); +test('monitor --json multiple folders', async (t) => { + chdirWorkspaces('fail-on'); + + const noFixableResult = getWorkspaceJSON( + 'fail-on', + 'no-fixable', + 'vulns-result.json', + ); + server.setNextResponse(noFixableResult); + try { + const response = await cli.monitor('upgradable', 'no-fixable', { + json: true, + }); + const res = JSON.parse(response); + if (_.isObject(res)) { + t.pass('monitor outputted JSON'); + } else { + t.fail('Failed parsing monitor JSON output'); + } + const keyList = ['packageManager', 'manageUrl']; + t.true(Array.isArray(res), 'Response is an array'); + t.equal(res.length, 2, 'Two monitor responses in the array'); + res.forEach((project) => { + keyList.forEach((k) => { + !_.get(project, k) ? t.fail(k + 'not found') : t.pass(k + ' found'); + }); + }); + } catch (error) { + t.fail('should not have failed'); + } +}); + /** * We can't expect all test environments to have Maven installed * So, hijack the system exec call and return the expected output diff --git a/test/acceptance/cli-monitor/cli-monitor.all-projects.spec.ts b/test/acceptance/cli-monitor/cli-monitor.all-projects.spec.ts index 795a215750..b39875f5ba 100644 --- a/test/acceptance/cli-monitor/cli-monitor.all-projects.spec.ts +++ b/test/acceptance/cli-monitor/cli-monitor.all-projects.spec.ts @@ -57,38 +57,47 @@ export const AllProjectsTests: AcceptanceTests = { ); }); }, - '`monitor maven-multi-app --all-projects`': (params, utils) => async ( - t, - ) => { + '`monitor maven-multi-app --all-projects --detection-depth=2`': ( + params, + utils, + ) => async (t) => { utils.chdirWorkspaces(); const spyPlugin = sinon.spy(params.plugins, 'loadPlugin'); t.teardown(spyPlugin.restore); const result = await params.cli.monitor('maven-multi-app', { allProjects: true, + detectionDepth: 2, }); t.ok( spyPlugin.withArgs('rubygems').notCalled, 'did not call rubygems plugin', ); t.ok(spyPlugin.withArgs('npm').notCalled, 'did not call npm plugin'); - t.ok(spyPlugin.withArgs('maven').calledOnce, 'calls maven plugin'); + t.equals( + spyPlugin.withArgs('maven').callCount, + 2, + 'calls maven plugin twice', + ); // maven + console.log(result); t.match(result, 'maven/some/project-id', 'maven project was monitored '); - const request = params.server.popRequest(); - // TODO: bump this test to discover both pom.xml in the repo - // once we have depth increase released - t.ok(request, 'Monitor POST request'); + const requests = params.server.popRequests(2); - t.match(request.url, '/monitor/', 'puts at correct url'); - t.notOk(request.body.targetFile, "doesn't send the targetFile"); - t.equal(request.method, 'PUT', 'makes PUT request'); - t.equal( - request.headers['x-snyk-cli-version'], - params.versionNumber, - 'sends version number', - ); + requests.forEach((request) => { + // once we have depth increase released + t.ok(request, 'Monitor POST request'); + + t.match(request.url, '/monitor/', 'puts at correct url'); + t.notOk(request.body.targetFile, "doesn't send the targetFile"); + t.equal(request.method, 'PUT', 'makes PUT request'); + t.equal( + request.headers['x-snyk-cli-version'], + params.versionNumber, + 'sends version number', + ); + }); }, '`monitor monorepo-bad-project --all-projects`': (params, utils) => async ( t, diff --git a/test/acceptance/cli-test/cli-test.all-projects.spec.ts b/test/acceptance/cli-test/cli-test.all-projects.spec.ts index 08582e6d10..490402a077 100644 --- a/test/acceptance/cli-test/cli-test.all-projects.spec.ts +++ b/test/acceptance/cli-test/cli-test.all-projects.spec.ts @@ -1,5 +1,6 @@ import { AcceptanceTests } from './cli-test.acceptance.test'; import { getWorkspaceJSON } from '../workspace-helper'; +import * as path from 'path'; import * as sinon from 'sinon'; export const AllProjectsTests: AcceptanceTests = { @@ -69,6 +70,164 @@ export const AllProjectsTests: AcceptanceTests = { ); }, + '`test --all-projects and --file payloads are the same`': ( + params, + utils, + ) => async (t) => { + utils.chdirWorkspaces(); + const spyPlugin = sinon.spy(params.plugins, 'loadPlugin'); + t.teardown(spyPlugin.restore); + + await params.cli.test('mono-repo-project', { + allProjects: true, + }); + const [ + rubyAllProjectsBody, + npmAllProjectsBody, + mavenAllProjectsBody, + ] = params.server.popRequests(3).map((req) => req.body); + + await params.cli.test('mono-repo-project', { + file: 'Gemfile.lock', + }); + const { body: rubyFileBody } = params.server.popRequest(); + + await params.cli.test('mono-repo-project', { + file: 'package-lock.json', + }); + const { body: npmFileBody } = params.server.popRequest(); + + await params.cli.test('mono-repo-project', { + file: 'pom.xml', + }); + const { body: mavenFileBody } = params.server.popRequest(); + + t.same( + rubyAllProjectsBody, + rubyFileBody, + 'Same body for --all-projects and --file=Gemfile.lock', + ); + + t.same( + npmAllProjectsBody, + npmFileBody, + 'Same body for --all-projects and --file=package-lock.json', + ); + + t.same( + mavenAllProjectsBody, + mavenFileBody, + 'Same body for --all-projects and --file=pom.xml', + ); + }, + + '`test maven-multi-app --all-projects --detection-depth=2`': ( + params, + utils, + ) => async (t) => { + utils.chdirWorkspaces(); + const spyPlugin = sinon.spy(params.plugins, 'loadPlugin'); + t.teardown(spyPlugin.restore); + + const result = await params.cli.test('maven-multi-app', { + allProjects: true, + detectionDepth: 2, + }); + + t.ok(spyPlugin.withArgs('maven').calledTwice, 'calls maven plugin'); + t.ok( + spyPlugin.withArgs('rubygems').notCalled, + 'did not call rubygems plugin', + ); + t.ok(spyPlugin.withArgs('npm').notCalled, 'did not call npm plugin'); + params.server.popRequests(2).forEach((req) => { + t.equal(req.method, 'POST', 'makes POST request'); + t.equal( + req.headers['x-snyk-cli-version'], + params.versionNumber, + 'sends version number', + ); + t.match(req.url, '/api/v1/test-dep-graph', 'posts to correct url'); + t.ok(req.body.depGraph, 'body contains depGraph'); + t.match( + req.body.depGraph.pkgManager.name, + /maven/, + 'depGraph has package manager', + ); + }); + t.match( + result, + 'Package manager: maven', + 'contains package manager maven', + ); + t.match( + result, + 'Target file: pom.xml', + 'contains target file pom.xml', + ); + t.match( + result, + `Target file: simple-child${path.sep}pom.xml`, + `contains target file simple-child${path.sep}pom.xml`, + ); + }, + + '`test large-mono-repo with --all-projects and --detection-depth=2`': ( + params, + utils, + ) => async (t) => { + utils.chdirWorkspaces(); + const spyPlugin = sinon.spy(params.plugins, 'loadPlugin'); + t.teardown(spyPlugin.restore); + await params.cli.test('large-mono-repo', { + allProjects: true, + detectionDepth: 2, + }); + t.equals( + spyPlugin.withArgs('rubygems').callCount, + 1, + 'calls rubygems plugin once', + ); + t.equals( + spyPlugin.withArgs('npm').callCount, + 19, + 'calls npm plugin 19 times', + ); + t.equals( + spyPlugin.withArgs('maven').callCount, + 1, + 'calls maven plugin once', + ); + }, + + '`test large-mono-repo with --all-projects and --detection-depth=7`': ( + params, + utils, + ) => async (t) => { + utils.chdirWorkspaces(); + const spyPlugin = sinon.spy(params.plugins, 'loadPlugin'); + t.teardown(spyPlugin.restore); + await params.cli.test('large-mono-repo', { + allProjects: true, + detectionDepth: 7, + }); + t.equals( + spyPlugin.withArgs('rubygems').callCount, + 19, + 'calls rubygems plugin 19 times', + ); + t.equals( + spyPlugin.withArgs('npm').callCount, + 19, + 'calls npm plugin 19 times', + ); + t.equals( + spyPlugin.withArgs('maven').callCount, + 6, + 'calls maven plugin 6 times', + ); + }, + '`test mono-repo-project-manifests-only --all-projects`': ( params, utils, @@ -167,7 +326,7 @@ export const AllProjectsTests: AcceptanceTests = { t.fail('should have thrown'); } catch (err) { const req = params.server.popRequest(); - t.equal(req.query.ignorePolicy, 'true'); + t.equal(req.query.ignorePolicy, 'true', 'should request ignore policy'); const res = err.message; t.match( res, diff --git a/test/acceptance/workspaces/ruby-app-no-vulns/test-result.json b/test/acceptance/workspaces/ruby-app-no-vulns/test-result.json index 1cb0e1e57c..dbc3b9de19 100644 --- a/test/acceptance/workspaces/ruby-app-no-vulns/test-result.json +++ b/test/acceptance/workspaces/ruby-app-no-vulns/test-result.json @@ -9,6 +9,7 @@ "policy": "# Snyk (https://snyk.io) policy file, patches or ignores known vulnerabilities.\nversion: v1.13.1\nignore: {}\npatch: {}\n", "ignoreSettings": null, "projectName": "ruby-app-no-vulns", + "displayTargetFile": "Gemfile", "summary": "No known vulnerabilities", "filesystemPolicy": false, "uniqueCount": 0, diff --git a/test/acceptance/workspaces/ruby-app-policy/test-result-cloud-ignore.json b/test/acceptance/workspaces/ruby-app-policy/test-result-cloud-ignore.json index 8a89262112..d7a080a423 100644 --- a/test/acceptance/workspaces/ruby-app-policy/test-result-cloud-ignore.json +++ b/test/acceptance/workspaces/ruby-app-policy/test-result-cloud-ignore.json @@ -283,6 +283,7 @@ "policy": "# Snyk (https://snyk.io) policy file, patches or ignores known vulnerabilities.\nversion: v1.13.1\n# ignores vulnerabilities until expiry date; change duration by modifying expiry date\nignore:\n SNYK-RUBY-LYNX-20160:\n - '*':\n reason: will check again in 2100\n expires: 2100-01-01T00:00:00.000Z\n source: cli\n SNYK-RUBY-SANITIZE-22024:\n - '*':\n reason: who needs sanitization anyway\n created: '2018-11-23T07:33:16.687Z'\n ignoredBy:\n id: 3c2d7dd6-e86e-4842-8124-5766bf55e060\n name: brian@doogdog.com\n email: brian@doogdog.com\n reasonType: temporary-ignore\n disregardIfFixable: false\n source: api\npatch: {}\n", "ignoreSettings": null, "summary": "7 vulnerable dependency paths", + "displayTargetFile": "Gemfile", "filesystemPolicy": true, "filtered": { "ignore": [ diff --git a/test/acceptance/workspaces/ruby-app-policy/test-result.json b/test/acceptance/workspaces/ruby-app-policy/test-result.json index 5339f2e889..c07cf27285 100644 --- a/test/acceptance/workspaces/ruby-app-policy/test-result.json +++ b/test/acceptance/workspaces/ruby-app-policy/test-result.json @@ -337,6 +337,7 @@ "policy": "# Snyk (https://snyk.io) policy file, patches or ignores known vulnerabilities.\nversion: v1.13.1\n# ignores vulnerabilities until expiry date; change duration by modifying expiry date\nignore:\n SNYK-RUBY-LYNX-20160:\n - '*':\n reason: will check again in 2100\n expires: 2100-01-01T00:00:00.000Z\n source: cli\npatch: {}\n", "ignoreSettings": null, "summary": "7 vulnerable dependency paths", + "displayTargetFile": "Gemfile", "filesystemPolicy": true, "filtered": { "ignore": [ diff --git a/test/acceptance/workspaces/ruby-app-thresholds/test-result-high-severity.json b/test/acceptance/workspaces/ruby-app-thresholds/test-result-high-severity.json index 748752de4e..302bbfa774 100644 --- a/test/acceptance/workspaces/ruby-app-thresholds/test-result-high-severity.json +++ b/test/acceptance/workspaces/ruby-app-thresholds/test-result-high-severity.json @@ -230,6 +230,7 @@ "ignoreSettings": null, "severityThreshold": "high", "summary": "4 high severity vulnerable dependency paths", + "displayTargetFile": "Gemfile", "filesystemPolicy": false, "filtered": { "ignore": [], diff --git a/test/acceptance/workspaces/ruby-app-thresholds/test-result-low-severity.json b/test/acceptance/workspaces/ruby-app-thresholds/test-result-low-severity.json index 5b6b74e7e7..d5a7656a1e 100644 --- a/test/acceptance/workspaces/ruby-app-thresholds/test-result-low-severity.json +++ b/test/acceptance/workspaces/ruby-app-thresholds/test-result-low-severity.json @@ -389,6 +389,7 @@ "policy": "# Snyk (https://snyk.io) policy file, patches or ignores known vulnerabilities.\nversion: v1.13.1\nignore: {}\npatch: {}\n", "ignoreSettings": null, "summary": "7 vulnerable dependency paths", + "displayTargetFile": "Gemfile", "filesystemPolicy": false, "filtered": { "ignore": [], diff --git a/test/acceptance/workspaces/ruby-app-thresholds/test-result-medium-severity.json b/test/acceptance/workspaces/ruby-app-thresholds/test-result-medium-severity.json index 76a03cd561..a648b99f3b 100644 --- a/test/acceptance/workspaces/ruby-app-thresholds/test-result-medium-severity.json +++ b/test/acceptance/workspaces/ruby-app-thresholds/test-result-medium-severity.json @@ -338,6 +338,7 @@ "ignoreSettings": null, "severityThreshold": "medium", "summary": "6 medium or high severity vulnerable dependency paths", + "displayTargetFile": "Gemfile", "filesystemPolicy": false, "filtered": { "ignore": [], diff --git a/test/acceptance/workspaces/sbt-simple-struts/legacy-res-json.json b/test/acceptance/workspaces/sbt-simple-struts/legacy-res-json.json index 06af31f147..9fd68ca72b 100644 --- a/test/acceptance/workspaces/sbt-simple-struts/legacy-res-json.json +++ b/test/acceptance/workspaces/sbt-simple-struts/legacy-res-json.json @@ -1963,6 +1963,7 @@ "policy": "# Snyk (https://snyk.io) policy file, patches or ignores known vulnerabilities.\nversion: v1.13.1\nignore: {}\npatch: {}\n", "ignoreSettings": null, "summary": "31 vulnerable dependency paths", + "displayTargetFile": "build.sbt", "filesystemPolicy": false, "projectName": "small-app:small-app_2.10", "filtered": {