Skip to content

Commit

Permalink
fix: improve reliability around call graph generation
Browse files Browse the repository at this point in the history
  • Loading branch information
muscar committed Jul 21, 2020
1 parent 3d76c61 commit 44fc1e8
Show file tree
Hide file tree
Showing 6 changed files with 73 additions and 7 deletions.
12 changes: 12 additions & 0 deletions help/help.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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=<jar-file-name>
--reachable
(test and monitor commands only)
Analyze your source code to find which vulnerable
functions and packages are called.
--reachable-timeout=<number>
(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=<string> (alias: --gradle-sub-project)
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand All @@ -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",
Expand Down
20 changes: 20 additions & 0 deletions src/cli/args.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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];
}
Expand All @@ -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]) {
Expand Down
19 changes: 17 additions & 2 deletions src/lib/monitor/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -46,6 +50,7 @@ import {
getTargetFile,
} from './utils';
import { countPathsToGraphRoot } from '../utils';
import * as alerts from '../alerts';

const debug = Debug('snyk');

Expand Down Expand Up @@ -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,
);
Expand Down
17 changes: 16 additions & 1 deletion src/lib/snyk-test/run-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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');

Expand Down Expand Up @@ -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,
Expand Down
8 changes: 6 additions & 2 deletions src/lib/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export interface TestOptions {
showVulnPaths: ShowVulnPaths;
failOn?: FailOn;
reachableVulns?: boolean;
reachableVulnsTimeout?: number;
yarnWorkspaces?: boolean;
}

Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -144,7 +146,6 @@ export type SupportedUserReachableFacingCliArgs =
| 'file'
| 'policy'
| 'fail-on'
| 'reachable-vulns'
| 'json'
| 'package-manager'
| 'packages-folder'
Expand All @@ -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'
Expand Down

0 comments on commit 44fc1e8

Please sign in to comment.