puppet-lint-check_unsafe_interpolations 0.0.3 → 0.0.5
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
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 06bfbbbb77295091db599b90f1f6052b98b96e5b3d0d5ab3dc77526527739d56
|
4
|
+
data.tar.gz: e5861ad1c3ce71eef31c619fe6ec00f4edbd58df53741ec9c6e302516276d1bc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3fff01f49a697082783b3ea9b6eab8fe92c26e10ddbe8c981eaac0dce1d733166903201f8f7ee438401453fd0096e2c571d5dabd9a5da12163d6a08cec5c306c
|
7
|
+
data.tar.gz: 0fe2a37dda1149d9396371c0eff81048845253cbb94b7badfd91c25c0496b5e10a3240a653b5fe494cba74a16002569b7df6292f936b7f34c8b1bebb240d0ecc
|
@@ -22,10 +22,10 @@ PuppetLint.new_check(:check_unsafe_interpolations) do
|
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
25
|
-
# Iterate over the tokens in a title and raise a warning if an interpolated variable is found
|
25
|
+
# Iterate over the tokens in a title and raise a warning if an unsafe interpolated variable is found
|
26
26
|
def check_unsafe_title(title)
|
27
27
|
title.each do |token|
|
28
|
-
notify_warning(token.next_code_token) if
|
28
|
+
notify_warning(token.next_code_token) if unsafe_interpolated?(token)
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
@@ -33,7 +33,7 @@ PuppetLint.new_check(:check_unsafe_interpolations) do
|
|
33
33
|
def check_unsafe_interpolations(command_resources)
|
34
34
|
command_resources[:tokens].each do |token|
|
35
35
|
# Skip iteration if token isn't a command of type :NAME
|
36
|
-
next unless COMMANDS.include?(token.value) && token.type == :NAME
|
36
|
+
next unless COMMANDS.include?(token.value) && (token.type == :NAME || token.type == :UNLESS)
|
37
37
|
# Don't check the command if it is parameterised
|
38
38
|
next if parameterised?(token)
|
39
39
|
|
@@ -60,7 +60,7 @@ PuppetLint.new_check(:check_unsafe_interpolations) do
|
|
60
60
|
# Iterate through tokens in command
|
61
61
|
while current_token.type != :NEWLINE
|
62
62
|
# Check if token is a varibale and if it is parameterised
|
63
|
-
rule_violations.append(current_token.next_code_token) if
|
63
|
+
rule_violations.append(current_token.next_code_token) if unsafe_interpolated?(current_token)
|
64
64
|
current_token = current_token.next_token
|
65
65
|
end
|
66
66
|
|
@@ -78,7 +78,7 @@ PuppetLint.new_check(:check_unsafe_interpolations) do
|
|
78
78
|
end
|
79
79
|
|
80
80
|
# This function is a replacement for puppet_lint's title_tokens function which assumes titles have single quotes
|
81
|
-
# This function adds a check for titles in double quotes where there could be interpolated variables
|
81
|
+
# This function adds a check for titles in double quotes where there could be unsafe interpolated variables
|
82
82
|
def get_exec_titles
|
83
83
|
result = []
|
84
84
|
tokens.each_index do |token_idx|
|
@@ -100,8 +100,8 @@ PuppetLint.new_check(:check_unsafe_interpolations) do
|
|
100
100
|
# Check if title is double quotes string
|
101
101
|
elsif tokens[token_idx].next_code_token.next_code_token.type == :DQPRE
|
102
102
|
# Find the start and end of the title
|
103
|
-
title_start_idx = tokens.
|
104
|
-
title_end_idx =
|
103
|
+
title_start_idx = tokens.find_index(tokens[token_idx].next_code_token.next_code_token)
|
104
|
+
title_end_idx = title_start_idx + index_offset_for(':', tokens[title_start_idx..tokens.length])
|
105
105
|
|
106
106
|
result << tokens[title_start_idx..title_end_idx]
|
107
107
|
# Title is in single quotes
|
@@ -114,7 +114,60 @@ PuppetLint.new_check(:check_unsafe_interpolations) do
|
|
114
114
|
result
|
115
115
|
end
|
116
116
|
|
117
|
-
def
|
118
|
-
|
117
|
+
def find_closing_brack(token)
|
118
|
+
while (token = token.next_code_token)
|
119
|
+
case token.type
|
120
|
+
when :RBRACK
|
121
|
+
return token
|
122
|
+
when :LBRACK
|
123
|
+
token = find_closing_brack(token)
|
124
|
+
end
|
125
|
+
end
|
126
|
+
raise 'not reached'
|
127
|
+
end
|
128
|
+
|
129
|
+
def find_closing_paren(token)
|
130
|
+
while (token = token.next_code_token)
|
131
|
+
case token.type
|
132
|
+
when :RPAREN
|
133
|
+
return token
|
134
|
+
when :LPAREN
|
135
|
+
token = find_closing_paren(token)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
raise 'not reached'
|
139
|
+
end
|
140
|
+
|
141
|
+
def unsafe_interpolated?(token)
|
142
|
+
# XXX: Since stdlib 9.0.0 'shell_escape' is deprecated in favor or 'stdlib::shell_escape'
|
143
|
+
# When the shell_escape function is removed from stdlib, we want to remove it bellow.
|
144
|
+
return false unless INTERPOLATED_STRINGS.include?(token.type)
|
145
|
+
|
146
|
+
token = token.next_code_token
|
147
|
+
|
148
|
+
if token.type == :FUNCTION_NAME && ['shell_escape', 'stdlib::shell_escape'].include?(token.value)
|
149
|
+
token = token.next_code_token
|
150
|
+
token = find_closing_paren(token).next_code_token if token.type == :LPAREN
|
151
|
+
return ![:DQPOST, :DQMID].include?(token.type)
|
152
|
+
elsif token.type == :VARIABLE
|
153
|
+
token = token.next_code_token
|
154
|
+
token = find_closing_brack(token).next_code_token if token.type == :LBRACK
|
155
|
+
if token.type == :DOT && [:NAME, :FUNCTION_NAME].include?(token.next_code_token.type) && ['shell_escape', 'stdlib::shell_escape'].include?(token.next_code_token.value)
|
156
|
+
token = token.next_code_token.next_code_token
|
157
|
+
token = find_closing_paren(token).next_code_token if token.type == :LPAREN
|
158
|
+
return ![:DQPOST, :DQMID].include?(token.type)
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
true
|
163
|
+
end
|
164
|
+
|
165
|
+
# Finds the index offset of the next instance of `value` in `tokens_slice` from the original index
|
166
|
+
def index_offset_for(value, tokens_slice)
|
167
|
+
i = 0
|
168
|
+
while i < tokens_slice.length
|
169
|
+
return i if value.include?(tokens_slice[i].value)
|
170
|
+
i += 1
|
171
|
+
end
|
119
172
|
end
|
120
173
|
end
|
@@ -33,6 +33,8 @@ describe 'check_unsafe_interpolations' do
|
|
33
33
|
|
34
34
|
exec { 'bar':
|
35
35
|
command => "echo ${foo} ${bar}",
|
36
|
+
onlyif => "${baz}",
|
37
|
+
unless => "${bazz}",
|
36
38
|
}
|
37
39
|
|
38
40
|
}
|
@@ -40,12 +42,14 @@ describe 'check_unsafe_interpolations' do
|
|
40
42
|
end
|
41
43
|
|
42
44
|
it 'detects multiple unsafe exec command arguments' do
|
43
|
-
expect(problems).to have(
|
45
|
+
expect(problems).to have(4).problems
|
44
46
|
end
|
45
47
|
|
46
48
|
it 'creates two warnings' do
|
47
49
|
expect(problems).to contain_warning(msg)
|
48
|
-
expect(problems).to contain_warning(
|
50
|
+
expect(problems).to contain_warning("unsafe interpolation of variable 'bar' in exec command")
|
51
|
+
expect(problems).to contain_warning("unsafe interpolation of variable 'baz' in exec command")
|
52
|
+
expect(problems).to contain_warning("unsafe interpolation of variable 'bazz' in exec command")
|
49
53
|
end
|
50
54
|
end
|
51
55
|
|
@@ -87,6 +91,44 @@ describe 'check_unsafe_interpolations' do
|
|
87
91
|
end
|
88
92
|
end
|
89
93
|
|
94
|
+
context 'exec with shell escaped string in command' do
|
95
|
+
let(:code) do
|
96
|
+
<<-PUPPET
|
97
|
+
class foo {
|
98
|
+
|
99
|
+
exec { 'bar':
|
100
|
+
command => "echo ${foo.stdlib::shell_escape} ${bar.stdlib::shell_escape()}",
|
101
|
+
onlyif => "${bar[1].stdlib::shell_escape}",
|
102
|
+
unless => "[ -x ${stdlib::shell_escape(reticulate($baz))} ]",
|
103
|
+
}
|
104
|
+
}
|
105
|
+
PUPPET
|
106
|
+
end
|
107
|
+
|
108
|
+
it 'detects zero problems' do
|
109
|
+
expect(problems).to have(0).problems
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
context 'exec with post-processed shell escaped string in command' do
|
114
|
+
let(:code) do
|
115
|
+
<<-PUPPET
|
116
|
+
class foo {
|
117
|
+
|
118
|
+
exec { 'bar':
|
119
|
+
command => "echo ${reticulate(foo.stdlib::shell_escape)} ${bar.stdlib::shell_escape().reticulate}",
|
120
|
+
onlyif => "${bar[1].stdlib::shell_escape.reticulate()}",
|
121
|
+
unless => "[ -x ${reticulate(stdlib::shell_escape($baz))} ]",
|
122
|
+
}
|
123
|
+
}
|
124
|
+
PUPPET
|
125
|
+
end
|
126
|
+
|
127
|
+
it 'detects zero problems' do
|
128
|
+
expect(problems).to have(4).problems
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
90
132
|
context 'exec that has an array of args in command' do
|
91
133
|
let(:code) do
|
92
134
|
<<-PUPPET
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,35 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: puppet-lint-check_unsafe_interpolations
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Puppet, Inc.
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-05-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: puppet-lint
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
20
|
-
- - "<"
|
21
|
-
- !ruby/object:Gem::Version
|
22
|
-
version: '4'
|
19
|
+
version: '4.0'
|
23
20
|
type: :runtime
|
24
21
|
prerelease: false
|
25
22
|
version_requirements: !ruby/object:Gem::Requirement
|
26
23
|
requirements:
|
27
|
-
- - "
|
28
|
-
- !ruby/object:Gem::Version
|
29
|
-
version: '1.0'
|
30
|
-
- - "<"
|
24
|
+
- - "~>"
|
31
25
|
- !ruby/object:Gem::Version
|
32
|
-
version: '4'
|
26
|
+
version: '4.0'
|
33
27
|
description: " A puppet-lint plugin to check for unsafe interpolations.\n"
|
34
28
|
email:
|
35
29
|
executables: []
|
@@ -54,7 +48,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
54
48
|
requirements:
|
55
49
|
- - ">="
|
56
50
|
- !ruby/object:Gem::Version
|
57
|
-
version: '2.
|
51
|
+
version: '2.5'
|
58
52
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
59
53
|
requirements:
|
60
54
|
- - ">="
|