nasl-pedant 0.0.3 → 0.0.4
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.
- data/Rakefile +38 -0
- data/bin/pedant +1 -1
- data/lib/pedant.rb +3 -1
- data/lib/pedant/check.rb +20 -12
- data/lib/pedant/checks/conditional_or_loop_is_empty.rb +1 -1
- data/lib/pedant/checks/contains_ip_address_literals.rb +1 -1
- data/lib/pedant/checks/contains_no_carriage_returns.rb +1 -1
- data/lib/pedant/checks/contains_no_tabs.rb +1 -1
- data/lib/pedant/checks/contains_registration_section.rb +10 -4
- data/lib/pedant/checks/contains_unreachable_code.rb +2 -2
- data/lib/pedant/checks/ends_with_newline.rb +1 -1
- data/lib/pedant/checks/{files_parse_without_error.rb → files_parse_without_errors.rb} +1 -1
- data/lib/pedant/checks/local_variable_unused.rb +51 -0
- data/lib/pedant/checks/parse_test_code.rb +1 -1
- data/lib/pedant/checks/plugin_type_not_specified.rb +4 -3
- data/lib/pedant/checks/script_category.rb +111 -0
- data/lib/pedant/checks/script_family_not_specified.rb +53 -16
- data/lib/pedant/checks/script_id.rb +115 -0
- data/lib/pedant/checks/script_name.rb +133 -0
- data/lib/pedant/checks/script_summary.rb +142 -0
- data/lib/pedant/cli.rb +41 -31
- data/lib/pedant/command.rb +16 -29
- data/lib/pedant/commands/check.rb +105 -6
- data/lib/pedant/commands/test.rb +24 -2
- data/lib/pedant/knowledge_base.rb +1 -1
- data/lib/pedant/test.rb +5 -5
- data/lib/pedant/version.rb +1 -1
- data/pedant.gemspec +33 -6
- data/test/test_helper.rb +26 -0
- data/test/unit/checks/test_conditional_or_loop_is_empty.rb +1 -1
- data/test/unit/checks/test_contains_ip_address_literals.rb +1 -1
- data/test/unit/checks/test_contains_no_carriage_returns.rb +1 -1
- data/test/unit/checks/test_contains_no_tabs.rb +1 -1
- data/test/unit/checks/test_contains_registration_section.rb +17 -1
- data/test/unit/checks/test_contains_unreachable_code.rb +11 -1
- data/test/unit/checks/test_ends_with_newline.rb +1 -1
- data/test/unit/checks/test_plugin_type_not_specified.rb +9 -1
- data/test/unit/checks/test_script_family_not_specified.rb +54 -13
- metadata +30 -20
data/lib/pedant/command.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
################################################################################
|
2
|
-
# Copyright (c) 2011,
|
2
|
+
# Copyright (c) 2011-2014, Tenable Network Security
|
3
3
|
# All rights reserved.
|
4
4
|
#
|
5
5
|
# Redistribution and use in source and binary forms, with or without
|
@@ -38,6 +38,10 @@ module Pedant
|
|
38
38
|
all << cls
|
39
39
|
end
|
40
40
|
|
41
|
+
def self.list
|
42
|
+
all.map{ |cls| cls.binding }.sort
|
43
|
+
end
|
44
|
+
|
41
45
|
def self.find(cmd)
|
42
46
|
all.each do |cls|
|
43
47
|
return cls if cls.binding == cmd
|
@@ -61,36 +65,19 @@ module Pedant
|
|
61
65
|
left + middle + right
|
62
66
|
end
|
63
67
|
|
64
|
-
def self.run(
|
65
|
-
#
|
66
|
-
|
67
|
-
args -= paths
|
68
|
-
|
69
|
-
# If we have no paths to process, there's a problem. Special purpose
|
70
|
-
# commands that don't require files to be declared should override this
|
71
|
-
# method.
|
72
|
-
if paths.empty?
|
73
|
-
puts "No directories (/), libraries (.inc), or plugins (.nasl) were specified."
|
74
|
-
exit 1
|
75
|
-
end
|
68
|
+
def self.run(opts, args)
|
69
|
+
# Parse the command's arguments.
|
70
|
+
opts, args = optparse(opts, args)
|
76
71
|
|
77
|
-
#
|
78
|
-
|
79
|
-
|
80
|
-
Pathname.new(path).find do |dirent|
|
81
|
-
if dirent.file? && dirent.extname =~ /inc|nasl/
|
82
|
-
dirents << dirent
|
83
|
-
end
|
84
|
-
end
|
85
|
-
end
|
72
|
+
# Run the command.
|
73
|
+
self.run_all(opts, args)
|
74
|
+
end
|
86
75
|
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
dirents.each { |d| analyze(cfg, d, args) }
|
93
|
-
end
|
76
|
+
def self.usage(msg)
|
77
|
+
puts Rainbow(msg).color(:red)
|
78
|
+
puts
|
79
|
+
puts help
|
80
|
+
exit 1
|
94
81
|
end
|
95
82
|
end
|
96
83
|
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
################################################################################
|
2
|
-
# Copyright (c) 2011,
|
2
|
+
# Copyright (c) 2011-2014, Tenable Network Security
|
3
3
|
# All rights reserved.
|
4
4
|
#
|
5
5
|
# Redistribution and use in source and binary forms, with or without
|
@@ -24,17 +24,116 @@
|
|
24
24
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
25
25
|
################################################################################
|
26
26
|
|
27
|
+
require 'set'
|
28
|
+
|
27
29
|
module Pedant
|
28
30
|
class CommandCheck < Command
|
29
31
|
def self.binding
|
30
32
|
'check'
|
31
33
|
end
|
32
34
|
|
33
|
-
def self.
|
35
|
+
def self.help
|
36
|
+
@@optparse.to_s
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.optparse(options, args)
|
40
|
+
options[:checks] = Set.new
|
41
|
+
|
42
|
+
@@optparse = OptionParser.new do |opts|
|
43
|
+
opts.banner = "Usage: pedant [global-options] #{binding} [command-options] [args]"
|
44
|
+
|
45
|
+
opts.separator ""
|
46
|
+
opts.separator "Input formats:"
|
47
|
+
|
48
|
+
opts.on('-f', '--filesystem', 'Read input from the filesystem.') do
|
49
|
+
options[:input_mode] = :filesystem
|
50
|
+
end
|
51
|
+
|
52
|
+
opts.on('-g', '--git', 'Read input from a Git repository.') do
|
53
|
+
options[:input_mode] = :git
|
54
|
+
end
|
55
|
+
|
56
|
+
opts.separator ""
|
57
|
+
opts.separator "Output formats:"
|
58
|
+
|
59
|
+
opts.on('-e', '--email', 'Output in a form suitable for an email.') do
|
60
|
+
options[:output_mode] = :email
|
61
|
+
end
|
62
|
+
|
63
|
+
opts.on('-t', '--terminal', 'Output in a form suitable for a terminal.') do
|
64
|
+
options[:output_mode] = :terminal
|
65
|
+
end
|
66
|
+
|
67
|
+
opts.separator ""
|
68
|
+
opts.separator "Common operations:"
|
69
|
+
|
70
|
+
opts.on('-c=NAME', '--check=NAME', 'Run only the check named, and its dependencies.') do |name|
|
71
|
+
# Unmangle class name and be very forgiving.
|
72
|
+
name = "Check" + name.gsub(/[-._ ]/, '')
|
73
|
+
|
74
|
+
begin
|
75
|
+
cls = Pedant.const_get(name)
|
76
|
+
rescue NameError => e
|
77
|
+
usage(e.message)
|
78
|
+
end
|
79
|
+
|
80
|
+
options[:checks] << cls
|
81
|
+
end
|
82
|
+
|
83
|
+
opts.on('-h', '--help', 'Display this help screen.') do
|
84
|
+
puts opts
|
85
|
+
exit 1
|
86
|
+
end
|
87
|
+
|
88
|
+
opts.on('-l', '--list', 'List the available checks.') do
|
89
|
+
puts Check.list
|
90
|
+
exit 0
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
# Load all of the checks.
|
34
95
|
Check.initialize!
|
35
96
|
|
36
|
-
|
37
|
-
|
97
|
+
@@optparse.order!(args)
|
98
|
+
|
99
|
+
return options, args
|
100
|
+
end
|
101
|
+
|
102
|
+
def self.run_all(opts, args)
|
103
|
+
# Separate plugins and libraries from the rest of the arguments.
|
104
|
+
paths = args.select { |a| a =~ /(\/|\.(inc|nasl))$/ }
|
105
|
+
args -= paths
|
106
|
+
|
107
|
+
# If we have paths that aren't acceptable, there's a problem.
|
108
|
+
usage("One or more unacceptable files were specified.") unless args.empty?
|
109
|
+
|
110
|
+
# If we have no paths to process, there's a problem.
|
111
|
+
usage("No directories (/), libraries (.inc), or plugins (.nasl) were specified.") if paths.empty?
|
112
|
+
|
113
|
+
# Collect all the paths together, recursively.
|
114
|
+
dirents = []
|
115
|
+
paths.each do |path|
|
116
|
+
begin
|
117
|
+
Pathname.new(path).find do |dirent|
|
118
|
+
if dirent.file? && dirent.extname =~ /inc|nasl/
|
119
|
+
dirents << dirent
|
120
|
+
end
|
121
|
+
end
|
122
|
+
rescue SystemCallError => e
|
123
|
+
usage(e.message)
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
dirents.each { |d| run_one(opts, d) }
|
128
|
+
end
|
129
|
+
|
130
|
+
def self.run_one(opts, path)
|
131
|
+
# Get a list of the checks we're going to be running.
|
132
|
+
if not opts[:checks].empty?
|
133
|
+
pending = opts[:checks].to_a
|
134
|
+
else
|
135
|
+
pending = Check.all
|
136
|
+
end
|
38
137
|
|
39
138
|
# Initialize the knowledge base where checks can store information for
|
40
139
|
# other checks.
|
@@ -63,14 +162,14 @@ module Pedant
|
|
63
162
|
end
|
64
163
|
|
65
164
|
# Display the results of the check.
|
66
|
-
puts chk.report(
|
165
|
+
puts chk.report(opts[:verbosity])
|
67
166
|
end
|
68
167
|
end
|
69
168
|
|
70
169
|
# Notify the user if any checks did not run due to unsatisfied
|
71
170
|
# dependencies or a fatal error occurring before they had the chance to
|
72
171
|
# run.
|
73
|
-
pending.each { |cls| puts cls.new(kb).report(
|
172
|
+
pending.each { |cls| puts cls.new(kb).report(opts[:verbosity]) }
|
74
173
|
end
|
75
174
|
end
|
76
175
|
end
|
data/lib/pedant/commands/test.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
################################################################################
|
2
|
-
# Copyright (c) 2011,
|
2
|
+
# Copyright (c) 2011-2014, Tenable Network Security
|
3
3
|
# All rights reserved.
|
4
4
|
#
|
5
5
|
# Redistribution and use in source and binary forms, with or without
|
@@ -30,7 +30,29 @@ module Pedant
|
|
30
30
|
'test'
|
31
31
|
end
|
32
32
|
|
33
|
-
def self.
|
33
|
+
def self.help
|
34
|
+
@@optparse.to_s
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.optparse(options, args)
|
38
|
+
@@optparse = OptionParser.new do |opts|
|
39
|
+
opts.banner = "Usage: pedant [global-options] #{binding} [command-options] [args]"
|
40
|
+
|
41
|
+
opts.separator ""
|
42
|
+
opts.separator "Common operations:"
|
43
|
+
|
44
|
+
opts.on('-h', '--help', 'Display this help screen.') do
|
45
|
+
puts opts
|
46
|
+
exit 1
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
@@optparse.order!(args)
|
51
|
+
|
52
|
+
return options, args
|
53
|
+
end
|
54
|
+
|
55
|
+
def self.run_all(opts, args)
|
34
56
|
Test.initialize!(args)
|
35
57
|
end
|
36
58
|
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
################################################################################
|
2
|
-
# Copyright (c) 2011,
|
2
|
+
# Copyright (c) 2011-2014, Tenable Network Security
|
3
3
|
# All rights reserved.
|
4
4
|
#
|
5
5
|
# Redistribution and use in source and binary forms, with or without
|
data/lib/pedant/test.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
################################################################################
|
2
|
-
# Copyright (c) 2011,
|
2
|
+
# Copyright (c) 2011-2014, Tenable Network Security
|
3
3
|
# All rights reserved.
|
4
4
|
#
|
5
5
|
# Redistribution and use in source and binary forms, with or without
|
@@ -28,13 +28,13 @@ require 'test/unit'
|
|
28
28
|
|
29
29
|
module Pedant
|
30
30
|
module Test
|
31
|
-
def self.initialize!(args)
|
31
|
+
def self.initialize!(args=[])
|
32
32
|
# Run all tests by default.
|
33
|
-
args = ['unit
|
33
|
+
args = ['unit/**/*'] if args.empty?
|
34
34
|
|
35
35
|
# Run each test or category of tests specified on the command line.
|
36
|
-
args.each do |
|
37
|
-
Dir.glob(Pedant.test + (
|
36
|
+
args.each do |path|
|
37
|
+
Dir.glob(Pedant.test + (path + '.rb')).each { |f| load(f) }
|
38
38
|
end
|
39
39
|
|
40
40
|
Check.initialize!
|
data/lib/pedant/version.rb
CHANGED
data/pedant.gemspec
CHANGED
@@ -1,3 +1,29 @@
|
|
1
|
+
################################################################################
|
2
|
+
# Copyright (c) 2011-2014, Tenable Network Security
|
3
|
+
# All rights reserved.
|
4
|
+
#
|
5
|
+
# Redistribution and use in source and binary forms, with or without
|
6
|
+
# modification, are permitted provided that the following conditions are met:
|
7
|
+
#
|
8
|
+
# 1. Redistributions of source code must retain the above copyright notice, this
|
9
|
+
# list of conditions and the following disclaimer.
|
10
|
+
#
|
11
|
+
# 2. Redistributions in binary form must reproduce the above copyright notice,
|
12
|
+
# this list of conditions and the following disclaimer in the documentation
|
13
|
+
# and/or other materials provided with the distribution.
|
14
|
+
#
|
15
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
16
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
17
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
18
|
+
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
19
|
+
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
20
|
+
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
21
|
+
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
22
|
+
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
23
|
+
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
24
|
+
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
25
|
+
################################################################################
|
26
|
+
|
1
27
|
# -*- encoding: utf-8 -*-
|
2
28
|
$:.push File.expand_path('../lib', __FILE__)
|
3
29
|
|
@@ -8,10 +34,11 @@ Gem::Specification.new do |s|
|
|
8
34
|
s.version = Pedant::VERSION
|
9
35
|
s.license = 'BSD'
|
10
36
|
s.homepage = 'http://github.com/tenable/pedant'
|
11
|
-
s.summary = 'A
|
37
|
+
s.summary = 'A framework for the Nessus Attack Scripting Language.'
|
38
|
+
s.description = 'A static analysis framework for the Nessus Attack Scripting Language.'
|
12
39
|
|
13
|
-
s.authors = ['Mak Kolybabi']
|
14
|
-
s.email = ['mak@kolybabi.com']
|
40
|
+
s.authors = ['Mak Kolybabi', 'Alex Weber', 'Jacob Hammack']
|
41
|
+
s.email = ['mak@kolybabi.com', 'aweber@tenable.com', 'jhammack@tenable.com']
|
15
42
|
|
16
43
|
s.rubyforge_project = 'nasl-pedant'
|
17
44
|
|
@@ -20,8 +47,8 @@ Gem::Specification.new do |s|
|
|
20
47
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
21
48
|
s.require_paths = ['lib']
|
22
49
|
|
23
|
-
s.add_development_dependency 'rake'
|
50
|
+
s.add_development_dependency 'rake', '~> 0'
|
24
51
|
|
25
|
-
s.add_runtime_dependency 'rainbow'
|
26
|
-
s.add_runtime_dependency 'nasl', '>= 0.0
|
52
|
+
s.add_runtime_dependency 'rainbow', '=2.0.0'
|
53
|
+
s.add_runtime_dependency 'nasl', '~> 0.2', '>= 0.2.0'
|
27
54
|
end
|
data/test/test_helper.rb
CHANGED
@@ -1,3 +1,29 @@
|
|
1
|
+
################################################################################
|
2
|
+
# Copyright (c) 2011-2014, Tenable Network Security
|
3
|
+
# All rights reserved.
|
4
|
+
#
|
5
|
+
# Redistribution and use in source and binary forms, with or without
|
6
|
+
# modification, are permitted provided that the following conditions are met:
|
7
|
+
#
|
8
|
+
# 1. Redistributions of source code must retain the above copyright notice, this
|
9
|
+
# list of conditions and the following disclaimer.
|
10
|
+
#
|
11
|
+
# 2. Redistributions in binary form must reproduce the above copyright notice,
|
12
|
+
# this list of conditions and the following disclaimer in the documentation
|
13
|
+
# and/or other materials provided with the distribution.
|
14
|
+
#
|
15
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
16
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
17
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
18
|
+
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
19
|
+
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
20
|
+
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
21
|
+
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
22
|
+
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
23
|
+
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
24
|
+
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
25
|
+
################################################################################
|
26
|
+
|
1
27
|
require 'pedant'
|
2
28
|
require 'test/unit'
|
3
29
|
|
@@ -1,5 +1,5 @@
|
|
1
1
|
################################################################################
|
2
|
-
# Copyright (c) 2011,
|
2
|
+
# Copyright (c) 2011-2014, Tenable Network Security
|
3
3
|
# All rights reserved.
|
4
4
|
#
|
5
5
|
# Redistribution and use in source and binary forms, with or without
|
@@ -1,5 +1,5 @@
|
|
1
1
|
################################################################################
|
2
|
-
# Copyright (c) 2011,
|
2
|
+
# Copyright (c) 2011-2014, Tenable Network Security
|
3
3
|
# All rights reserved.
|
4
4
|
#
|
5
5
|
# Redistribution and use in source and binary forms, with or without
|
@@ -1,5 +1,5 @@
|
|
1
1
|
################################################################################
|
2
|
-
# Copyright (c) 2011,
|
2
|
+
# Copyright (c) 2011-2014, Tenable Network Security
|
3
3
|
# All rights reserved.
|
4
4
|
#
|
5
5
|
# Redistribution and use in source and binary forms, with or without
|
@@ -1,5 +1,5 @@
|
|
1
1
|
################################################################################
|
2
|
-
# Copyright (c) 2011,
|
2
|
+
# Copyright (c) 2011-2014, Tenable Network Security
|
3
3
|
# All rights reserved.
|
4
4
|
#
|
5
5
|
# Redistribution and use in source and binary forms, with or without
|
@@ -1,5 +1,5 @@
|
|
1
1
|
################################################################################
|
2
|
-
# Copyright (c) 2011,
|
2
|
+
# Copyright (c) 2011-2014, Tenable Network Security
|
3
3
|
# All rights reserved.
|
4
4
|
#
|
5
5
|
# Redistribution and use in source and binary forms, with or without
|
@@ -98,4 +98,20 @@ class TestContainsRegistrationSection < Test::Unit::TestCase
|
|
98
98
|
%q|if (description) { exit(0, foo); }|
|
99
99
|
)
|
100
100
|
end
|
101
|
+
|
102
|
+
def test_indexed_description
|
103
|
+
check(
|
104
|
+
:fail,
|
105
|
+
:CheckContainsRegistrationSection,
|
106
|
+
%q|if (description["foo"]) { exit(0); }|
|
107
|
+
)
|
108
|
+
end
|
109
|
+
|
110
|
+
def test_indexed_exit
|
111
|
+
check(
|
112
|
+
:fail,
|
113
|
+
:CheckContainsRegistrationSection,
|
114
|
+
%q|if (description) { exit[foo](0); }|
|
115
|
+
)
|
116
|
+
end
|
101
117
|
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
################################################################################
|
2
|
-
# Copyright (c) 2011,
|
2
|
+
# Copyright (c) 2011-2014, Tenable Network Security
|
3
3
|
# All rights reserved.
|
4
4
|
#
|
5
5
|
# Redistribution and use in source and binary forms, with or without
|
@@ -90,4 +90,14 @@ class TestContainsUnreachableCode < Test::Unit::TestCase
|
|
90
90
|
%q|{ continue; foo(); }|
|
91
91
|
)
|
92
92
|
end
|
93
|
+
|
94
|
+
# exit() is a special case in this check, because it's a function instead of a
|
95
|
+
# language keyword.
|
96
|
+
def test_indexed_exit
|
97
|
+
check(
|
98
|
+
:pass,
|
99
|
+
:CheckContainsUnreachableCode,
|
100
|
+
%q|{ exit.foo(); foo(); }|
|
101
|
+
)
|
102
|
+
end
|
93
103
|
end
|