From 2139190cc6a1ae9d038864f92c4065a622b4b7e7 Mon Sep 17 00:00:00 2001 From: joshua-ostrom Date: Tue, 16 May 2023 15:57:21 -0400 Subject: [PATCH 1/4] Reporting compress option and sarif filter update --- lib/salus/plugin_manager.rb | 4 +-- lib/salus/report.rb | 16 +++++++-- spec/fixtures/sarifs/diff/git_diff_yarn.txt | 36 --------------------- 3 files changed, 15 insertions(+), 41 deletions(-) delete mode 100644 spec/fixtures/sarifs/diff/git_diff_yarn.txt diff --git a/lib/salus/plugin_manager.rb b/lib/salus/plugin_manager.rb index c26fff0d..a56b80d5 100644 --- a/lib/salus/plugin_manager.rb +++ b/lib/salus/plugin_manager.rb @@ -18,9 +18,9 @@ def register_listener(listener) @@listners << listener end - def apply_filter(filter_family, filter_method, data) + def apply_filter(filter_family, filter_method, *data) @@filters[filter_family]&.each do |f| - data = f.__send__(filter_method, data) if f.respond_to?(filter_method) + data = f.__send__(filter_method, *data) if f.respond_to?(filter_method) end data end diff --git a/lib/salus/report.rb b/lib/salus/report.rb index ad277ecd..b618c91a 100644 --- a/lib/salus/report.rb +++ b/lib/salus/report.rb @@ -2,6 +2,7 @@ require 'deepsort' require 'salus/formatting' require 'salus/bugsnag' +require 'zlib' # Adding aliases to prevent deep_sort from failing when comparing symbols and strings class Symbol @@ -63,8 +64,8 @@ def apply_report_hash_filters(report_hash) Salus::PluginManager.apply_filter(:salus_report, :filter_report_hash, report_hash) end - def apply_report_sarif_filters(sarif_json) - Salus::PluginManager.apply_filter(:salus_report, :filter_report_sarif, sarif_json) + def apply_report_sarif_filters(sarif_json, config) + Salus::PluginManager.apply_filter(:salus_report, :filter_report_sarif, sarif_json, config) end # Syntatical sugar register salus_report filters @@ -197,6 +198,7 @@ def to_json def to_sarif(config = {}) sarif_json = Sarif::SarifReport.new(@scan_reports, config, @repo_path, @config).to_sarif begin + # This is dangerous in salus as rule mappings sorted_sarif = JSON.parse(sarif_json).deep_sort rescue StandardError => e bugsnag_notify(e.inspect + "\n" + e.message + "\nResult String: " + to_h.to_s) @@ -205,7 +207,7 @@ def to_sarif(config = {}) # We will validate to ensure the applied filter # doesn't produce any invalid SARIF sarif_json = JSON.pretty_generate(sorted_sarif) - Sarif::SarifReport.validate_sarif(apply_report_sarif_filters(sarif_json)) + Sarif::SarifReport.validate_sarif(apply_report_sarif_filters(sarif_json, config)) rescue StandardError => e bugsnag_notify(e.class.to_s + " " + e.message + "\nBuild Info:" + @builds.to_s) end @@ -300,6 +302,7 @@ def publish_report(directive) else raise ExportReportError, "unknown report format #{directive['format']}" end + if Salus::Config::REMOTE_URI_SCHEME_REGEX.match?(URI(uri).scheme) Salus::ReportRequest.send_report(directive, report_body(directive), uri) else @@ -395,12 +398,19 @@ def write_report_to_file(report_file_path, report_string) "Cannot write file #{report_file_path} - #{e.class}: #{e.message}" end + def compress(data) + Base64.strict_encode64(Zlib::Deflate.deflate(data)) + end + def report_body_hash(config, data) return data unless config&.key?('post') && config['post'].present? body_hash = config['post']['additional_params'] || {} return body_hash unless config['post']['salus_report_param_name'] + compress_sarif = config.dig('post', 'salus_report_options', 'gzip-base64') + data = compress(data) if compress_sarif + body_hash[config['post']['salus_report_param_name']] = data body_hash end diff --git a/spec/fixtures/sarifs/diff/git_diff_yarn.txt b/spec/fixtures/sarifs/diff/git_diff_yarn.txt deleted file mode 100644 index 10815378..00000000 --- a/spec/fixtures/sarifs/diff/git_diff_yarn.txt +++ /dev/null @@ -1,36 +0,0 @@ -diff --git a/yarn.lock b/yarn.lock -index 06e7d3ba9ef..e3f8fbb5889 100644 ---- a/yarn.lock -+++ b/yarn.lock -@@ -10599,10 +10599,10 @@ base64-arraybuffer@^0.2.0: - resolved "https://registry-npm.com/base64-arraybuffer/-/base64-arraybuffer-0.2.0.tgz#4b944fac0191aa5907afe2d8c999ccc57ce80f45" - integrity sha512-7emyCsu1/xiBXgQZrscw/8KPRT44I4Yq9Pe6EGs3aPRTsWuggML1/1DTuZUuIaJPIm1FTDUVXl4x/yW8s0kQDQ== - --jspdf@2.5.1: -- version "2.5.1" -- resolved "https://registry.yarnpkg.com/jspdf/-/jspdf-2.5.1.tgz#00c85250abf5447a05f3b32ab9935ab4a56592cc" -- integrity sha512-hXObxz7ZqoyhxET78+XR34Xu2qFGrJJ2I2bE5w4SM8eFaFEkW2xcGRVUss360fYelwRSid/jT078kbNvmoW0QA== -+jspdf@2.3.1: -+ version "2.3.1" -+ resolved "https://registry-npm.com/jspdf/-/jspdf-2.3.1.tgz#313d117234b546469694a1fd81a1e02411647576" -+ integrity sha512-1vp0USP1mQi1h7NKpwxjFgQkJ5ncZvtH858aLpycUc/M+r/RpWJT8PixAU7Cw/3fPd4fpC8eB/Bj42LnsR21YQ== - dependencies: -- "@babel/runtime" "^7.14.0" - atob "^2.1.2" - btoa "^1.2.1" - fflate "^0.4.8" -@@ -31897,12 +31889,12 @@ text-encoding@0.7.0: - resolved "https://registry-npm.com/text-encoding/-/text-encoding-0.7.0.tgz#f895e836e45990624086601798ea98e8f36ee643" - integrity sha512-oJQ3f1hrOnbRLOcwKz0Liq2IcrvDeZRHXhd9RgLrsT+DjWY/nty1Hi7v3dtkaEYbPYe0mUoOfzRrMwfXXwgPUA== - --text-segmentation@^1.0.2, text-segmentation@^1.0.3: -- version "1.0.3" -- resolved "https://registry.yarnpkg.com/text-segmentation/-/text-segmentation-1.0.3.tgz#52a388159efffe746b24a63ba311b6ac9f2d7943" -- integrity sha512-iOiPUo/BGnZ6+54OsWxZidGCsdU8YbE4PSpdPinp7DeMtUJNJBoJ/ouUSTJjHkh1KntHaltHl/gDs2FC4i5+Nw== -+text-segmentation@^1.0.2: -+ version "1.0.2" -+ resolved "https://registry-npm.com/text-segmentation/-/text-segmentation-1.0.2.tgz#1f828fa14aa101c114ded1bda35ba7dcc17c9858" -+ integrity sha512-uTqvLxdBrVnx/CFQOtnf8tfzSXFm+1Qxau7Xi54j4OPTZokuDOX8qncQzrg2G8ZicAMOM8TgzFAYTb+AqNO4Cw== - dependencies: -- utrie "^1.0.2" -+ utrie "^1.0.1" From 9f53e8d3de0d2efc358bbdd495c02fa8a4f40ec5 Mon Sep 17 00:00:00 2001 From: joshua-ostrom Date: Wed, 17 May 2023 09:23:47 -0400 Subject: [PATCH 2/4] Rolling in fixes --- lib/salus/report.rb | 5 +++-- lib/salus/scanners/brakeman.rb | 3 ++- lib/sarif/base_sarif.rb | 21 +++++++++++++++++---- 3 files changed, 22 insertions(+), 7 deletions(-) diff --git a/lib/salus/report.rb b/lib/salus/report.rb index b618c91a..41d4eca1 100644 --- a/lib/salus/report.rb +++ b/lib/salus/report.rb @@ -198,7 +198,8 @@ def to_json def to_sarif(config = {}) sarif_json = Sarif::SarifReport.new(@scan_reports, config, @repo_path, @config).to_sarif begin - # This is dangerous in salus as rule mappings + # This is dangerous in salus as rule mappings use the ruleIndex + # which can change when a deep sort is executed sorted_sarif = JSON.parse(sarif_json).deep_sort rescue StandardError => e bugsnag_notify(e.inspect + "\n" + e.message + "\nResult String: " + to_h.to_s) @@ -399,7 +400,7 @@ def write_report_to_file(report_file_path, report_string) end def compress(data) - Base64.strict_encode64(Zlib::Deflate.deflate(data)) + Base64.strict_encode64(Zlib::Deflate.deflate(data)) end def report_body_hash(config, data) diff --git a/lib/salus/scanners/brakeman.rb b/lib/salus/scanners/brakeman.rb index cacca3a9..fffa1920 100644 --- a/lib/salus/scanners/brakeman.rb +++ b/lib/salus/scanners/brakeman.rb @@ -113,7 +113,8 @@ def merged_ignore_file_contents def ignore_list return [] unless user_supplied_ignore? - + # ADDED THIS LINE UNTIL PUBLIC SALUS HAS IT + return [] unless File.exist?(@config['ignore']) data = JSON.parse(File.read(@config['ignore'])) return [] unless data.key?('ignored_warnings') diff --git a/lib/sarif/base_sarif.rb b/lib/sarif/base_sarif.rb index 0fb35d2a..9e61736d 100644 --- a/lib/sarif/base_sarif.rb +++ b/lib/sarif/base_sarif.rb @@ -1,6 +1,7 @@ require 'json' require 'set' require 'sarif/shared_objects' +require 'deepsort' module Sarif class BaseSarif @@ -83,7 +84,7 @@ def uri_info def build_result(parsed_issue) result = { "ruleId": parsed_issue[:id], - "ruleIndex": @mapped_rules[parsed_issue[:id]], + "ruleIndex": @mapped_rules[parsed_issue[:id]], # this is wrong "level": sarif_level(parsed_issue[:level]), "message": { "text": parsed_issue[:details] @@ -115,6 +116,7 @@ def build_result(parsed_issue) def build_rule(parsed_issue) # only include one entry per rule id if !@mapped_rules.include?(parsed_issue[:id]) + # puts "mapped rules #{@mapped_rules.keys} do not include #{parsed_issue[:id]}" rule = { "id": parsed_issue[:id], "name": parsed_issue[:name], @@ -128,6 +130,7 @@ def build_rule(parsed_issue) "markdown": "[More info](#{parsed_issue[:help_url]})." } } + # puts "Setting @mapped_rules[#{parsed_issue[:id]}] to @rule_index (#{@rule_index}) vs #{@mapped_rules.size}" @mapped_rules[parsed_issue[:id]] = @rule_index @rule_index += 1 rule[:fullDescription][:text] = "errors reported by scanner" if rule[:id] == SCANNER_ERROR @@ -152,6 +155,7 @@ def build_runs_object(supported) rule = build_rule(parsed_issue) rules << rule if rule + result = build_result(parsed_issue) # Add suppresion object for suppressed results @@ -168,13 +172,22 @@ def build_runs_object(supported) # Salus::ScanReport invocation = build_invocations(@scan_report, supported) - { - "tool" => build_tool(rules: rules), + runs_object = { + "tool" => build_tool(rules: rules.deep_sort), "conversion" => build_conversion, "results" => results, "invocations" => [invocation], "originalUriBaseIds" => uri_info } + remap_rule_ids(runs_object) + end + + def remap_rule_ids(run) + rules = run['tool'][:driver]['rules'] + run['results'].each do |r| + r['ruleIndex'] = rules.index { |rule| rule[:id] == r[:ruleId] } + end + run end # Returns the conversion object for the SARIF report @@ -311,4 +324,4 @@ def self.snippet_possibly_in_diff?(snippet, scanner, lines_added) adapter_cls.snippet_possibly_in_git_diff?(snippet, lines_added) end end -end +end \ No newline at end of file From 4ddcc7ac01a23338be5330274fdec7d3f53093a5 Mon Sep 17 00:00:00 2001 From: joshua-ostrom Date: Wed, 17 May 2023 09:28:08 -0400 Subject: [PATCH 3/4] Cleanup --- lib/salus/scanners/brakeman.rb | 2 +- lib/sarif/base_sarif.rb | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/salus/scanners/brakeman.rb b/lib/salus/scanners/brakeman.rb index fffa1920..b4b8760e 100644 --- a/lib/salus/scanners/brakeman.rb +++ b/lib/salus/scanners/brakeman.rb @@ -113,7 +113,7 @@ def merged_ignore_file_contents def ignore_list return [] unless user_supplied_ignore? - # ADDED THIS LINE UNTIL PUBLIC SALUS HAS IT + return [] unless File.exist?(@config['ignore']) data = JSON.parse(File.read(@config['ignore'])) return [] unless data.key?('ignored_warnings') diff --git a/lib/sarif/base_sarif.rb b/lib/sarif/base_sarif.rb index 9e61736d..3d9bd476 100644 --- a/lib/sarif/base_sarif.rb +++ b/lib/sarif/base_sarif.rb @@ -84,7 +84,7 @@ def uri_info def build_result(parsed_issue) result = { "ruleId": parsed_issue[:id], - "ruleIndex": @mapped_rules[parsed_issue[:id]], # this is wrong + "ruleIndex": @mapped_rules[parsed_issue[:id]], "level": sarif_level(parsed_issue[:level]), "message": { "text": parsed_issue[:details] @@ -116,7 +116,6 @@ def build_result(parsed_issue) def build_rule(parsed_issue) # only include one entry per rule id if !@mapped_rules.include?(parsed_issue[:id]) - # puts "mapped rules #{@mapped_rules.keys} do not include #{parsed_issue[:id]}" rule = { "id": parsed_issue[:id], "name": parsed_issue[:name], @@ -130,7 +129,6 @@ def build_rule(parsed_issue) "markdown": "[More info](#{parsed_issue[:help_url]})." } } - # puts "Setting @mapped_rules[#{parsed_issue[:id]}] to @rule_index (#{@rule_index}) vs #{@mapped_rules.size}" @mapped_rules[parsed_issue[:id]] = @rule_index @rule_index += 1 rule[:fullDescription][:text] = "errors reported by scanner" if rule[:id] == SCANNER_ERROR @@ -155,7 +153,6 @@ def build_runs_object(supported) rule = build_rule(parsed_issue) rules << rule if rule - result = build_result(parsed_issue) # Add suppresion object for suppressed results @@ -173,12 +170,15 @@ def build_runs_object(supported) # Salus::ScanReport invocation = build_invocations(@scan_report, supported) runs_object = { - "tool" => build_tool(rules: rules.deep_sort), + "tool" => build_tool(rules: rules.deep_sort), # we deep sort here as + # our SARIF needs to be deep sorted for easier comparisions "conversion" => build_conversion, "results" => results, "invocations" => [invocation], "originalUriBaseIds" => uri_info } + # Ensure our ruleIndex values are correct after the + # prior deep sorting remap_rule_ids(runs_object) end From a9bce1686597b3d0cfa00fe343ec6ec4beb4994b Mon Sep 17 00:00:00 2001 From: joshua-ostrom Date: Thu, 18 May 2023 14:38:11 -0400 Subject: [PATCH 4/4] Spec fixes, rubocop --- lib/salus/plugin_manager.rb | 5 +++-- lib/salus/report.rb | 5 +++-- lib/salus/scanners/brakeman.rb | 1 + lib/sarif/base_sarif.rb | 4 ++-- .../success_with_exceptions/salus-sarif.yaml | 12 +++++++++++- spec/fixtures/sorted_results/sorted_sarif.json | 4 ++-- spec/lib/sarif/brakeman_sarif_spec.rb | 2 +- spec/lib/sarif/osv/maven_osv_sarif_spec.rb | 2 +- spec/lib/sarif/pattern_search_sarif_spec.rb | 2 +- spec/lib/sarif/semgrep_sarif_spec.rb | 2 +- spec/lib/sarif/trufflehog_sarif_spec.rb | 6 +++--- 11 files changed, 29 insertions(+), 16 deletions(-) diff --git a/lib/salus/plugin_manager.rb b/lib/salus/plugin_manager.rb index a56b80d5..466a9528 100644 --- a/lib/salus/plugin_manager.rb +++ b/lib/salus/plugin_manager.rb @@ -19,10 +19,11 @@ def register_listener(listener) end def apply_filter(filter_family, filter_method, *data) + result = data&.first @@filters[filter_family]&.each do |f| - data = f.__send__(filter_method, *data) if f.respond_to?(filter_method) + result = f.__send__(filter_method, *data) if f.respond_to?(filter_method) end - data + result end def send_event(event_name, *data) diff --git a/lib/salus/report.rb b/lib/salus/report.rb index 41d4eca1..77512f22 100644 --- a/lib/salus/report.rb +++ b/lib/salus/report.rb @@ -64,7 +64,7 @@ def apply_report_hash_filters(report_hash) Salus::PluginManager.apply_filter(:salus_report, :filter_report_hash, report_hash) end - def apply_report_sarif_filters(sarif_json, config) + def apply_report_sarif_filters(sarif_json, config = nil) Salus::PluginManager.apply_filter(:salus_report, :filter_report_sarif, sarif_json, config) end @@ -210,6 +210,7 @@ def to_sarif(config = {}) sarif_json = JSON.pretty_generate(sorted_sarif) Sarif::SarifReport.validate_sarif(apply_report_sarif_filters(sarif_json, config)) rescue StandardError => e + puts "Failure in validing SARIF" bugsnag_notify(e.class.to_s + " " + e.message + "\nBuild Info:" + @builds.to_s) end @@ -410,7 +411,7 @@ def report_body_hash(config, data) return body_hash unless config['post']['salus_report_param_name'] compress_sarif = config.dig('post', 'salus_report_options', 'gzip-base64') - data = compress(data) if compress_sarif + data = compress(JSON.pretty_generate(data)) if ["true", true].include?(compress_sarif) body_hash[config['post']['salus_report_param_name']] = data body_hash diff --git a/lib/salus/scanners/brakeman.rb b/lib/salus/scanners/brakeman.rb index b4b8760e..95383ca7 100644 --- a/lib/salus/scanners/brakeman.rb +++ b/lib/salus/scanners/brakeman.rb @@ -115,6 +115,7 @@ def ignore_list return [] unless user_supplied_ignore? return [] unless File.exist?(@config['ignore']) + data = JSON.parse(File.read(@config['ignore'])) return [] unless data.key?('ignored_warnings') diff --git a/lib/sarif/base_sarif.rb b/lib/sarif/base_sarif.rb index 3d9bd476..c6ca7609 100644 --- a/lib/sarif/base_sarif.rb +++ b/lib/sarif/base_sarif.rb @@ -185,7 +185,7 @@ def build_runs_object(supported) def remap_rule_ids(run) rules = run['tool'][:driver]['rules'] run['results'].each do |r| - r['ruleIndex'] = rules.index { |rule| rule[:id] == r[:ruleId] } + r[:ruleIndex] = rules.index { |rule| rule[:id] == r[:ruleId] } end run end @@ -324,4 +324,4 @@ def self.snippet_possibly_in_diff?(snippet, scanner, lines_added) adapter_cls.snippet_possibly_in_git_diff?(snippet, lines_added) end end -end \ No newline at end of file +end diff --git a/spec/fixtures/npm_audit/success_with_exceptions/salus-sarif.yaml b/spec/fixtures/npm_audit/success_with_exceptions/salus-sarif.yaml index 2a60ddca..a3cbcc5b 100644 --- a/spec/fixtures/npm_audit/success_with_exceptions/salus-sarif.yaml +++ b/spec/fixtures/npm_audit/success_with_exceptions/salus-sarif.yaml @@ -20,4 +20,14 @@ scanner_configs: advisory_id: "1091018", changed_by: "joshua.ostrom", notes: "See https://www.npmjs.com/advisories/48. We're not vulnerable to this because this is a regex dos and we have nothing that puts user input into it. The impact is also minimal.", - } \ No newline at end of file + } + - { + advisory_id: "1091686", + changed_by: "joshua.ostrom", + notes: "WAGMI", + } + - { + advisory_id: "1091710", + changed_by: "joshua.ostrom", + notes: "BTC $26.5K", + } diff --git a/spec/fixtures/sorted_results/sorted_sarif.json b/spec/fixtures/sorted_results/sorted_sarif.json index e876ce00..5c01847b 100644 --- a/spec/fixtures/sorted_results/sorted_sarif.json +++ b/spec/fixtures/sorted_results/sorted_sarif.json @@ -31,7 +31,7 @@ "text": "Useless equality test.. Pattern 1 == $X is required but not found." }, "ruleId": "Required Pattern Not Found", - "ruleIndex": 1 + "ruleIndex": 0 }, { "level": "error", @@ -53,7 +53,7 @@ "text": "Syntax error at line /home/spec/fixtures/semgrep/invalid/unparsable_py.py:3:\n `print(\"foo\"` was unexpected" }, "ruleId": "SAL002", - "ruleIndex": 0 + "ruleIndex": 1 } ], "tool": { diff --git a/spec/lib/sarif/brakeman_sarif_spec.rb b/spec/lib/sarif/brakeman_sarif_spec.rb index a1b7a10a..d505c140 100644 --- a/spec/lib/sarif/brakeman_sarif_spec.rb +++ b/spec/lib/sarif/brakeman_sarif_spec.rb @@ -186,7 +186,7 @@ # Check result info expect(result['ruleId']).to eq('13') - expect(result['ruleIndex']).to eq(0) + expect(result['ruleIndex']).to eq(2) expect(result['level']).to eq('error') expect(result['locations'][0]['physicalLocation']['region']['startLine']).to eq(3) snippet = result['locations'][0]['physicalLocation']['region']['snippet']['text'].to_s diff --git a/spec/lib/sarif/osv/maven_osv_sarif_spec.rb b/spec/lib/sarif/osv/maven_osv_sarif_spec.rb index 9a28b8f4..6f00fc25 100644 --- a/spec/lib/sarif/osv/maven_osv_sarif_spec.rb +++ b/spec/lib/sarif/osv/maven_osv_sarif_spec.rb @@ -91,7 +91,7 @@ def stub_req_with_valid_response "severity" => "HIGH" }, "ruleId" => "CVE-2018-15756", - "ruleIndex" => 5 + "ruleIndex" => 0 } ) diff --git a/spec/lib/sarif/pattern_search_sarif_spec.rb b/spec/lib/sarif/pattern_search_sarif_spec.rb index 22ff3ee0..176569df 100644 --- a/spec/lib/sarif/pattern_search_sarif_spec.rb +++ b/spec/lib/sarif/pattern_search_sarif_spec.rb @@ -44,7 +44,7 @@ expect(results).to include( { "ruleId": "Forbidden Pattern Found", - "ruleIndex": 0, + "ruleIndex": 1, "level": "error", "message": { "text": "not important string. Pattern Nerv is forbidden." diff --git a/spec/lib/sarif/semgrep_sarif_spec.rb b/spec/lib/sarif/semgrep_sarif_spec.rb index d2939a00..2a6828bb 100644 --- a/spec/lib/sarif/semgrep_sarif_spec.rb +++ b/spec/lib/sarif/semgrep_sarif_spec.rb @@ -146,7 +146,7 @@ expect(result).to include( { "ruleId" => "Required Pattern Not Found", - "ruleIndex" => 1, + "ruleIndex" => 0, "level" => "error", "message" => { "text" => "Useless equality test.. Pattern 1 == $X is required but not found." diff --git a/spec/lib/sarif/trufflehog_sarif_spec.rb b/spec/lib/sarif/trufflehog_sarif_spec.rb index b757bf84..34110920 100644 --- a/spec/lib/sarif/trufflehog_sarif_spec.rb +++ b/spec/lib/sarif/trufflehog_sarif_spec.rb @@ -27,7 +27,7 @@ } }], "message" => { "text" => "Leaked credential detected" }, "properties" => { "severity" => "high" }, - "ruleId" => "FlatIO-PLAIN", "ruleIndex" => 1 } + "ruleId" => "FlatIO-PLAIN", "ruleIndex" => 0 } expected_vul1 = { "level" => "error", "locations" => [{ "physicalLocation" => { "artifactLocation" => { "uri" => "url.txt", @@ -40,7 +40,7 @@ } }], "message" => { "text" => "Leaked credential detected" }, "properties" => { "severity" => "high" }, - "ruleId" => "JDBC-PLAIN", "ruleIndex" => 0 } + "ruleId" => "JDBC-PLAIN", "ruleIndex" => 1 } expected_vul2 = { "level" => "error", "locations" => [{ "physicalLocation" => { "artifactLocation" => { "uri" => "url.txt", @@ -53,7 +53,7 @@ } }], "message" => { "text" => "Leaked credential detected" }, "properties" => { "severity" => "high" }, - "ruleId" => "JDBC-PLAIN", "ruleIndex" => 0 } + "ruleId" => "JDBC-PLAIN", "ruleIndex" => 1 } expect(result.size).to eq(3) [expected_vul0, expected_vul1, expected_vul2].each { |v| expect(result).to include(v) } end