owasp-pipeline 0.8.3 → 0.8.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/pipeline/mounters/filesystem_mounter.rb +2 -7
- data/lib/pipeline/options.rb +18 -0
- data/lib/pipeline/tasks/checkmarx.rb +4 -5
- data/lib/pipeline/tasks/dawnscanner.rb +56 -0
- data/lib/pipeline/tasks/findsecbugs.rb +81 -0
- data/lib/pipeline/tasks/pmd.rb +64 -0
- data/lib/pipeline/tasks/zap.rb +21 -8
- data/lib/pipeline/version.rb +1 -1
- metadata +75 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bf5efee842fff5ee62a05d074fe47d057bc0dd1d
|
4
|
+
data.tar.gz: 417d5379d1b73b82a0a20561d5d78d50e907c020
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5c44a4dc6c22acacac6b6d3a4b6197da7427ed3373341b28f2c4b1d01064b9d7d3357ae59c9a4020bf7fc2bb462d913db3f353038bbed328d556f427c7d68c12
|
7
|
+
data.tar.gz: 4a8f15ac36f2533638c0d8fc2d695168bc6bfa3bac7e3d41429b712d6e2b2618cd8b7c068f5b9d5140eaaaab9b9694e3e7100aad1a522e5fb75eefb3780a1206
|
@@ -2,7 +2,7 @@ require 'pipeline/mounters/base_mounter'
|
|
2
2
|
|
3
3
|
class Pipeline::FileSystemMounter < Pipeline::BaseMounter
|
4
4
|
Pipeline::Mounters.add self
|
5
|
-
|
5
|
+
|
6
6
|
def initialize trigger, options
|
7
7
|
super(trigger)
|
8
8
|
@options = options
|
@@ -15,11 +15,6 @@ class Pipeline::FileSystemMounter < Pipeline::BaseMounter
|
|
15
15
|
end
|
16
16
|
|
17
17
|
def supports? target
|
18
|
-
|
19
|
-
if last === "/" or last === "."
|
20
|
-
return true
|
21
|
-
else
|
22
|
-
return false
|
23
|
-
end
|
18
|
+
File.directory? target
|
24
19
|
end
|
25
20
|
end
|
data/lib/pipeline/options.rb
CHANGED
@@ -190,6 +190,24 @@ module Pipeline::Options
|
|
190
190
|
options[:checkmarx_project] = project
|
191
191
|
end
|
192
192
|
|
193
|
+
opts.separator ""
|
194
|
+
opts.separator "PMD options:"
|
195
|
+
|
196
|
+
opts.on "--pmd-path PATH", "The full path to the base PMD directory" do |dir|
|
197
|
+
options[:pmd_path] = dir
|
198
|
+
end
|
199
|
+
|
200
|
+
opts.on "--pmd-checks CHECK1,CHECK2", "The list of checks passed to PMD run.sh -R, default: 'java-basic,java-sunsecure'" do |checks|
|
201
|
+
options[:pmd_checks] = checks
|
202
|
+
end
|
203
|
+
|
204
|
+
opts.separator ""
|
205
|
+
opts.separator "FindSecurityBugs options:"
|
206
|
+
|
207
|
+
opts.on "--findsecbugs-path PATH", "The full path to the base FindSecurityBugs directory" do |dir|
|
208
|
+
options[:findsecbugs_path] = dir
|
209
|
+
end
|
210
|
+
|
193
211
|
opts.separator ""
|
194
212
|
opts.separator "Configuration files:"
|
195
213
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'pipeline/tasks/base_task'
|
2
2
|
require 'pipeline/util'
|
3
|
-
|
3
|
+
require 'nokogiri'
|
4
4
|
|
5
5
|
class Pipeline::Checkmarx < Pipeline::BaseTask
|
6
6
|
|
@@ -28,7 +28,7 @@ class Pipeline::Checkmarx < Pipeline::BaseTask
|
|
28
28
|
"-ReportXML", "#{rootpath}checkmarx_results.xml",
|
29
29
|
"-Log", "#{@tracker.options[:checkmarx_log]}"
|
30
30
|
)
|
31
|
-
|
31
|
+
@results = Nokogiri::XML(File.read("#{rootpath}checkmarx_results.xml")).xpath '//Result'
|
32
32
|
end
|
33
33
|
|
34
34
|
def analyze
|
@@ -38,9 +38,9 @@ class Pipeline::Checkmarx < Pipeline::BaseTask
|
|
38
38
|
detail = result.attributes['DeepLink'].value
|
39
39
|
source = { :scanner => @name, :file => result.attributes['FileName'].value, :line => result.attributes['Line'].value.to_i, :code => result.at_xpath('Path/PathNode/Snippet/Line/Code').text }
|
40
40
|
sev = severity(result.parent.attributes['Severity'].value)
|
41
|
-
|
41
|
+
fprint = fingerprint("#{description}#{source}#{sev}")
|
42
42
|
|
43
|
-
report description, detail, source, sev,
|
43
|
+
report description, detail, source, sev, fprint
|
44
44
|
end
|
45
45
|
rescue Exception => e
|
46
46
|
Pipeline.warn e.message
|
@@ -59,4 +59,3 @@ class Pipeline::Checkmarx < Pipeline::BaseTask
|
|
59
59
|
end
|
60
60
|
|
61
61
|
end
|
62
|
-
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'pipeline/tasks/base_task'
|
2
|
+
require 'pipeline/util'
|
3
|
+
require 'tempfile'
|
4
|
+
|
5
|
+
class Pipeline::DawnScanner < Pipeline::BaseTask
|
6
|
+
|
7
|
+
Pipeline::Tasks.add self
|
8
|
+
include Pipeline::Util
|
9
|
+
|
10
|
+
def initialize(trigger, tracker)
|
11
|
+
super(trigger, tracker)
|
12
|
+
@name = "DawnScanner"
|
13
|
+
@description = "DawnScanner ruby analyzer"
|
14
|
+
@stage = :code
|
15
|
+
@labels << "code"
|
16
|
+
end
|
17
|
+
|
18
|
+
def run
|
19
|
+
Pipeline.notify "#{@name}"
|
20
|
+
Dir.chdir("#{@trigger.path}") do
|
21
|
+
@results_file = Tempfile.new(['dawnresults', 'xml'])
|
22
|
+
runsystem(true, "dawn", "-F", "#{@results_file.path}", "-j", ".")
|
23
|
+
@results = JSON.parse(File.read("#{@results_file.path}"))['vulnerabilities']
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def analyze
|
28
|
+
begin
|
29
|
+
@results.each do |result|
|
30
|
+
description = result['name'].gsub('\n',' ')
|
31
|
+
detail = "#{result['message']}\n#{result['remediation']}\n#{result['cve_link']}"
|
32
|
+
source = {:scanner => @name, :file => nil, :line => nil, :code => nil}
|
33
|
+
sev = severity(result['severity'])
|
34
|
+
fprint = fingerprint("#{description}#{detail}#{source}#{sev}")
|
35
|
+
|
36
|
+
report description, detail, source, sev, fprint
|
37
|
+
end
|
38
|
+
rescue Exception => e
|
39
|
+
Pipeline.warn e.message
|
40
|
+
Pipeline.warn e.backtrace
|
41
|
+
ensure
|
42
|
+
File.unlink @results_file
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def supported?
|
47
|
+
supported=runsystem(true, "dawn", "--version")
|
48
|
+
if supported =~ /command not found/
|
49
|
+
Pipeline.notify "Install dawnscanner: 'gem install dawnscanner'"
|
50
|
+
return false
|
51
|
+
else
|
52
|
+
return true
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
require 'pipeline/tasks/base_task'
|
2
|
+
require 'pipeline/util'
|
3
|
+
require 'nokogiri'
|
4
|
+
require 'tempfile'
|
5
|
+
require 'mkmf'
|
6
|
+
|
7
|
+
MakeMakefile::Logging.instance_variable_set(:@logfile, File::NULL)
|
8
|
+
|
9
|
+
class Pipeline::FindSecurityBugs < Pipeline::BaseTask
|
10
|
+
|
11
|
+
Pipeline::Tasks.add self
|
12
|
+
include Pipeline::Util
|
13
|
+
|
14
|
+
def initialize(trigger, tracker)
|
15
|
+
super(trigger, tracker)
|
16
|
+
@name = "FindSecurityBugs"
|
17
|
+
@description = "FindSecurityBugs plugin for FindBugs"
|
18
|
+
@stage = :code
|
19
|
+
@labels << "code"
|
20
|
+
end
|
21
|
+
|
22
|
+
def run
|
23
|
+
Pipeline.notify "#{@name}"
|
24
|
+
@results_file = Tempfile.new(['findsecbugs','xml'])
|
25
|
+
|
26
|
+
Dir.chdir("#{@trigger.path}") do
|
27
|
+
runsystem(true, "mvn", "compile", "-fn")
|
28
|
+
end
|
29
|
+
|
30
|
+
Dir.chdir("#{@tracker.options[:findsecbugs_path]}") do
|
31
|
+
runsystem(true, "/bin/sh", "#{@tracker.options[:findsecbugs_path]}/findsecbugs.sh", "-effort:max", "-quiet", "-xml:withMessages", "-output", "#{@results_file.path}", "#{@trigger.path}")
|
32
|
+
@results = Nokogiri::XML(File.read(@results_file)).xpath '//BugInstance'
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def analyze
|
37
|
+
begin
|
38
|
+
@results.each do |result|
|
39
|
+
description = result.xpath('ShortMessage').text
|
40
|
+
bug_type = result.attributes['type'].value
|
41
|
+
detail = "Class: #{result.at_xpath('Method').attributes['classname'].value}, Method: #{result.at_xpath('Method').attributes['name'].value}\n#{result.xpath('LongMessage').text}\nhttps://find-sec-bugs.github.io/bugs.htm##{bug_type}"
|
42
|
+
|
43
|
+
file = result.at_xpath('SourceLine').attributes['sourcepath'].value
|
44
|
+
trigger_path = Pathname.new(@trigger.path)
|
45
|
+
real_path = nil
|
46
|
+
trigger_path.find {|path| real_path = path if path.fnmatch "*/#{file}"}
|
47
|
+
file = real_path.relative_path_from(trigger_path).to_s unless real_path.nil?
|
48
|
+
|
49
|
+
line = result.at_xpath('SourceLine[@primary="true"]').attributes['start'].value
|
50
|
+
code = "#{result.at_xpath('String').attributes['value'].value}"
|
51
|
+
source = {:scanner => @name, :file => file, :line => line, :code => code}
|
52
|
+
sev = result.attributes['priority'].value
|
53
|
+
fprint = fingerprint("#{description}#{detail}#{source}")
|
54
|
+
|
55
|
+
report description, detail, source, sev, fprint
|
56
|
+
end
|
57
|
+
rescue Exception => e
|
58
|
+
Pipeline.warn e.message
|
59
|
+
Pipeline.warn e.backtrace
|
60
|
+
ensure
|
61
|
+
File.unlink @results_file
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def supported?
|
66
|
+
unless find_executable0('mvn') and File.exist?("#{@trigger.path}/pom.xml")
|
67
|
+
Pipeline.notify "FindSecurityBugs support requires maven and pom.xml"
|
68
|
+
Pipeline.notify "Please install maven somewhere in your PATH and include a valid pom.xml in the project root"
|
69
|
+
return false
|
70
|
+
end
|
71
|
+
|
72
|
+
unless @tracker.options.has_key?(:findsecbugs_path) and File.exist?("#{@tracker.options[:findsecbugs_path]}/findsecbugs.sh")
|
73
|
+
Pipeline.notify "#{@tracker.options[:findsecbugs_path]}"
|
74
|
+
Pipeline.notify "Download and unpack the latest findsecbugs-cli release: https://github.com/find-sec-bugs/find-sec-bugs/releases"
|
75
|
+
return false
|
76
|
+
else
|
77
|
+
return true
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'pipeline/tasks/base_task'
|
2
|
+
require 'pipeline/util'
|
3
|
+
require 'nokogiri'
|
4
|
+
require 'pathname'
|
5
|
+
|
6
|
+
class Pipeline::PMD < Pipeline::BaseTask
|
7
|
+
|
8
|
+
Pipeline::Tasks.add self
|
9
|
+
include Pipeline::Util
|
10
|
+
|
11
|
+
def initialize(trigger, tracker)
|
12
|
+
super(trigger, tracker)
|
13
|
+
@name = "PMD"
|
14
|
+
@description = "PMD Source Code Analyzer"
|
15
|
+
@stage = :code
|
16
|
+
@labels << "code"
|
17
|
+
end
|
18
|
+
|
19
|
+
def run
|
20
|
+
Pipeline.notify "#{@name}"
|
21
|
+
@tracker.options[:pmd_checks] ||= "java-basic,java-sunsecure"
|
22
|
+
Dir.chdir @tracker.options[:pmd_path] do
|
23
|
+
@results = Nokogiri::XML(`bin/run.sh pmd -d #{@trigger.path} -f xml -R #{@tracker.options[:pmd_checks]}`).xpath('//file')
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def analyze
|
28
|
+
begin
|
29
|
+
@results.each do |result|
|
30
|
+
attributes = result.at_xpath('violation').attributes
|
31
|
+
description = result.children.children.to_s.strip
|
32
|
+
detail = "Ruleset: #{attributes['ruleset']}"
|
33
|
+
source = {:scanner => @name, :file => result.attributes['name'].to_s.split(Pathname.new(@trigger.path).cleanpath.to_s)[1][1..-1], :line => attributes['beginline'].to_s, :code => "package: #{attributes['package'].to_s}\nclass: #{attributes['class'].to_s}\nmethod: #{attributes['method'].to_s}" }
|
34
|
+
case attributes['priority'].value.to_i
|
35
|
+
when 3
|
36
|
+
sev = 1
|
37
|
+
when 2
|
38
|
+
sev = 2
|
39
|
+
when 1
|
40
|
+
sev = 3
|
41
|
+
else
|
42
|
+
sev = 0
|
43
|
+
end
|
44
|
+
fprint = fingerprint("#{description}#{detail}#{source}#{sev}")
|
45
|
+
|
46
|
+
report description, detail, source, sev, fprint
|
47
|
+
end
|
48
|
+
rescue Exception => e
|
49
|
+
Pipeline.warn e.message
|
50
|
+
Pipeline.warn e.backtrace
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def supported?
|
55
|
+
unless @tracker.options.has_key?(:pmd_path) and File.exist?("#{@tracker.options[:pmd_path]}/bin/run.sh")
|
56
|
+
Pipeline.notify "#{@tracker.options[:pmd_path]}"
|
57
|
+
Pipeline.notify "Install PMD from: https://pmd.github.io/"
|
58
|
+
return false
|
59
|
+
else
|
60
|
+
return true
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
data/lib/pipeline/tasks/zap.rb
CHANGED
@@ -2,6 +2,7 @@ require 'pipeline/tasks/base_task'
|
|
2
2
|
require 'pipeline/util'
|
3
3
|
require 'json'
|
4
4
|
require 'curb'
|
5
|
+
require 'securerandom'
|
5
6
|
|
6
7
|
class Pipeline::Zap < Pipeline::BaseTask
|
7
8
|
|
@@ -19,21 +20,33 @@ class Pipeline::Zap < Pipeline::BaseTask
|
|
19
20
|
def run
|
20
21
|
rootpath = @trigger.path
|
21
22
|
base = "#{@tracker.options[:zap_host]}:#{@tracker.options[:zap_port]}"
|
22
|
-
|
23
|
+
apikey = "#{@tracker.options[:zap_api_token]}"
|
24
|
+
context = SecureRandom.uuid
|
23
25
|
|
24
|
-
|
25
|
-
|
26
|
+
Pipeline.debug "Running ZAP on: #{rootpath} from #{base} with #{context}"
|
27
|
+
|
28
|
+
# Set up Context
|
29
|
+
Curl.get("#{base}/JSON/context/action/newContext/?&apikey=#{apikey}&contextName=#{context}")
|
30
|
+
Curl.get("#{base}/JSON/context/action/includeInContext/?apikey=#{apikey}&contextName=#{context}®ex=#{rootpath}.*")
|
26
31
|
|
27
32
|
# Spider
|
28
|
-
Curl.get("#{base}/JSON/spider/action/scan
|
29
|
-
poll_until_100("#{base}/JSON/spider/view/status")
|
33
|
+
spider = get_scan_id( Curl.get("#{base}/JSON/spider/action/scan/?apikey=#{apikey}&url=#{rootpath}&context=#{context}") )
|
34
|
+
poll_until_100("#{base}/JSON/spider/view/status/?scanId=#{spider}")
|
30
35
|
|
31
36
|
# 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
|
37
|
+
scan = get_scan_id ( Curl.get("#{base}/JSON/ascan/action/scan/?apikey=#{apikey}&recurse=true&inScopeOnly=true&url=#{rootpath}") )
|
38
|
+
poll_until_100("#{base}/JSON/ascan/view/status/?scanId=#{scan}")
|
34
39
|
|
35
40
|
# Result
|
36
|
-
@result = Curl.get("#{base}/JSON/core/view/alerts
|
41
|
+
@result = Curl.get("#{base}/JSON/core/view/alerts/?baseurl=#{rootpath}").body_str
|
42
|
+
|
43
|
+
# Remove Context
|
44
|
+
Curl.get("#{base}/JSON/context/action/removeContext/?&apikey=#{apikey}&contextName=#{context}")
|
45
|
+
end
|
46
|
+
|
47
|
+
def get_scan_id(response)
|
48
|
+
json = JSON.parse response.body_str
|
49
|
+
return json["scan"]
|
37
50
|
end
|
38
51
|
|
39
52
|
def poll_until_100(url)
|
data/lib/pipeline/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: owasp-pipeline
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.8.
|
4
|
+
version: 0.8.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Matt Konda
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2016-
|
13
|
+
date: 2016-03-07 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: terminal-table
|
@@ -124,6 +124,76 @@ dependencies:
|
|
124
124
|
- - ">="
|
125
125
|
- !ruby/object:Gem::Version
|
126
126
|
version: 0.5.7
|
127
|
+
- !ruby/object:Gem::Dependency
|
128
|
+
name: nokogiri
|
129
|
+
requirement: !ruby/object:Gem::Requirement
|
130
|
+
requirements:
|
131
|
+
- - ">="
|
132
|
+
- !ruby/object:Gem::Version
|
133
|
+
version: 1.6.6.2
|
134
|
+
type: :runtime
|
135
|
+
prerelease: false
|
136
|
+
version_requirements: !ruby/object:Gem::Requirement
|
137
|
+
requirements:
|
138
|
+
- - ">="
|
139
|
+
- !ruby/object:Gem::Version
|
140
|
+
version: 1.6.6.2
|
141
|
+
- !ruby/object:Gem::Dependency
|
142
|
+
name: rake
|
143
|
+
requirement: !ruby/object:Gem::Requirement
|
144
|
+
requirements:
|
145
|
+
- - ">="
|
146
|
+
- !ruby/object:Gem::Version
|
147
|
+
version: '0'
|
148
|
+
type: :runtime
|
149
|
+
prerelease: false
|
150
|
+
version_requirements: !ruby/object:Gem::Requirement
|
151
|
+
requirements:
|
152
|
+
- - ">="
|
153
|
+
- !ruby/object:Gem::Version
|
154
|
+
version: '0'
|
155
|
+
- !ruby/object:Gem::Dependency
|
156
|
+
name: dawnscanner
|
157
|
+
requirement: !ruby/object:Gem::Requirement
|
158
|
+
requirements:
|
159
|
+
- - ">="
|
160
|
+
- !ruby/object:Gem::Version
|
161
|
+
version: 1.6.0
|
162
|
+
type: :runtime
|
163
|
+
prerelease: false
|
164
|
+
version_requirements: !ruby/object:Gem::Requirement
|
165
|
+
requirements:
|
166
|
+
- - ">="
|
167
|
+
- !ruby/object:Gem::Version
|
168
|
+
version: 1.6.0
|
169
|
+
- !ruby/object:Gem::Dependency
|
170
|
+
name: pry
|
171
|
+
requirement: !ruby/object:Gem::Requirement
|
172
|
+
requirements:
|
173
|
+
- - ">="
|
174
|
+
- !ruby/object:Gem::Version
|
175
|
+
version: '0'
|
176
|
+
type: :development
|
177
|
+
prerelease: false
|
178
|
+
version_requirements: !ruby/object:Gem::Requirement
|
179
|
+
requirements:
|
180
|
+
- - ">="
|
181
|
+
- !ruby/object:Gem::Version
|
182
|
+
version: '0'
|
183
|
+
- !ruby/object:Gem::Dependency
|
184
|
+
name: pry-byebug
|
185
|
+
requirement: !ruby/object:Gem::Requirement
|
186
|
+
requirements:
|
187
|
+
- - ">="
|
188
|
+
- !ruby/object:Gem::Version
|
189
|
+
version: '0'
|
190
|
+
type: :development
|
191
|
+
prerelease: false
|
192
|
+
version_requirements: !ruby/object:Gem::Requirement
|
193
|
+
requirements:
|
194
|
+
- - ">="
|
195
|
+
- !ruby/object:Gem::Version
|
196
|
+
version: '0'
|
127
197
|
description: Pipeline detects security vulnerabilities in code.
|
128
198
|
email: matt.konda@owasp.org
|
129
199
|
executables:
|
@@ -163,11 +233,14 @@ files:
|
|
163
233
|
- lib/pipeline/tasks/brakeman.rb
|
164
234
|
- lib/pipeline/tasks/bundle-audit.rb
|
165
235
|
- lib/pipeline/tasks/checkmarx.rb
|
236
|
+
- lib/pipeline/tasks/dawnscanner.rb
|
166
237
|
- lib/pipeline/tasks/eslint.rb
|
167
238
|
- lib/pipeline/tasks/fim.rb
|
239
|
+
- lib/pipeline/tasks/findsecbugs.rb
|
168
240
|
- lib/pipeline/tasks/nsp.rb
|
169
241
|
- lib/pipeline/tasks/owasp-dep-check.rb
|
170
242
|
- lib/pipeline/tasks/patterns.json
|
243
|
+
- lib/pipeline/tasks/pmd.rb
|
171
244
|
- lib/pipeline/tasks/retirejs.rb
|
172
245
|
- lib/pipeline/tasks/scanjs-eslintrc
|
173
246
|
- lib/pipeline/tasks/scanjs.rb
|