nasl-pedant 0.1.1 → 0.1.2
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 +5 -13
- data/README.md +1 -1
- data/lib/pedant/checks/contains_display.rb +53 -0
- data/lib/pedant/checks/contains_unreachable_code.rb +4 -1
- data/lib/pedant/checks/get_byte_used.rb +62 -0
- data/lib/pedant/checks/script_missing_audit_inc.rb +67 -0
- data/lib/pedant/checks/script_not_signed_and_using_secret_kb_item.rb +90 -0
- data/lib/pedant/checks/script_not_signed_and_using_trusted_function.rb +195 -0
- data/lib/pedant/checks/socket_leak.rb +189 -0
- data/lib/pedant/version.rb +1 -1
- data/pedant.gemspec +1 -0
- data/test/unit/checks/test_contains_display.rb +53 -0
- data/test/unit/checks/test_contains_unreachable_code.rb +14 -0
- data/test/unit/checks/test_get_byte_used.rb +105 -0
- data/test/unit/checks/test_script_missing_audit_inc.rb +61 -0
- data/test/unit/checks/test_script_not_signed_and_using_secret_kb_item.rb +251 -0
- data/test/unit/checks/test_script_not_signed_and_using_trusted_functions.rb +89 -0
- data/test/unit/checks/test_socket_leak.rb +174 -0
- metadata +44 -13
@@ -0,0 +1,189 @@
|
|
1
|
+
################################################################################
|
2
|
+
# Copyright (c) 2016, 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
|
+
|
27
|
+
module Pedant
|
28
|
+
class CheckSocketLeak < Check
|
29
|
+
def self.requires
|
30
|
+
super + [:trees]
|
31
|
+
end
|
32
|
+
|
33
|
+
##
|
34
|
+
# Breaks the tree up into functions and feeds them into block_parser
|
35
|
+
# @param file the current file being examined
|
36
|
+
# @param tree the entire file tree
|
37
|
+
##
|
38
|
+
def check(file, tree)
|
39
|
+
|
40
|
+
##
|
41
|
+
# If the allFound contains anything then throw up a warning
|
42
|
+
##
|
43
|
+
def report_findings(allFound)
|
44
|
+
if allFound.size() > 0
|
45
|
+
warn
|
46
|
+
output = ""
|
47
|
+
allFound.each do |handle|
|
48
|
+
if !output.empty?
|
49
|
+
output += ", "
|
50
|
+
end
|
51
|
+
if handle == ""
|
52
|
+
handle = "<unassigned>"
|
53
|
+
end
|
54
|
+
output += handle
|
55
|
+
end
|
56
|
+
report(:warn, "Possibly leaked socket handle(s): " + output)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
##
|
61
|
+
# Examines a single passed in node and tries to appropriately handle it
|
62
|
+
# based on the type. This function ignores "g_sock" and _ssh_socket as both
|
63
|
+
# of these are handled in a way that this parser can't really handle
|
64
|
+
#
|
65
|
+
# @param bnode the node to examine
|
66
|
+
# @param found a set of active "open_sock_tcp" items
|
67
|
+
# @return the new list of open_sock_tcp items
|
68
|
+
##
|
69
|
+
def node_parser(bnode, found)
|
70
|
+
if bnode.is_a?(Nasl::Assignment)
|
71
|
+
name = ""
|
72
|
+
if bnode.lval.is_a?(Nasl::Lvalue)
|
73
|
+
name = bnode.lval.ident.name;
|
74
|
+
end
|
75
|
+
if bnode.expr.is_a?(Nasl::Call)
|
76
|
+
if ((bnode.expr.name.ident.name == "open_sock_tcp" ||
|
77
|
+
bnode.expr.name.ident.name == "http_open_socket") &&
|
78
|
+
name != "g_sock" && name != "_ssh_socket")
|
79
|
+
found.add(name)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
elsif bnode.is_a?(Nasl::Local)
|
83
|
+
bnode.idents.each do |idents|
|
84
|
+
if idents.is_a?(Nasl::Assignment)
|
85
|
+
name = ""
|
86
|
+
if idents.lval.is_a?(Nasl::Lvalue)
|
87
|
+
name = idents.lval.ident.name
|
88
|
+
elsif idents.lval.is_a?(Nasl::Identifier)
|
89
|
+
name = idents.lval.name
|
90
|
+
end
|
91
|
+
if idents.expr.is_a?(Nasl::Call)
|
92
|
+
if ((idents.expr.name.ident.name == "open_sock_tcp" ||
|
93
|
+
idents.expr.name.ident.name == "http_open_socket") &&
|
94
|
+
name != "g_sock" && name != "_ssh_socket")
|
95
|
+
found.add(name)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
elsif bnode.is_a?(Nasl::Return)
|
101
|
+
# if the socket we are tracking gets returned then never mark it as
|
102
|
+
# a leak
|
103
|
+
if bnode.expr.is_a?(Nasl::Lvalue)
|
104
|
+
found = found - [bnode.expr.ident.name]
|
105
|
+
end
|
106
|
+
elsif (bnode.is_a?(Nasl::Break) || bnode.is_a?(Nasl::Continue) ||
|
107
|
+
(bnode.is_a?(Nasl::Call) && (bnode.name.ident.name == "exit" ||
|
108
|
+
bnode.name.ident.name == "audit")))
|
109
|
+
report_findings(found)
|
110
|
+
elsif bnode.is_a?(Nasl::If)
|
111
|
+
if (bnode.cond.is_a?(Nasl::Expression) and bnode.cond.rhs.is_a?(Nasl::Lvalue))
|
112
|
+
if bnode.cond.op.to_s() == "!"
|
113
|
+
if found.any? {|varName| varName == bnode.cond.rhs.ident.name}
|
114
|
+
# don't go down this path. This is the !soc path
|
115
|
+
return found;
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
# the if statement provides us with a block we can peak down to.
|
120
|
+
# However, it isn't always enumerable so handle accordingly
|
121
|
+
if (bnode.true.is_a?(Enumerable))
|
122
|
+
found = block_parser(bnode.true, found)
|
123
|
+
else
|
124
|
+
found = node_parser(bnode.true, found);
|
125
|
+
end
|
126
|
+
if (bnode.false.is_a?(Enumerable))
|
127
|
+
found = block_parser(bnode.false, found)
|
128
|
+
else
|
129
|
+
found = node_parser(bnode.false, found);
|
130
|
+
end
|
131
|
+
elsif bnode.is_a?(Nasl::Block)
|
132
|
+
found = block_parser(bnode.body, found);
|
133
|
+
elsif bnode.is_a?(Nasl::Call)
|
134
|
+
if (bnode.name.ident.name == "open_sock_tcp" ||
|
135
|
+
bnode.name.ident.name == "http_open_socket")
|
136
|
+
found.add("")
|
137
|
+
elsif (bnode.name.ident.name == "close" ||
|
138
|
+
bnode.name.ident.name == "ftp_close" ||
|
139
|
+
bnode.name.ident.name == "http_close_socket" ||
|
140
|
+
bnode.name.ident.name == "smtp_close")
|
141
|
+
# Check that this is an Lvalue. It could be a call or something
|
142
|
+
# which is just too complicated to handle and doesn't really work
|
143
|
+
# with our variable tracking system
|
144
|
+
if bnode.args[0].expr.is_a?(Nasl::Lvalue)
|
145
|
+
found = found - [bnode.args[0].expr.ident.name]
|
146
|
+
end
|
147
|
+
elsif (bnode.name.ident.name == "session_init" ||
|
148
|
+
bnode.name.ident.name == "ssh_close_connection")
|
149
|
+
pass
|
150
|
+
end
|
151
|
+
end
|
152
|
+
return found
|
153
|
+
end
|
154
|
+
|
155
|
+
##
|
156
|
+
# Iterates over the blocks and hands individual nodes up to the node_parser
|
157
|
+
# @param block the current Block node to examine
|
158
|
+
# @param found the current list of found open_sock_tcp
|
159
|
+
# @param all the found open_sock_tcp that haven't been closed
|
160
|
+
##
|
161
|
+
def block_parser(block, found)
|
162
|
+
block.each do |node|
|
163
|
+
found = node_parser(node, found);
|
164
|
+
end
|
165
|
+
return found;
|
166
|
+
end
|
167
|
+
|
168
|
+
# Extract by the block. Will help us since we don't dive down into all
|
169
|
+
# blocks as of yet (only if statements)
|
170
|
+
allFound = Set.new
|
171
|
+
tree.all(:Function).each do |node|
|
172
|
+
allFound.merge(block_parser(node.body, Set.new))
|
173
|
+
end
|
174
|
+
|
175
|
+
# The main body of a file is not a Block, so it must be considered
|
176
|
+
# separately.
|
177
|
+
allFound.merge(block_parser(tree, Set.new))
|
178
|
+
report_findings(allFound)
|
179
|
+
end
|
180
|
+
|
181
|
+
def run
|
182
|
+
# This check will pass by default.
|
183
|
+
pass
|
184
|
+
|
185
|
+
# Run this check on the tree from every file.
|
186
|
+
@kb[:trees].each { |file, tree| check(file, tree) }
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
data/lib/pedant/version.rb
CHANGED
data/pedant.gemspec
CHANGED
@@ -0,0 +1,53 @@
|
|
1
|
+
################################################################################
|
2
|
+
# Copyright (c) 2016, 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
|
+
|
27
|
+
class TestContainsDisplay < Test::Unit::TestCase
|
28
|
+
include Pedant::Test
|
29
|
+
|
30
|
+
def test_empty
|
31
|
+
check(
|
32
|
+
:pass,
|
33
|
+
:CheckContainsDisplay,
|
34
|
+
%Q||
|
35
|
+
)
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_with_display
|
39
|
+
check(
|
40
|
+
:warn,
|
41
|
+
:CheckContainsDisplay,
|
42
|
+
%q|display("test"); exit(0);|
|
43
|
+
)
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_without
|
47
|
+
check(
|
48
|
+
:pass,
|
49
|
+
:CheckContainsDisplay,
|
50
|
+
%q|exit(0);|
|
51
|
+
)
|
52
|
+
end
|
53
|
+
end
|
@@ -40,6 +40,12 @@ class TestContainsUnreachableCode < Test::Unit::TestCase
|
|
40
40
|
%q|exit(); foo();|
|
41
41
|
)
|
42
42
|
|
43
|
+
check(
|
44
|
+
:fail,
|
45
|
+
:CheckContainsUnreachableCode,
|
46
|
+
%q|audit(); foo();|
|
47
|
+
)
|
48
|
+
|
43
49
|
check(
|
44
50
|
:fail,
|
45
51
|
:CheckContainsUnreachableCode,
|
@@ -100,4 +106,12 @@ class TestContainsUnreachableCode < Test::Unit::TestCase
|
|
100
106
|
%q|{ exit.foo(); foo(); }|
|
101
107
|
)
|
102
108
|
end
|
109
|
+
|
110
|
+
def audit_indexed_exit
|
111
|
+
check(
|
112
|
+
:pass,
|
113
|
+
:CheckContainsUnreachableCode,
|
114
|
+
%q|{ audit.foo(); foo(); }|
|
115
|
+
)
|
116
|
+
end
|
103
117
|
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
################################################################################
|
2
|
+
# Copyright (c) 2016, 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
|
+
|
27
|
+
class TestGetByteUsed< Test::Unit::TestCase
|
28
|
+
include Pedant::Test
|
29
|
+
|
30
|
+
def test_get_byte_used
|
31
|
+
check(
|
32
|
+
:fail,
|
33
|
+
:CheckGetByteUsed,
|
34
|
+
%q|get_byte(blob:blah, pos:10);|
|
35
|
+
)
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_get_word_used
|
39
|
+
check(
|
40
|
+
:fail,
|
41
|
+
:CheckGetByteUsed,
|
42
|
+
%q|get_word(blob:blah, pos:10);|
|
43
|
+
)
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_get_dword_used
|
47
|
+
check(
|
48
|
+
:fail,
|
49
|
+
:CheckGetByteUsed,
|
50
|
+
%q|get_dword(blob:blah, pos:10);|
|
51
|
+
)
|
52
|
+
end
|
53
|
+
|
54
|
+
def test_getbyte_used
|
55
|
+
check(
|
56
|
+
:pass,
|
57
|
+
:CheckGetByteUsed,
|
58
|
+
%q|getbyte(blob:blah, pos:10);|
|
59
|
+
)
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_getword_used
|
63
|
+
check(
|
64
|
+
:pass,
|
65
|
+
:CheckGetByteUsed,
|
66
|
+
%q|getword(blob:blah, pos:10);|
|
67
|
+
)
|
68
|
+
end
|
69
|
+
|
70
|
+
def test_getdword_used
|
71
|
+
check(
|
72
|
+
:pass,
|
73
|
+
:CheckGetByteUsed,
|
74
|
+
%q|getdword(blob:blah, pos:10);|
|
75
|
+
)
|
76
|
+
end
|
77
|
+
|
78
|
+
def test_get_byte_used_with_set_byte_order
|
79
|
+
check(
|
80
|
+
:fail,
|
81
|
+
:CheckGetByteUsed,
|
82
|
+
%q|set_byte_order(BYTE_ORDER_LITTLE_ENDIAN);| +
|
83
|
+
%q|get_byte(blob:blah, pos:10);|
|
84
|
+
)
|
85
|
+
end
|
86
|
+
|
87
|
+
def test_get_word_used_with_set_byte_order
|
88
|
+
check(
|
89
|
+
:fail,
|
90
|
+
:CheckGetByteUsed,
|
91
|
+
%q|set_byte_order(BYTE_ORDER_LITTLE_ENDIAN);| +
|
92
|
+
%q|get_word(blob:blah, pos:10);|
|
93
|
+
)
|
94
|
+
end
|
95
|
+
|
96
|
+
def test_get_dword_used_with_set_byte_order
|
97
|
+
check(
|
98
|
+
:fail,
|
99
|
+
:CheckGetByteUsed,
|
100
|
+
%q|set_byte_order(BYTE_ORDER_LITTLE_ENDIAN);| +
|
101
|
+
%q|get_dword(blob:blah, pos:10);|
|
102
|
+
)
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
################################################################################
|
2
|
+
# Copyright (c) 2011-2016, 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
|
+
|
27
|
+
class TestScriptDoesNotUseAuditDotInc < Test::Unit::TestCase
|
28
|
+
include Pedant::Test
|
29
|
+
|
30
|
+
def test_does
|
31
|
+
check(
|
32
|
+
:pass,
|
33
|
+
:CheckScriptDoesNotUseAuditDotInc,
|
34
|
+
%q|include("audit.inc");|+
|
35
|
+
%q|audit(AUDIT_hahaha,"really");|
|
36
|
+
)
|
37
|
+
check(
|
38
|
+
:pass,
|
39
|
+
:CheckScriptDoesNotUseAuditDotInc,
|
40
|
+
%q|include('audit.inc');|+
|
41
|
+
%q|audit(AUDIT_hahaha,"yeah really");|
|
42
|
+
)
|
43
|
+
end
|
44
|
+
|
45
|
+
def test_does_no_audit_call
|
46
|
+
check(
|
47
|
+
:warn,
|
48
|
+
:CheckScriptDoesNotUseAuditDotInc,
|
49
|
+
%q|include("audit.inc");|
|
50
|
+
)
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_unexpected
|
54
|
+
check(
|
55
|
+
:fail,
|
56
|
+
:CheckScriptDoesNotUseAuditDotInc,
|
57
|
+
%q|include('audit.inc');|+
|
58
|
+
%q|include("audit.inc");|
|
59
|
+
)
|
60
|
+
end
|
61
|
+
end
|