From cc8730e28974fe7c74750a4637506d9ea0cedf8b Mon Sep 17 00:00:00 2001 From: thisislawatts Date: Tue, 26 Jan 2021 15:00:31 +0100 Subject: [PATCH 1/3] feat: adds support for critical severity --- src/cli/commands/protect/prompts.ts | 5 +++++ src/cli/commands/test/formatters/legacy-format-issue.ts | 5 +++++ .../test/formatters/remediation-based-format-issues.ts | 5 +++++ src/cli/commands/test/iac-output.ts | 5 +++++ src/lib/snyk-test/common.ts | 5 +++++ src/lib/snyk-test/legacy.ts | 1 + 6 files changed, 26 insertions(+) diff --git a/src/cli/commands/protect/prompts.ts b/src/cli/commands/protect/prompts.ts index 7cf36f31b8..ee3f353e0f 100644 --- a/src/cli/commands/protect/prompts.ts +++ b/src/cli/commands/protect/prompts.ts @@ -62,6 +62,11 @@ function createSeverityBasedIssueHeading(msg: string, severity: SEVERITY) { return chalk.bold.red(text); }, }, + critical: { + colorFunc(text) { + return chalk.bold.magenta(text); + }, + }, }; return severitiesColourMapping[severity].colorFunc(msg); } diff --git a/src/cli/commands/test/formatters/legacy-format-issue.ts b/src/cli/commands/test/formatters/legacy-format-issue.ts index 39945e27f8..83f2f53f49 100644 --- a/src/cli/commands/test/formatters/legacy-format-issue.ts +++ b/src/cli/commands/test/formatters/legacy-format-issue.ts @@ -111,6 +111,11 @@ function createSeverityBasedIssueHeading({ return chalk.bold.red(text); }, }, + critical: { + colorFunc(text) { + return chalk.bold.magenta(text); + }, + }, }; let originalSeverityStr = ''; diff --git a/src/cli/commands/test/formatters/remediation-based-format-issues.ts b/src/cli/commands/test/formatters/remediation-based-format-issues.ts index 29c53c1ae8..463fc00b91 100644 --- a/src/cli/commands/test/formatters/remediation-based-format-issues.ts +++ b/src/cli/commands/test/formatters/remediation-based-format-issues.ts @@ -454,6 +454,11 @@ export function formatIssue( return chalk.redBright(text); }, }, + critical: { + colorFunc(text) { + return chalk.magentaBright(`🚨` + text + ` 🚨 `); + }, + }, }; const newBadge = isNew ? ' (new)' : ''; const name = vulnerableModule ? ` in ${chalk.bold(vulnerableModule)}` : ''; diff --git a/src/cli/commands/test/iac-output.ts b/src/cli/commands/test/iac-output.ts index d95575935f..7d338adbf8 100644 --- a/src/cli/commands/test/iac-output.ts +++ b/src/cli/commands/test/iac-output.ts @@ -35,6 +35,11 @@ function formatIacIssue( return chalk.redBright(text); }, }, + critical: { + colorFunc(text) { + return chalk.magentaBright(text); + }, + }, }; const newBadge = isNew ? ' (new)' : ''; const name = issue.subType ? ` in ${chalk.bold(issue.subType)}` : ''; diff --git a/src/lib/snyk-test/common.ts b/src/lib/snyk-test/common.ts index 6362b7d55d..b496659a52 100644 --- a/src/lib/snyk-test/common.ts +++ b/src/lib/snyk-test/common.ts @@ -24,6 +24,7 @@ export enum SEVERITY { LOW = 'low', MEDIUM = 'medium', HIGH = 'high', + CRITICAL = 'critical', } export const SEVERITIES: Array<{ verboseName: SEVERITY; @@ -41,6 +42,10 @@ export const SEVERITIES: Array<{ verboseName: SEVERITY.HIGH, value: 3, }, + { + verboseName: SEVERITY.CRITICAL, + value: 4, + }, ]; export enum FAIL_ON { diff --git a/src/lib/snyk-test/legacy.ts b/src/lib/snyk-test/legacy.ts index 2aec4a68db..720775655d 100644 --- a/src/lib/snyk-test/legacy.ts +++ b/src/lib/snyk-test/legacy.ts @@ -20,6 +20,7 @@ export enum SEVERITY { LOW = 'low', MEDIUM = 'medium', HIGH = 'high', + CRITICAL = 'critical', } export enum REACHABILITY { From ea94dea7265622746b145b37d65dcd58675ac676 Mon Sep 17 00:00:00 2001 From: Karen Yavine Shemesh Date: Tue, 9 Feb 2021 14:37:40 +0200 Subject: [PATCH 2/3] chore: unified place for severity-to-color mapping chore: add default color for unknown severity and avoid crashing test: update testing to include critical severity --- src/cli/commands/protect/prompts.ts | 31 ++-- .../test/formatters/legacy-format-issue.ts | 31 ++-- .../remediation-based-format-issues.ts | 34 ++--- src/cli/commands/test/iac-output.ts | 31 ++-- src/lib/snyk-test/common.ts | 53 +++++++ .../acceptance/cli-test/cli-test.ruby.spec.ts | 75 ++++++++++ .../test-graph-result-critical-severity.json | 76 ++++++++++ .../test-result-critical-severity.json | 132 ++++++++++++++++++ .../test-result-high-severity.json | 2 +- .../test-result-medium-severity.json | 2 +- 10 files changed, 372 insertions(+), 95 deletions(-) create mode 100644 test/acceptance/workspaces/ruby-app-thresholds/test-graph-result-critical-severity.json create mode 100644 test/acceptance/workspaces/ruby-app-thresholds/test-result-critical-severity.json diff --git a/src/cli/commands/protect/prompts.ts b/src/cli/commands/protect/prompts.ts index ee3f353e0f..8abe6edac2 100644 --- a/src/cli/commands/protect/prompts.ts +++ b/src/cli/commands/protect/prompts.ts @@ -20,6 +20,10 @@ import * as config from '../../../lib/config'; import * as snykPolicy from 'snyk-policy'; import chalk from 'chalk'; import { AnnotatedIssue, SEVERITY } from '../../../lib/snyk-test/legacy'; +import { + legacySeveritiesColourMapping, + defaultSeverityColor, +} from '../../../lib/snyk-test/common'; import { titleCaseText } from '../test/formatters/legacy-format-issue'; const debug = debugModule('snyk'); @@ -46,29 +50,10 @@ function sort(prop) { function createSeverityBasedIssueHeading(msg: string, severity: SEVERITY) { // Example: ✗ Medium severity vulnerability found in xmldom - const severitiesColourMapping = { - low: { - colorFunc(text) { - return chalk.bold.blue(text); - }, - }, - medium: { - colorFunc(text) { - return chalk.bold.yellow(text); - }, - }, - high: { - colorFunc(text) { - return chalk.bold.red(text); - }, - }, - critical: { - colorFunc(text) { - return chalk.bold.magenta(text); - }, - }, - }; - return severitiesColourMapping[severity].colorFunc(msg); + const severityColor = legacySeveritiesColourMapping[severity] + ? legacySeveritiesColourMapping[severity] + : defaultSeverityColor; + return severityColor.colorFunc(msg); } function sortUpgradePrompts(a, b) { diff --git a/src/cli/commands/test/formatters/legacy-format-issue.ts b/src/cli/commands/test/formatters/legacy-format-issue.ts index 83f2f53f49..8be1033761 100644 --- a/src/cli/commands/test/formatters/legacy-format-issue.ts +++ b/src/cli/commands/test/formatters/legacy-format-issue.ts @@ -18,6 +18,10 @@ import { import { formatLegalInstructions } from './legal-license-instructions'; import { getReachabilityText } from './format-reachability'; import { PATH_SEPARATOR } from '../../constants'; +import { + legacySeveritiesColourMapping, + defaultSeverityColor, +} from '../../../../lib/snyk-test/common'; export function formatIssues( vuln: GroupedVuln, @@ -95,28 +99,9 @@ function createSeverityBasedIssueHeading({ }: CreateSeverityBasedIssueHeading) { // Example: ✗ Medium severity vulnerability found in xmldom const vulnTypeText = type === 'license' ? 'issue' : 'vulnerability'; - const severitiesColourMapping = { - low: { - colorFunc(text) { - return chalk.bold.blue(text); - }, - }, - medium: { - colorFunc(text) { - return chalk.bold.yellow(text); - }, - }, - high: { - colorFunc(text) { - return chalk.bold.red(text); - }, - }, - critical: { - colorFunc(text) { - return chalk.bold.magenta(text); - }, - }, - }; + const severityColor = legacySeveritiesColourMapping[severity] + ? legacySeveritiesColourMapping[severity] + : defaultSeverityColor; let originalSeverityStr = ''; if (originalSeverity && originalSeverity !== severity) { @@ -124,7 +109,7 @@ function createSeverityBasedIssueHeading({ } return ( - severitiesColourMapping[severity].colorFunc( + severityColor.colorFunc( '✗ ' + titleCaseText(severity) + ` severity${originalSeverityStr} ` + diff --git a/src/cli/commands/test/formatters/remediation-based-format-issues.ts b/src/cli/commands/test/formatters/remediation-based-format-issues.ts index 463fc00b91..34b2a85649 100644 --- a/src/cli/commands/test/formatters/remediation-based-format-issues.ts +++ b/src/cli/commands/test/formatters/remediation-based-format-issues.ts @@ -14,7 +14,11 @@ import { SEVERITY, UpgradeRemediation, } from '../../../../lib/snyk-test/legacy'; -import { SEVERITIES } from '../../../../lib/snyk-test/common'; +import { + SEVERITIES, + severitiesColourMapping, + defaultSeverityColor, +} from '../../../../lib/snyk-test/common'; import { formatLegalInstructions } from './legal-license-instructions'; import { formatReachability, @@ -438,28 +442,10 @@ export function formatIssue( reachability?: REACHABILITY, sampleReachablePaths?: SampleReachablePaths, ): string { - const severitiesColourMapping = { - low: { - colorFunc(text) { - return chalk.blueBright(text); - }, - }, - medium: { - colorFunc(text) { - return chalk.yellowBright(text); - }, - }, - high: { - colorFunc(text) { - return chalk.redBright(text); - }, - }, - critical: { - colorFunc(text) { - return chalk.magentaBright(`🚨` + text + ` 🚨 `); - }, - }, - }; + const severityColor = severitiesColourMapping[severity] + ? severitiesColourMapping[severity] + : defaultSeverityColor; + const newBadge = isNew ? ' (new)' : ''; const name = vulnerableModule ? ` in ${chalk.bold(vulnerableModule)}` : ''; let legalLicenseInstructionsText; @@ -512,7 +498,7 @@ export function formatIssue( } return ( - severitiesColourMapping[severity].colorFunc( + severityColor.colorFunc( ` ✗ ${chalk.bold(title)}${newBadge} [${titleCaseText( severity, )} Severity${originalSeverityStr}]`, diff --git a/src/cli/commands/test/iac-output.ts b/src/cli/commands/test/iac-output.ts index 7d338adbf8..d654ed4594 100644 --- a/src/cli/commands/test/iac-output.ts +++ b/src/cli/commands/test/iac-output.ts @@ -10,6 +10,10 @@ import { printPath } from './formatters/remediation-based-format-issues'; import { titleCaseText } from './formatters/legacy-format-issue'; import * as sarif from 'sarif'; import { SEVERITY } from '../../../lib/snyk-test/legacy'; +import { + severitiesColourMapping, + defaultSeverityColor, +} from '../../../lib/snyk-test/common'; import { IacFileInDirectory } from '../../../lib/types'; import upperFirst = require('lodash.upperfirst'); const debug = Debug('iac-output'); @@ -19,28 +23,6 @@ function formatIacIssue( isNew: boolean, path: string[], ): string { - const severitiesColourMapping = { - low: { - colorFunc(text) { - return chalk.blueBright(text); - }, - }, - medium: { - colorFunc(text) { - return chalk.yellowBright(text); - }, - }, - high: { - colorFunc(text) { - return chalk.redBright(text); - }, - }, - critical: { - colorFunc(text) { - return chalk.magentaBright(text); - }, - }, - }; const newBadge = isNew ? ' (new)' : ''; const name = issue.subType ? ` in ${chalk.bold(issue.subType)}` : ''; @@ -53,9 +35,12 @@ function formatIacIssue( const description = extractOverview(issue.description).trim(); const descriptionLine = `\n ${description}\n`; + const severityColor = severitiesColourMapping[issue.severity] + ? severitiesColourMapping[issue.severity] + : defaultSeverityColor; return ( - severitiesColourMapping[issue.severity].colorFunc( + severityColor.colorFunc( ` ✗ ${chalk.bold(issue.title)}${newBadge} [${titleCaseText( issue.severity, )} Severity]`, diff --git a/src/lib/snyk-test/common.ts b/src/lib/snyk-test/common.ts index b496659a52..b8bb757871 100644 --- a/src/lib/snyk-test/common.ts +++ b/src/lib/snyk-test/common.ts @@ -1,4 +1,5 @@ import * as config from '../config'; +import chalk from 'chalk'; export function assembleQueryString(options) { const org = options.org || config.org || null; @@ -48,6 +49,58 @@ export const SEVERITIES: Array<{ }, ]; +export const severitiesColourMapping = { + low: { + colorFunc(text) { + return chalk.blueBright(text); + }, + }, + medium: { + colorFunc(text) { + return chalk.yellowBright(text); + }, + }, + high: { + colorFunc(text) { + return chalk.redBright(text); + }, + }, + critical: { + colorFunc(text) { + return chalk.magentaBright(text); + }, + }, +}; + +export const legacySeveritiesColourMapping = { + low: { + colorFunc(text) { + return chalk.bold.blue(text); + }, + }, + medium: { + colorFunc(text) { + return chalk.bold.yellow(text); + }, + }, + high: { + colorFunc(text) { + return chalk.bold.red(text); + }, + }, + critical: { + colorFunc(text) { + return chalk.bold.magenta(text); + }, + }, +}; + +export const defaultSeverityColor = { + colorFunc(text) { + return chalk.grey(text); + }, +}; + export enum FAIL_ON { all = 'all', upgradable = 'upgradable', diff --git a/test/acceptance/cli-test/cli-test.ruby.spec.ts b/test/acceptance/cli-test/cli-test.ruby.spec.ts index 0a27935196..c6379b7e67 100644 --- a/test/acceptance/cli-test/cli-test.ruby.spec.ts +++ b/test/acceptance/cli-test/cli-test.ruby.spec.ts @@ -456,6 +456,81 @@ export const RubyTests: AcceptanceTests = { } }, + '`test ruby-app-thresholds --severity-threshold=critical': ( + params, + utils, + ) => async (t) => { + utils.chdirWorkspaces(); + + params.server.setNextResponse( + getWorkspaceJSON( + 'ruby-app-thresholds', + 'test-graph-result-critical-severity.json', + ), + ); + + try { + await params.cli.test('ruby-app-thresholds', { + severityThreshold: 'critical', + }); + t.fail('should have thrown'); + } catch (err) { + const req = params.server.popRequest(); + t.is(req.query.severityThreshold, 'critical'); + + const res = err.message; + + t.match( + res, + 'Tested 7 dependencies for known vulnerabilities, found 1 vulnerability, 2 vulnerable paths', + '1 vuln', + ); + } + }, + + '`test ruby-app-thresholds --severity-threshold=critical --json`': ( + params, + utils, + ) => async (t) => { + utils.chdirWorkspaces(); + + params.server.setNextResponse( + getWorkspaceJSON( + 'ruby-app-thresholds', + 'test-graph-result-critical-severity.json', + ), + ); + + try { + await params.cli.test('ruby-app-thresholds', { + severityThreshold: 'critical', + json: true, + }); + t.fail('should have thrown'); + } catch (err) { + const req = params.server.popRequest(); + t.is(req.query.severityThreshold, 'critical'); + + const res = JSON.parse(err.message); + + const expected = getWorkspaceJSON( + 'ruby-app-thresholds', + 'test-result-critical-severity.json', + ); + + t.deepEqual( + omit(res, ['vulnerabilities']), + omit(expected, ['vulnerabilities']), + 'metadata is ok', + ); + t.deepEqual( + sortBy(res.vulnerabilities, 'id'), + sortBy(expected.vulnerabilities, 'id'), + 'vulns are the same', + ); + } + }, + '`test ruby-app-policy`': (params, utils) => async (t) => { utils.chdirWorkspaces(); diff --git a/test/acceptance/workspaces/ruby-app-thresholds/test-graph-result-critical-severity.json b/test/acceptance/workspaces/ruby-app-thresholds/test-graph-result-critical-severity.json new file mode 100644 index 0000000000..633506add3 --- /dev/null +++ b/test/acceptance/workspaces/ruby-app-thresholds/test-graph-result-critical-severity.json @@ -0,0 +1,76 @@ +{ + "result": { + "affectedPkgs": { + "nokogiri@1.8.5": { + "pkg": { + "name": "nokogiri", + "version": "1.8.5" + }, + "issues": { + "SNYK-RUBY-NOKOGIRI-20299": { + "issueId": "SNYK-RUBY-NOKOGIRI-20299", + "fixInfo": { + "isPatchable": false, + "upgradePaths": [] + } + } + } + } + }, + "issuesData": { + "SNYK-RUBY-NOKOGIRI-20299": { + "CVSSv3": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:L", + "alternativeIds": [], + "creationTime": "2017-01-12T12:37:00Z", + "credit": [ + "Snyk Security Research Team" + ], + "cvssScore": 7.3, + "description": "## Overview\n[nokogiri](https://rubygems.org/gems/nokogiri) is an HTML, XML, SAX, and Reader parser, with the ability to search documents via XPath or CSS3 selectors.\n\nAffected versions of this Gem are vulnerable to XML External Entity (XXE) attacks when opting into the `DTDLOAD` option and opting out of the `NONET` option.\n`Nokogiri` is affected by series of vulnerabilities in libxml2 and libxslt, which are libraries it depends on. When handling the expansion of XML external entities (XXE) in libxml2, you can specify documents to be read. Opting into the `DTDLOAD` option and opting out of the `NONET` option in `Nokogiri` allows unknown documents to be loaded from the network. This can be used by attackers to load specially crafted XML documents on an internal XML parsing service and may lead to unauthorized disclosure of potentially sensitive information.\n\n**Note:** This vulnerability exists also in versions `< 1.5.4` regardless of the options opted into or out of. See information [here](https://snyk.io/vuln/SNYK-RUBY-NOKOGIRI-20298)\n\n## Details\n\nXXE Injection is a type of attack against an application that parses XML input.\nXML is a markup language that defines a set of rules for encoding documents in a format that is both human-readable and machine-readable. By default, many XML processors allow specification of an external entity, a URI that is dereferenced and evaluated during XML processing. When an XML document is being parsed, the parser can make a request and include the content at the specified URI inside of the XML document.\n\nAttacks can include disclosing local files, which may contain sensitive data such as passwords or private user data, using file: schemes or relative paths in the system identifier.\n\nFor example, below is a sample XML document, containing an XML element- username.\n\n```xml\n\n John\n\n```\n\nAn external XML entity - `xxe`, is defined using a system identifier and present within a DOCTYPE header. These entities can access local or remote content. For example the below code contains an external XML entity that would fetch the content of `/etc/passwd` and display it to the user rendered by `username`.\n\n```xml\n\n]>\n &xxe;\n\n```\n\nOther XXE Injection attacks can access local resources that may not stop returning data, possibly impacting application availability and leading to Denial of Service.\n\n## Remediation\nNokogiri suggests not to opt-out of `NONET` unless only trusted documents are being parsed.\nThere currently is no fix in libxml2 as of September 17th, 2017.\n`Nokogiri` will be waiting for a fix upstream to update.\n\n## Disclosure Timeline\n- January 11th, 2017 - Reported the issue to [Mike Dalessio](https://github.com/flavorjones) of Nokogiri Core.\n- January 11th, 2017 - Issue triaged and acknowledged by [Mike Dalessio](https://github.com/flavorjones) of Nokogiri Core.\n\n## References\n- [GitHub Issue](https://github.com/sparklemotion/nokogiri/issues/1582)\n- [CVE-2016-9318](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2016-9318)\n", + "disclosureTime": "2017-01-11T21:00:00Z", + "functions": [], + "id": "SNYK-RUBY-NOKOGIRI-20299", + "identifiers": { + "CVE": [], + "CWE": [ + "CWE-611" + ] + }, + "language": "ruby", + "methods": [], + "modificationTime": "2018-11-21T10:10:04.153595Z", + "moduleName": "nokogiri", + "packageManager": "rubygems", + "packageName": "nokogiri", + "patches": [], + "publicationTime": "2017-01-16T21:00:00Z", + "references": [ + { + "title": "CVE-2016-9318", + "url": "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2016-9318" + }, + { + "title": "GitHub Issue", + "url": "https://github.com/sparklemotion/nokogiri/issues/1582" + } + ], + "semver": { + "vulnerable": [ + ">= 1.5.4" + ] + }, + "severity": "critical", + "title": "XML External Entity (XXE) Injection" + } + } + }, + "meta": { + "isPublic": false, + "isLicensesEnabled": false, + "licensesPolicy": null, + "policy": "# Snyk (https://snyk.io) policy file, patches or ignores known vulnerabilities.\nversion: v1.13.1\nignore: {}\npatch: {}\n", + "ignoreSettings": null, + "org": "test-org" + }, + "filesystemPolicy": false +} diff --git a/test/acceptance/workspaces/ruby-app-thresholds/test-result-critical-severity.json b/test/acceptance/workspaces/ruby-app-thresholds/test-result-critical-severity.json new file mode 100644 index 0000000000..b6e0915c88 --- /dev/null +++ b/test/acceptance/workspaces/ruby-app-thresholds/test-result-critical-severity.json @@ -0,0 +1,132 @@ +{ + "ok": false, + "vulnerabilities": [ + { + "CVSSv3": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:L", + "alternativeIds": [], + "creationTime": "2017-01-12T12:37:00Z", + "credit": [ + "Snyk Security Research Team" + ], + "cvssScore": 7.3, + "description": "## Overview\n[nokogiri](https://rubygems.org/gems/nokogiri) is an HTML, XML, SAX, and Reader parser, with the ability to search documents via XPath or CSS3 selectors.\n\nAffected versions of this Gem are vulnerable to XML External Entity (XXE) attacks when opting into the `DTDLOAD` option and opting out of the `NONET` option.\n`Nokogiri` is affected by series of vulnerabilities in libxml2 and libxslt, which are libraries it depends on. When handling the expansion of XML external entities (XXE) in libxml2, you can specify documents to be read. Opting into the `DTDLOAD` option and opting out of the `NONET` option in `Nokogiri` allows unknown documents to be loaded from the network. This can be used by attackers to load specially crafted XML documents on an internal XML parsing service and may lead to unauthorized disclosure of potentially sensitive information.\n\n**Note:** This vulnerability exists also in versions `< 1.5.4` regardless of the options opted into or out of. See information [here](https://snyk.io/vuln/SNYK-RUBY-NOKOGIRI-20298)\n\n## Details\n\nXXE Injection is a type of attack against an application that parses XML input.\nXML is a markup language that defines a set of rules for encoding documents in a format that is both human-readable and machine-readable. By default, many XML processors allow specification of an external entity, a URI that is dereferenced and evaluated during XML processing. When an XML document is being parsed, the parser can make a request and include the content at the specified URI inside of the XML document.\n\nAttacks can include disclosing local files, which may contain sensitive data such as passwords or private user data, using file: schemes or relative paths in the system identifier.\n\nFor example, below is a sample XML document, containing an XML element- username.\n\n```xml\n\n John\n\n```\n\nAn external XML entity - `xxe`, is defined using a system identifier and present within a DOCTYPE header. These entities can access local or remote content. For example the below code contains an external XML entity that would fetch the content of `/etc/passwd` and display it to the user rendered by `username`.\n\n```xml\n\n]>\n &xxe;\n\n```\n\nOther XXE Injection attacks can access local resources that may not stop returning data, possibly impacting application availability and leading to Denial of Service.\n\n## Remediation\nNokogiri suggests not to opt-out of `NONET` unless only trusted documents are being parsed.\nThere currently is no fix in libxml2 as of September 17th, 2017.\n`Nokogiri` will be waiting for a fix upstream to update.\n\n## Disclosure Timeline\n- January 11th, 2017 - Reported the issue to [Mike Dalessio](https://github.com/flavorjones) of Nokogiri Core.\n- January 11th, 2017 - Issue triaged and acknowledged by [Mike Dalessio](https://github.com/flavorjones) of Nokogiri Core.\n\n## References\n- [GitHub Issue](https://github.com/sparklemotion/nokogiri/issues/1582)\n- [CVE-2016-9318](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2016-9318)\n", + "disclosureTime": "2017-01-11T21:00:00Z", + "functions": [], + "id": "SNYK-RUBY-NOKOGIRI-20299", + "identifiers": { + "CVE": [], + "CWE": [ + "CWE-611" + ] + }, + "language": "ruby", + "methods": [], + "modificationTime": "2018-11-21T10:10:04.153595Z", + "moduleName": "nokogiri", + "packageManager": "rubygems", + "packageName": "nokogiri", + "patches": [], + "publicationTime": "2017-01-16T21:00:00Z", + "references": [ + { + "title": "CVE-2016-9318", + "url": "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2016-9318" + }, + { + "title": "GitHub Issue", + "url": "https://github.com/sparklemotion/nokogiri/issues/1582" + } + ], + "semver": { + "vulnerable": [ + ">= 1.5.4" + ] + }, + "severity": "critical", + "title": "XML External Entity (XXE) Injection", + "from": [ + "ruby-app-thresholds@*", + "sanitize@4.6.2", + "nokogiri@1.8.5" + ], + "upgradePath": [], + "version": "1.8.5", + "name": "nokogiri", + "isUpgradable": false, + "isPatchable": false + }, + { + "CVSSv3": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:L", + "alternativeIds": [], + "creationTime": "2017-01-12T12:37:00Z", + "credit": [ + "Snyk Security Research Team" + ], + "cvssScore": 7.3, + "description": "## Overview\n[nokogiri](https://rubygems.org/gems/nokogiri) is an HTML, XML, SAX, and Reader parser, with the ability to search documents via XPath or CSS3 selectors.\n\nAffected versions of this Gem are vulnerable to XML External Entity (XXE) attacks when opting into the `DTDLOAD` option and opting out of the `NONET` option.\n`Nokogiri` is affected by series of vulnerabilities in libxml2 and libxslt, which are libraries it depends on. When handling the expansion of XML external entities (XXE) in libxml2, you can specify documents to be read. Opting into the `DTDLOAD` option and opting out of the `NONET` option in `Nokogiri` allows unknown documents to be loaded from the network. This can be used by attackers to load specially crafted XML documents on an internal XML parsing service and may lead to unauthorized disclosure of potentially sensitive information.\n\n**Note:** This vulnerability exists also in versions `< 1.5.4` regardless of the options opted into or out of. See information [here](https://snyk.io/vuln/SNYK-RUBY-NOKOGIRI-20298)\n\n## Details\n\nXXE Injection is a type of attack against an application that parses XML input.\nXML is a markup language that defines a set of rules for encoding documents in a format that is both human-readable and machine-readable. By default, many XML processors allow specification of an external entity, a URI that is dereferenced and evaluated during XML processing. When an XML document is being parsed, the parser can make a request and include the content at the specified URI inside of the XML document.\n\nAttacks can include disclosing local files, which may contain sensitive data such as passwords or private user data, using file: schemes or relative paths in the system identifier.\n\nFor example, below is a sample XML document, containing an XML element- username.\n\n```xml\n\n John\n\n```\n\nAn external XML entity - `xxe`, is defined using a system identifier and present within a DOCTYPE header. These entities can access local or remote content. For example the below code contains an external XML entity that would fetch the content of `/etc/passwd` and display it to the user rendered by `username`.\n\n```xml\n\n]>\n &xxe;\n\n```\n\nOther XXE Injection attacks can access local resources that may not stop returning data, possibly impacting application availability and leading to Denial of Service.\n\n## Remediation\nNokogiri suggests not to opt-out of `NONET` unless only trusted documents are being parsed.\nThere currently is no fix in libxml2 as of September 17th, 2017.\n`Nokogiri` will be waiting for a fix upstream to update.\n\n## Disclosure Timeline\n- January 11th, 2017 - Reported the issue to [Mike Dalessio](https://github.com/flavorjones) of Nokogiri Core.\n- January 11th, 2017 - Issue triaged and acknowledged by [Mike Dalessio](https://github.com/flavorjones) of Nokogiri Core.\n\n## References\n- [GitHub Issue](https://github.com/sparklemotion/nokogiri/issues/1582)\n- [CVE-2016-9318](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2016-9318)\n", + "disclosureTime": "2017-01-11T21:00:00Z", + "functions": [], + "id": "SNYK-RUBY-NOKOGIRI-20299", + "identifiers": { + "CVE": [], + "CWE": [ + "CWE-611" + ] + }, + "language": "ruby", + "methods": [], + "modificationTime": "2018-11-21T10:10:04.153595Z", + "moduleName": "nokogiri", + "packageManager": "rubygems", + "packageName": "nokogiri", + "patches": [], + "publicationTime": "2017-01-16T21:00:00Z", + "references": [ + { + "title": "CVE-2016-9318", + "url": "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2016-9318" + }, + { + "title": "GitHub Issue", + "url": "https://github.com/sparklemotion/nokogiri/issues/1582" + } + ], + "semver": { + "vulnerable": [ + ">= 1.5.4" + ] + }, + "severity": "critical", + "title": "XML External Entity (XXE) Injection", + "from": [ + "ruby-app-thresholds@*", + "sanitize@4.6.2", + "nokogumbo@1.5.0", + "nokogiri@1.8.5" + ], + "upgradePath": [], + "version": "1.8.5", + "name": "nokogiri", + "isUpgradable": false, + "isPatchable": false + } + ], + "dependencyCount": 7, + "org": "test-org", + "licensesPolicy": null, + "isPrivate": true, + "packageManager": "rubygems", + "policy": "# Snyk (https://snyk.io) policy file, patches or ignores known vulnerabilities.\nversion: v1.13.1\nignore: {}\npatch: {}\n", + "ignoreSettings": null, + "severityThreshold": "critical", + "summary": "2 critical severity vulnerable dependency paths", + "displayTargetFile": "Gemfile", + "filesystemPolicy": false, + "filtered": { + "ignore": [], + "patch": [] + }, + "projectName": "ruby-app-thresholds", + "uniqueCount": 1, + "path": "ruby-app-thresholds" +} 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 302bbfa774..73b8043bbb 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 @@ -229,7 +229,7 @@ "policy": "# Snyk (https://snyk.io) policy file, patches or ignores known vulnerabilities.\nversion: v1.13.1\nignore: {}\npatch: {}\n", "ignoreSettings": null, "severityThreshold": "high", - "summary": "4 high severity vulnerable dependency paths", + "summary": "4 high or critical severity vulnerable dependency paths", "displayTargetFile": "Gemfile", "filesystemPolicy": false, "filtered": { 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 a648b99f3b..ebfeef4395 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 @@ -337,7 +337,7 @@ "policy": "# Snyk (https://snyk.io) policy file, patches or ignores known vulnerabilities.\nversion: v1.13.1\nignore: {}\npatch: {}\n", "ignoreSettings": null, "severityThreshold": "medium", - "summary": "6 medium or high severity vulnerable dependency paths", + "summary": "6 medium or high or critical severity vulnerable dependency paths", "displayTargetFile": "Gemfile", "filesystemPolicy": false, "filtered": { From 96f619e0a87c40c4b83dedc8d240c07729b8c5ba Mon Sep 17 00:00:00 2001 From: Karen Yavine Shemesh Date: Mon, 15 Feb 2021 09:23:08 +0200 Subject: [PATCH 3/3] chore: export function to map severity to color --- src/cli/commands/protect/prompts.ts | 9 ++------- src/cli/commands/test/formatters/legacy-format-issue.ts | 9 ++------- .../test/formatters/remediation-based-format-issues.ts | 7 ++----- src/cli/commands/test/iac-output.ts | 9 ++------- src/lib/snyk-test/common.ts | 8 ++++++++ 5 files changed, 16 insertions(+), 26 deletions(-) diff --git a/src/cli/commands/protect/prompts.ts b/src/cli/commands/protect/prompts.ts index 8abe6edac2..31a368db77 100644 --- a/src/cli/commands/protect/prompts.ts +++ b/src/cli/commands/protect/prompts.ts @@ -20,10 +20,7 @@ import * as config from '../../../lib/config'; import * as snykPolicy from 'snyk-policy'; import chalk from 'chalk'; import { AnnotatedIssue, SEVERITY } from '../../../lib/snyk-test/legacy'; -import { - legacySeveritiesColourMapping, - defaultSeverityColor, -} from '../../../lib/snyk-test/common'; +import { getLegacySeveritiesColour } from '../../../lib/snyk-test/common'; import { titleCaseText } from '../test/formatters/legacy-format-issue'; const debug = debugModule('snyk'); @@ -50,9 +47,7 @@ function sort(prop) { function createSeverityBasedIssueHeading(msg: string, severity: SEVERITY) { // Example: ✗ Medium severity vulnerability found in xmldom - const severityColor = legacySeveritiesColourMapping[severity] - ? legacySeveritiesColourMapping[severity] - : defaultSeverityColor; + const severityColor = getLegacySeveritiesColour(severity); return severityColor.colorFunc(msg); } diff --git a/src/cli/commands/test/formatters/legacy-format-issue.ts b/src/cli/commands/test/formatters/legacy-format-issue.ts index 8be1033761..fb348d1ac3 100644 --- a/src/cli/commands/test/formatters/legacy-format-issue.ts +++ b/src/cli/commands/test/formatters/legacy-format-issue.ts @@ -18,10 +18,7 @@ import { import { formatLegalInstructions } from './legal-license-instructions'; import { getReachabilityText } from './format-reachability'; import { PATH_SEPARATOR } from '../../constants'; -import { - legacySeveritiesColourMapping, - defaultSeverityColor, -} from '../../../../lib/snyk-test/common'; +import { getLegacySeveritiesColour } from '../../../../lib/snyk-test/common'; export function formatIssues( vuln: GroupedVuln, @@ -99,9 +96,7 @@ function createSeverityBasedIssueHeading({ }: CreateSeverityBasedIssueHeading) { // Example: ✗ Medium severity vulnerability found in xmldom const vulnTypeText = type === 'license' ? 'issue' : 'vulnerability'; - const severityColor = legacySeveritiesColourMapping[severity] - ? legacySeveritiesColourMapping[severity] - : defaultSeverityColor; + const severityColor = getLegacySeveritiesColour(severity); let originalSeverityStr = ''; if (originalSeverity && originalSeverity !== severity) { diff --git a/src/cli/commands/test/formatters/remediation-based-format-issues.ts b/src/cli/commands/test/formatters/remediation-based-format-issues.ts index 34b2a85649..7c0f5a6b2a 100644 --- a/src/cli/commands/test/formatters/remediation-based-format-issues.ts +++ b/src/cli/commands/test/formatters/remediation-based-format-issues.ts @@ -16,8 +16,7 @@ import { } from '../../../../lib/snyk-test/legacy'; import { SEVERITIES, - severitiesColourMapping, - defaultSeverityColor, + getSeveritiesColour, } from '../../../../lib/snyk-test/common'; import { formatLegalInstructions } from './legal-license-instructions'; import { @@ -442,9 +441,7 @@ export function formatIssue( reachability?: REACHABILITY, sampleReachablePaths?: SampleReachablePaths, ): string { - const severityColor = severitiesColourMapping[severity] - ? severitiesColourMapping[severity] - : defaultSeverityColor; + const severityColor = getSeveritiesColour(severity); const newBadge = isNew ? ' (new)' : ''; const name = vulnerableModule ? ` in ${chalk.bold(vulnerableModule)}` : ''; diff --git a/src/cli/commands/test/iac-output.ts b/src/cli/commands/test/iac-output.ts index d654ed4594..bba45c02ba 100644 --- a/src/cli/commands/test/iac-output.ts +++ b/src/cli/commands/test/iac-output.ts @@ -10,10 +10,7 @@ import { printPath } from './formatters/remediation-based-format-issues'; import { titleCaseText } from './formatters/legacy-format-issue'; import * as sarif from 'sarif'; import { SEVERITY } from '../../../lib/snyk-test/legacy'; -import { - severitiesColourMapping, - defaultSeverityColor, -} from '../../../lib/snyk-test/common'; +import { getSeveritiesColour } from '../../../lib/snyk-test/common'; import { IacFileInDirectory } from '../../../lib/types'; import upperFirst = require('lodash.upperfirst'); const debug = Debug('iac-output'); @@ -35,9 +32,7 @@ function formatIacIssue( const description = extractOverview(issue.description).trim(); const descriptionLine = `\n ${description}\n`; - const severityColor = severitiesColourMapping[issue.severity] - ? severitiesColourMapping[issue.severity] - : defaultSeverityColor; + const severityColor = getSeveritiesColour(issue.severity); return ( severityColor.colorFunc( diff --git a/src/lib/snyk-test/common.ts b/src/lib/snyk-test/common.ts index b8bb757871..aaee849c2b 100644 --- a/src/lib/snyk-test/common.ts +++ b/src/lib/snyk-test/common.ts @@ -101,6 +101,14 @@ export const defaultSeverityColor = { }, }; +export function getSeveritiesColour(severity: string) { + return severitiesColourMapping[severity] || defaultSeverityColor; +} + +export function getLegacySeveritiesColour(severity: string) { + return legacySeveritiesColourMapping[severity] || defaultSeverityColor; +} + export enum FAIL_ON { all = 'all', upgradable = 'upgradable',