owasp-pipeline 0.8.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CHANGES +23 -0
- data/FEATURES +19 -0
- data/README.md +101 -0
- data/bin/pipeline +67 -0
- data/lib/pipeline.rb +301 -0
- data/lib/pipeline/event.rb +14 -0
- data/lib/pipeline/filters.rb +41 -0
- data/lib/pipeline/filters/base_filter.rb +19 -0
- data/lib/pipeline/filters/jira_one_time_filter.rb +57 -0
- data/lib/pipeline/filters/remove_all_filter.rb +16 -0
- data/lib/pipeline/finding.rb +52 -0
- data/lib/pipeline/mounters.rb +55 -0
- data/lib/pipeline/mounters/base_mounter.rb +31 -0
- data/lib/pipeline/mounters/docker_mounter.rb +44 -0
- data/lib/pipeline/mounters/filesystem_mounter.rb +25 -0
- data/lib/pipeline/mounters/git_mounter.rb +52 -0
- data/lib/pipeline/mounters/iso_mounter.rb +42 -0
- data/lib/pipeline/mounters/url_mounter.rb +28 -0
- data/lib/pipeline/options.rb +240 -0
- data/lib/pipeline/reporters.rb +50 -0
- data/lib/pipeline/reporters/base_reporter.rb +21 -0
- data/lib/pipeline/reporters/csv_reporter.rb +19 -0
- data/lib/pipeline/reporters/jira_reporter.rb +61 -0
- data/lib/pipeline/reporters/json_reporter.rb +20 -0
- data/lib/pipeline/reporters/text_reporter.rb +19 -0
- data/lib/pipeline/scanner.rb +28 -0
- data/lib/pipeline/tasks.rb +124 -0
- data/lib/pipeline/tasks/av.rb +43 -0
- data/lib/pipeline/tasks/base_task.rb +64 -0
- data/lib/pipeline/tasks/brakeman.rb +60 -0
- data/lib/pipeline/tasks/bundle-audit.rb +93 -0
- data/lib/pipeline/tasks/checkmarx.rb +62 -0
- data/lib/pipeline/tasks/eslint.rb +71 -0
- data/lib/pipeline/tasks/fim.rb +61 -0
- data/lib/pipeline/tasks/nsp.rb +59 -0
- data/lib/pipeline/tasks/owasp-dep-check.rb +120 -0
- data/lib/pipeline/tasks/patterns.json +394 -0
- data/lib/pipeline/tasks/retirejs.rb +106 -0
- data/lib/pipeline/tasks/scanjs-eslintrc +106 -0
- data/lib/pipeline/tasks/scanjs.rb +32 -0
- data/lib/pipeline/tasks/sfl.rb +67 -0
- data/lib/pipeline/tasks/test.rb +47 -0
- data/lib/pipeline/tasks/zap.rb +84 -0
- data/lib/pipeline/tracker.rb +47 -0
- data/lib/pipeline/util.rb +39 -0
- data/lib/pipeline/version.rb +3 -0
- data/lib/zapjson.json +0 -0
- metadata +205 -0
@@ -0,0 +1,106 @@
|
|
1
|
+
require 'pipeline/tasks/base_task'
|
2
|
+
require 'json'
|
3
|
+
require 'pipeline/util'
|
4
|
+
require 'jsonpath'
|
5
|
+
require 'pathname'
|
6
|
+
|
7
|
+
class Pipeline::RetireJS < Pipeline::BaseTask
|
8
|
+
|
9
|
+
Pipeline::Tasks.add self
|
10
|
+
include Pipeline::Util
|
11
|
+
|
12
|
+
def initialize(trigger, tracker)
|
13
|
+
super(trigger, tracker)
|
14
|
+
@name = "RetireJS"
|
15
|
+
@description = "Dependency analysis for JavaScript"
|
16
|
+
@stage = :code
|
17
|
+
@labels << "code" << "javascript"
|
18
|
+
end
|
19
|
+
|
20
|
+
def run
|
21
|
+
rootpath = @trigger.path
|
22
|
+
Pipeline.debug "Retire rootpath: #{rootpath}"
|
23
|
+
Dir.chdir("#{rootpath}") do
|
24
|
+
if @tracker.options.has_key?(:npm_registry)
|
25
|
+
registry = "--registry #{@tracker.options[:npm_registry]}"
|
26
|
+
else
|
27
|
+
registry = nil
|
28
|
+
end
|
29
|
+
@result = `npm install --ignore-scripts #{registry}` # Need this even though it is slow to get full dependency analysis.
|
30
|
+
end
|
31
|
+
@result = `retire -c --outputformat json --path #{rootpath} 2>&1`
|
32
|
+
end
|
33
|
+
|
34
|
+
def analyze
|
35
|
+
begin
|
36
|
+
vulnerabilities = parse_retire_json(JSON.parse(@result))
|
37
|
+
|
38
|
+
vulnerabilities.each do |vuln|
|
39
|
+
report "Package #{vuln[:package]} has known security issues", vuln[:detail], vuln[:source], vuln[:severity], fingerprint("#{vuln[:package]}#{vuln[:source]}#{vuln[:severity]}")
|
40
|
+
end
|
41
|
+
rescue Exception => e
|
42
|
+
Pipeline.warn e.message
|
43
|
+
Pipeline.warn e.backtrace
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def parse_retire_json result
|
48
|
+
Pipeline.debug "Retire JSON Raw Result: #{result}"
|
49
|
+
vulnerabilities = []
|
50
|
+
# This is very ugly, but so is the json retire.js spits out
|
51
|
+
# Loop through each component/version combo and pull all results for it
|
52
|
+
JsonPath.on(result, '$..component').uniq.each do |comp|
|
53
|
+
JsonPath.on(result, "$..results[?(@.component == \'#{comp}\')].version").uniq.each do |version|
|
54
|
+
vuln_hash = {}
|
55
|
+
vuln_hash[:package] = "#{comp}-#{version}"
|
56
|
+
|
57
|
+
version_results = JsonPath.on(result, "$..results[?(@.component == \'#{comp}\')]").select { |r| r['version'] == version }.uniq
|
58
|
+
|
59
|
+
# If we see the parent-->component relationship, dig through the dependency tree to try and make a dep map
|
60
|
+
deps = []
|
61
|
+
obj = version_results[0]
|
62
|
+
while !obj['parent'].nil?
|
63
|
+
deps << obj['parent']['component']
|
64
|
+
obj = obj['parent']
|
65
|
+
end
|
66
|
+
if deps.length > 0
|
67
|
+
vuln_hash[:source] = { :scanner => @name, :file => "#{deps.reverse.join('->')}->#{comp}-#{version}", :line => nil, :code => nil }
|
68
|
+
end
|
69
|
+
|
70
|
+
vuln_hash[:severity] = 'unknown'
|
71
|
+
# pull detail/severity
|
72
|
+
version_results.each do |version_result|
|
73
|
+
JsonPath.on(version_result, '$..vulnerabilities').uniq.each do |vuln|
|
74
|
+
vuln_hash[:severity] = severity(vuln[0]['severity'])
|
75
|
+
vuln_hash[:detail] = vuln[0]['info'].join('\n')
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
vulnerabilities << vuln_hash
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
# Loop through the separately reported 'file' findings so we can tag the source (no dep map here)
|
84
|
+
result.select { |r| !r['file'].nil? }.each do |file_result|
|
85
|
+
JsonPath.on(file_result, '$..component').uniq.each do |comp|
|
86
|
+
JsonPath.on(file_result, "$..results[?(@.component == \'#{comp}\')].version").uniq.each do |version|
|
87
|
+
source_path = Pathname.new(file_result['file']).relative_path_from Pathname.new(@trigger.path)
|
88
|
+
vulnerabilities.select { |v| v[:package] == "#{comp}-#{version}" }.first[:source] = { :scanner => @name, :file => source_path.to_s, :line => nil, :code => nil }
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
return vulnerabilities
|
93
|
+
end
|
94
|
+
|
95
|
+
def supported?
|
96
|
+
supported=runsystem(true, "retire", "--help")
|
97
|
+
if supported =~ /command not found/
|
98
|
+
Pipeline.notify "Install RetireJS"
|
99
|
+
return false
|
100
|
+
else
|
101
|
+
return true
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
106
|
+
|
@@ -0,0 +1,106 @@
|
|
1
|
+
{ "ecmaFeatures" : {
|
2
|
+
"modules" : true
|
3
|
+
},
|
4
|
+
"env" : {
|
5
|
+
"browser" : true,
|
6
|
+
"es6" : true /** all es6 features except modules */
|
7
|
+
},
|
8
|
+
"plugins" : [
|
9
|
+
"scanjs-rules",
|
10
|
+
"no-unsafe-innerhtml"
|
11
|
+
],
|
12
|
+
"rules" : {
|
13
|
+
/** useful rules from eslint **/
|
14
|
+
|
15
|
+
/** no-unsafe-innerhtml rule **/
|
16
|
+
"no-unsafe-innerhtml/no-unsafe-innerhtml" : 2,
|
17
|
+
|
18
|
+
/** ScanJS rules **/
|
19
|
+
"scanjs-rules/assign_to_hostname" : 1,
|
20
|
+
"scanjs-rules/assign_to_href" : 1,
|
21
|
+
"scanjs-rules/assign_to_location" : 1,
|
22
|
+
"scanjs-rules/assign_to_mozAudioChannel" : 1,
|
23
|
+
"scanjs-rules/assign_to_mozAudioChannelType" : 1,
|
24
|
+
"scanjs-rules/assign_to_onmessage" : 1,
|
25
|
+
"scanjs-rules/assign_to_pathname" : 1,
|
26
|
+
"scanjs-rules/assign_to_protocol" : 1,
|
27
|
+
"scanjs-rules/assign_to_search" : 1,
|
28
|
+
"scanjs-rules/assign_to_src" : 1,
|
29
|
+
"scanjs-rules/call_Function" : 1,
|
30
|
+
"scanjs-rules/call_addEventListener" : 1,
|
31
|
+
"scanjs-rules/call_addEventListener_cellbroadcastmsgchanged" : 1,
|
32
|
+
"scanjs-rules/call_addEventListener_deviceproximity" : 1,
|
33
|
+
"scanjs-rules/call_addEventListener_message" : 1,
|
34
|
+
"scanjs-rules/call_addEventListener_moznetworkdownload" : 1,
|
35
|
+
"scanjs-rules/call_addEventListener_moznetworkupload" : 1,
|
36
|
+
"scanjs-rules/call_connect" : 1,
|
37
|
+
"scanjs-rules/call_eval" : 1,
|
38
|
+
"scanjs-rules/call_execScript" : 1,
|
39
|
+
"scanjs-rules/call_generateCRMFRequest" : 1,
|
40
|
+
"scanjs-rules/call_getDeviceStorage_apps" : 1,
|
41
|
+
"scanjs-rules/call_getDeviceStorage_crashes" : 1,
|
42
|
+
"scanjs-rules/call_getDeviceStorage_music" : 1,
|
43
|
+
"scanjs-rules/call_getDeviceStorage_pictures" : 1,
|
44
|
+
"scanjs-rules/call_getDeviceStorage_sdcard" : 1,
|
45
|
+
"scanjs-rules/call_getDeviceStorage_videos" : 1,
|
46
|
+
"scanjs-rules/call_hide" : 1,
|
47
|
+
"scanjs-rules/call_mozSetMessageHandler" : 1,
|
48
|
+
"scanjs-rules/call_mozSetMessageHandler_activity" : 1,
|
49
|
+
"scanjs-rules/call_mozSetMessageHandler_wappush_received" : 1,
|
50
|
+
"scanjs-rules/call_open_attention" : 1,
|
51
|
+
"scanjs-rules/call_open_remote=true" : 1,
|
52
|
+
"scanjs-rules/call_parseFromString" : 1,
|
53
|
+
"scanjs-rules/call_setAttribute_mozapp" : 1,
|
54
|
+
"scanjs-rules/call_setAttribute_mozbrowser" : 1,
|
55
|
+
"scanjs-rules/call_setImmediate" : 1,
|
56
|
+
"scanjs-rules/call_setInterval" : 1,
|
57
|
+
"scanjs-rules/call_setMessageHandler_connect" : 1,
|
58
|
+
"scanjs-rules/call_setTimeout" : 1,
|
59
|
+
"scanjs-rules/call_write" : 1,
|
60
|
+
"scanjs-rules/call_writeln" : 1,
|
61
|
+
"scanjs-rules/identifier_indexedDB" : 1,
|
62
|
+
"scanjs-rules/identifier_localStorage" : 1,
|
63
|
+
"scanjs-rules/identifier_sessionStorage" : 1,
|
64
|
+
"scanjs-rules/new_Function" : 1,
|
65
|
+
"scanjs-rules/new_MozActivity" : 1,
|
66
|
+
"scanjs-rules/new_MozSpeakerManager" : 1,
|
67
|
+
"scanjs-rules/new_Notification" : 1,
|
68
|
+
"scanjs-rules/object_mozSystem" : 1,
|
69
|
+
"scanjs-rules/property_addIdleObserver" : 1,
|
70
|
+
"scanjs-rules/property_createContextualFragment" : 1,
|
71
|
+
"scanjs-rules/property_geolocation" : 1,
|
72
|
+
"scanjs-rules/property_getDataStores" : 1,
|
73
|
+
"scanjs-rules/property_getDeviceStorage" : 1,
|
74
|
+
"scanjs-rules/property_getUserMedia" : 1,
|
75
|
+
"scanjs-rules/property_indexedDB" : 1,
|
76
|
+
"scanjs-rules/property_lastKnownHomeNetwork" : 1,
|
77
|
+
"scanjs-rules/property_lastKnownNetwork" : 1,
|
78
|
+
"scanjs-rules/property_localStorage" : 1,
|
79
|
+
"scanjs-rules/property_mgmt" : 1,
|
80
|
+
"scanjs-rules/property_mozAlarms" : 1,
|
81
|
+
"scanjs-rules/property_mozBluetooth" : 1,
|
82
|
+
"scanjs-rules/property_mozCameras" : 1,
|
83
|
+
"scanjs-rules/property_mozCellBroadcast" : 1,
|
84
|
+
"scanjs-rules/property_mozContacts" : 1,
|
85
|
+
"scanjs-rules/property_mozDownloadManager" : 1,
|
86
|
+
"scanjs-rules/property_mozFMRadio" : 1,
|
87
|
+
"scanjs-rules/property_mozInputMethod" : 1,
|
88
|
+
"scanjs-rules/property_mozKeyboard" : 1,
|
89
|
+
"scanjs-rules/property_mozMobileConnection" : 1,
|
90
|
+
"scanjs-rules/property_mozMobileConnections" : 1,
|
91
|
+
"scanjs-rules/property_mozMobileMessage" : 1,
|
92
|
+
"scanjs-rules/property_mozNetworkStats" : 1,
|
93
|
+
"scanjs-rules/property_mozNfc" : 1,
|
94
|
+
"scanjs-rules/property_mozNotification" : 1,
|
95
|
+
"scanjs-rules/property_mozPermissionSettings" : 1,
|
96
|
+
"scanjs-rules/property_mozPhoneNumberService" : 1,
|
97
|
+
"scanjs-rules/property_mozPower" : 1,
|
98
|
+
"scanjs-rules/property_mozSettings" : 1,
|
99
|
+
"scanjs-rules/property_mozTCPSocket" : 1,
|
100
|
+
"scanjs-rules/property_mozTelephony" : 1,
|
101
|
+
"scanjs-rules/property_mozTime" : 1,
|
102
|
+
"scanjs-rules/property_mozVoicemail" : 1,
|
103
|
+
"scanjs-rules/property_mozWifiManager" : 1,
|
104
|
+
"scanjs-rules/property_sessionStorage" : 1
|
105
|
+
}
|
106
|
+
}
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'pipeline/tasks/base_task'
|
2
|
+
|
3
|
+
class Pipeline::ScanJS < Pipeline::BaseTask
|
4
|
+
|
5
|
+
# WIP
|
6
|
+
# Pipeline::Tasks.add self
|
7
|
+
|
8
|
+
def initialize(trigger, tracker)
|
9
|
+
super(trigger)
|
10
|
+
@name = "ScanJS"
|
11
|
+
@description = "Source analysis for JavaScript"
|
12
|
+
@stage = :code
|
13
|
+
@labels << "code" << "javascript"
|
14
|
+
end
|
15
|
+
|
16
|
+
def run
|
17
|
+
Pipeline.notify "#{@name}"
|
18
|
+
rootpath = @trigger.path
|
19
|
+
@result=`scanner.js -t "#{rootpath}"`
|
20
|
+
end
|
21
|
+
|
22
|
+
def analyze
|
23
|
+
puts @result
|
24
|
+
end
|
25
|
+
|
26
|
+
def supported?
|
27
|
+
# In future, verify tool is available.
|
28
|
+
return true
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'pipeline/tasks/base_task'
|
2
|
+
require 'json'
|
3
|
+
require 'pipeline/util'
|
4
|
+
require 'find'
|
5
|
+
|
6
|
+
class Pipeline::SFL < Pipeline::BaseTask
|
7
|
+
|
8
|
+
Pipeline::Tasks.add self
|
9
|
+
include Pipeline::Util
|
10
|
+
|
11
|
+
def initialize(trigger, tracker)
|
12
|
+
super(trigger,tracker)
|
13
|
+
@name = "SFL"
|
14
|
+
@description = "Sentive Files Lookup"
|
15
|
+
@stage = :code
|
16
|
+
@labels << "code"
|
17
|
+
# Pipeline.debug "initialized SFL"
|
18
|
+
@patterns = read_patterns_file!
|
19
|
+
end
|
20
|
+
|
21
|
+
def run
|
22
|
+
# Pipeline.notify "#{@name}"
|
23
|
+
@files = Find.find(@trigger.path)
|
24
|
+
Pipeline.debug "Found #{@files.count} files"
|
25
|
+
end
|
26
|
+
|
27
|
+
def analyze
|
28
|
+
begin
|
29
|
+
@files.each do |file|
|
30
|
+
@patterns.each do |pattern|
|
31
|
+
case pattern['part']
|
32
|
+
when 'filename'
|
33
|
+
if pattern_matched?(File.basename(file), pattern)
|
34
|
+
report pattern['caption'], pattern['description'], @name + ":" + file, 'unknown', 'TBD'
|
35
|
+
end
|
36
|
+
when 'extension'
|
37
|
+
if pattern_matched?(File.extname(file), pattern)
|
38
|
+
report pattern['caption'], pattern['description'], @name + ":" + file, 'unknown', 'TBD'
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
rescue Exception => e
|
44
|
+
Pipeline.warn e.message
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def supported?
|
49
|
+
true
|
50
|
+
end
|
51
|
+
|
52
|
+
def pattern_matched?(txt, pattrn)
|
53
|
+
case pattrn['type']
|
54
|
+
when 'match'
|
55
|
+
return txt == pattrn['pattern']
|
56
|
+
when 'regex'
|
57
|
+
regex = Regexp.new(pattrn['pattern'], Regexp::IGNORECASE)
|
58
|
+
return !regex.match(txt).nil?
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def read_patterns_file!
|
63
|
+
JSON.parse(File.read("#{File.dirname(__FILE__)}/patterns.json"))
|
64
|
+
rescue JSON::ParserError => e
|
65
|
+
Pipeline.warn "Cannot parse pattern file: #{e.message}"
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'pipeline/tasks/base_task'
|
2
|
+
require 'pipeline/util'
|
3
|
+
|
4
|
+
class Pipeline::Test < Pipeline::BaseTask
|
5
|
+
Pipeline::Tasks.add self
|
6
|
+
include Pipeline::Util
|
7
|
+
|
8
|
+
def initialize(trigger, tracker)
|
9
|
+
super(trigger, tracker)
|
10
|
+
@name = "Test"
|
11
|
+
@description = "Test"
|
12
|
+
@stage = :code
|
13
|
+
@labels << "code" << "ruby"
|
14
|
+
end
|
15
|
+
|
16
|
+
def run
|
17
|
+
# Pipeline.notify "#{@name}"
|
18
|
+
rootpath = @trigger.path
|
19
|
+
Pipeline.debug "Rootpath: #{rootpath}"
|
20
|
+
Dir.chdir("#{rootpath}") do
|
21
|
+
@result= runsystem(true, "grep", "-R", "secret")
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def analyze
|
26
|
+
begin
|
27
|
+
list = @result.split(/\n/)
|
28
|
+
list.each do |match|
|
29
|
+
report "Match", match, @name, :low, "fingerprint"
|
30
|
+
end
|
31
|
+
rescue Exception => e
|
32
|
+
Pipeline.warn e.message
|
33
|
+
Pipeline.notify "Error grepping ... "
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def supported?
|
38
|
+
supported=runsystem(true, "grep", "-h")
|
39
|
+
if supported =~ /usage/
|
40
|
+
Pipeline.notify "Install grep."
|
41
|
+
return false
|
42
|
+
else
|
43
|
+
return true
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
require 'pipeline/tasks/base_task'
|
2
|
+
require 'pipeline/util'
|
3
|
+
require 'json'
|
4
|
+
require 'curb'
|
5
|
+
|
6
|
+
class Pipeline::Zap < Pipeline::BaseTask
|
7
|
+
|
8
|
+
Pipeline::Tasks.add self
|
9
|
+
include Pipeline::Util
|
10
|
+
|
11
|
+
def initialize(trigger,tracker)
|
12
|
+
super(trigger,tracker)
|
13
|
+
@name = "ZAP"
|
14
|
+
@description = "App Scanning"
|
15
|
+
@stage = :live
|
16
|
+
@labels << "live"
|
17
|
+
end
|
18
|
+
|
19
|
+
def run
|
20
|
+
rootpath = @trigger.path
|
21
|
+
base = "#{@tracker.options[:zap_host]}:#{@tracker.options[:zap_port]}"
|
22
|
+
Pipeline.debug "Running ZAP on: #{rootpath} from #{base}"
|
23
|
+
|
24
|
+
# TODO: Add API Key
|
25
|
+
# TODO: Find out if we need to worry about "contexts" stepping on each other.
|
26
|
+
|
27
|
+
# Spider
|
28
|
+
Curl.get("#{base}/JSON/spider/action/scan/?#{rootpath}")
|
29
|
+
poll_until_100("#{base}/JSON/spider/view/status")
|
30
|
+
|
31
|
+
# Active Scan
|
32
|
+
Curl.get("#{base}/JSON/ascan/action/scan/?recurse=true&inScopeOnly=true&url=#{rootpath}")
|
33
|
+
poll_until_100("#{base}/JSON/ascan/view/status/")
|
34
|
+
|
35
|
+
# Result
|
36
|
+
@result = Curl.get("#{base}/JSON/core/view/alerts/").body_str
|
37
|
+
end
|
38
|
+
|
39
|
+
def poll_until_100(url)
|
40
|
+
count = 0
|
41
|
+
loop do
|
42
|
+
sleep 5
|
43
|
+
status = JSON.parse(Curl.get(url).body_str)
|
44
|
+
count = count + 1
|
45
|
+
Pipeline.notify "Count ... #{count}"
|
46
|
+
break if status["status"] == "100" or count > 100
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def analyze
|
51
|
+
begin
|
52
|
+
json = JSON.parse @result
|
53
|
+
alerts = json["alerts"]
|
54
|
+
count = 0
|
55
|
+
alerts.each do |alert|
|
56
|
+
count = count + 1
|
57
|
+
description = alert["description"]
|
58
|
+
detail = "Url: #{alert["url"]} Param: #{alert["param"]} \nReference: #{alert["reference"]}\n"+
|
59
|
+
"Solution: #{alert["solution"]}\nCWE: #{alert["cweid"]}\tWASCID: #{alert["wascid"]}"
|
60
|
+
source = @name + alert["url"]
|
61
|
+
sev = severity alert["risk"]
|
62
|
+
fingerprint = @name + alert["url"] + alert["alert"] + alert["param"]
|
63
|
+
report description, detail, source, sev, fingerprint
|
64
|
+
end
|
65
|
+
Pipeline.debug "ZAP Identified #{count} issues."
|
66
|
+
rescue Exception => e
|
67
|
+
Pipeline.warn e.message
|
68
|
+
Pipeline.notify "Problem running ZAP."
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def supported?
|
73
|
+
base = "#{@tracker.options[:zap_host]}:#{@tracker.options[:zap_port]}"
|
74
|
+
supported=JSON.parse(Curl.get("#{base}/JSON/core/view/version/").body_str)
|
75
|
+
if supported["version"] == "2.4.3"
|
76
|
+
return true
|
77
|
+
else
|
78
|
+
Pipeline.notify "Install ZAP from owasp.org and ensure that the configuration to connect is correct."
|
79
|
+
return false
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
|