diff --git a/help/help.txt b/help/help.txt index 4bf5cda8c1..a7364c0dc2 100644 --- a/help/help.txt +++ b/help/help.txt @@ -90,6 +90,18 @@ Maven options: --scan-all-unmanaged Auto detects maven jars and wars in given directory. Individual testing can be done with --file= + --reachable + (test and monitor commands only) + Analyze your source code to find which vulnerable + functions and packages are called. + --reachable-timeout= + (test and monitor commands only) + The amount of time (in seconds) to wait for Snyk + to gather reachability data. If it takes longer than + the specified interval, Reachable Vulnerabilities are + not reported. This does not affect regular test or + monitor output. + Defaults to waiting 300s (5 minutes). Gradle options: --sub-project= (alias: --gradle-sub-project) diff --git a/package.json b/package.json index e14eb81713..bacee8d91b 100644 --- a/package.json +++ b/package.json @@ -53,7 +53,7 @@ "author": "snyk.io", "license": "Apache-2.0", "dependencies": { - "@snyk/cli-interface": "2.8.0", + "@snyk/cli-interface": "2.8.1", "@snyk/dep-graph": "1.18.3", "@snyk/gemfile": "1.2.0", "@snyk/graphlib": "2.1.9-patch", @@ -80,7 +80,7 @@ "snyk-go-plugin": "1.14.2", "snyk-gradle-plugin": "3.5.1", "snyk-module": "3.1.0", - "snyk-mvn-plugin": "2.17.1", + "snyk-mvn-plugin": "2.17.3", "snyk-nodejs-lockfile-parser": "1.26.3", "snyk-nuget-plugin": "1.18.1", "snyk-php-plugin": "1.9.0", diff --git a/src/cli/args.ts b/src/cli/args.ts index 022a6acb2f..2bed5de2e1 100644 --- a/src/cli/args.ts +++ b/src/cli/args.ts @@ -36,6 +36,10 @@ const DEBUG_DEFAULT_NAMESPACES = [ 'snyk-mvn-plugin', ]; +// NOTE[muscar] This is accepted in seconds for UX reasons, the mavem plugin +// turns it into milliseconds before calling the call graph generator +const REACHABLE_VULNS_TIMEOUT = 5 * 60; // 5 min (in seconds) + function dashToCamelCase(dash) { return dash.indexOf('-') < 0 ? dash @@ -192,11 +196,17 @@ export function args(rawArgv: string[]): Args { 'all-projects', 'yarn-workspaces', 'detection-depth', + 'reachable', 'reachable-vulns', + 'reachable-timeout', + 'reachable-vulns-timeout', ]; for (const dashedArg of argumentsToTransform) { if (argv[dashedArg]) { const camelCased = dashToCamelCase(dashedArg); + if (camelCased === dashedArg) { + continue; + } argv[camelCased] = argv[dashedArg]; delete argv[dashedArg]; } @@ -218,10 +228,20 @@ export function args(rawArgv: string[]): Args { } } + if ( + argv.reachableTimeout === undefined && + argv.reachableVulnsTimeout === undefined + ) { + argv.reachableVulnsTimeout = REACHABLE_VULNS_TIMEOUT.toString(); + } + // Alias const aliases = { gradleSubProject: 'subProject', container: 'docker', + reachable: 'reachableVulns', + reachableTimeout: 'callGraphBuilderTimeout', + reachableVulnsTimeout: 'callGraphBuilderTimeout', }; for (const argAlias in aliases) { if (argv[argAlias]) { diff --git a/src/lib/monitor/index.ts b/src/lib/monitor/index.ts index 55e4565d16..b6fefea3ed 100644 --- a/src/lib/monitor/index.ts +++ b/src/lib/monitor/index.ts @@ -36,7 +36,11 @@ import { dropEmptyDeps } from './drop-empty-deps'; import { pruneTree } from './prune-dep-tree'; import { findAndLoadPolicy } from '../policy'; import { PluginMetadata } from '@snyk/cli-interface/legacy/plugin'; -import { CallGraph, ScannedProject } from '@snyk/cli-interface/legacy/common'; +import { + CallGraph, + CallGraphError, + ScannedProject, +} from '@snyk/cli-interface/legacy/common'; import { isGitTarget } from '../project-metadata/types'; import { serializeCallGraphWithMetrics } from '../reachable-vulns'; import { @@ -46,6 +50,7 @@ import { getTargetFile, } from './utils'; import { countPathsToGraphRoot } from '../utils'; +import * as alerts from '../alerts'; const debug = Debug('snyk'); @@ -213,7 +218,17 @@ async function monitorDepTree( depTree = dropEmptyDeps(depTree); let callGraphPayload; - if (scannedProject.callGraph) { + if (options.reachableVulns && scannedProject.callGraph?.innerError) { + const err = scannedProject.callGraph as CallGraphError; + analytics.add('callGraphError', err.innerError.toString()); + alerts.registerAlerts([ + { + type: 'error', + name: 'missing-call-graph', + msg: err.message, + }, + ]); + } else if (scannedProject.callGraph) { const { callGraph, nodeCount, edgeCount } = serializeCallGraphWithMetrics( scannedProject.callGraph, ); diff --git a/src/lib/snyk-test/run-test.ts b/src/lib/snyk-test/run-test.ts index ca6b614125..ce9d5d34cb 100644 --- a/src/lib/snyk-test/run-test.ts +++ b/src/lib/snyk-test/run-test.ts @@ -53,6 +53,8 @@ import { validateOptions } from '../options-validator'; import { findAndLoadPolicy } from '../policy'; import { assembleIacLocalPayloads, parseIacTestResult } from './run-iac-test'; import { Payload, PayloadBody, DepTreeFromResolveDeps } from './types'; +import { CallGraphError } from '@snyk/cli-interface/legacy/common'; +import * as alerts from '../alerts'; const debug = debugModule('snyk'); @@ -513,7 +515,20 @@ async function assembleLocalPayloads( body.depGraph = depGraph; } - if (scannedProject.callGraph) { + if ( + options.reachableVulns && + (scannedProject.callGraph as CallGraphError).innerError + ) { + const err = scannedProject.callGraph as CallGraphError; + analytics.add('callGraphError', err.innerError.toString()); + alerts.registerAlerts([ + { + type: 'error', + name: 'missing-call-graph', + msg: err.message, + }, + ]); + } else if (scannedProject.callGraph) { const { callGraph, nodeCount, diff --git a/src/lib/types.ts b/src/lib/types.ts index 32f0aa3254..fa7ed9f15b 100644 --- a/src/lib/types.ts +++ b/src/lib/types.ts @@ -19,6 +19,7 @@ export interface TestOptions { showVulnPaths: ShowVulnPaths; failOn?: FailOn; reachableVulns?: boolean; + reachableVulnsTimeout?: number; yarnWorkspaces?: boolean; } @@ -91,6 +92,7 @@ export interface MonitorOptions { // Used with the Docker plugin only. Allows application scanning. 'app-vulns'?: boolean; reachableVulns?: boolean; + reachableVulnsTimeout?: number; yarnWorkspaces?: boolean; } @@ -144,7 +146,6 @@ export type SupportedUserReachableFacingCliArgs = | 'file' | 'policy' | 'fail-on' - | 'reachable-vulns' | 'json' | 'package-manager' | 'packages-folder' @@ -160,7 +161,10 @@ export type SupportedUserReachableFacingCliArgs = | 'yarn-workspaces' | 'detection-depth' | 'project-name' - | 'reachable-vulns'; + | 'reachable' + | 'reachable-vulns' + | 'reachable-timeout' + | 'reachable-vulns-timeout'; export type SupportedCliCommands = | 'protect'