puppet-lint-check_unsafe_interpolations 0.0.3 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1e90440a4433f82202315ae44353245ca75123974ba549af84cd46d47bc9b1b3
4
- data.tar.gz: 29e8dbe2d2e16fe3593dcc3ec4f1b7ef2d87b0d88df7b626086001e93562aeca
3
+ metadata.gz: 06bfbbbb77295091db599b90f1f6052b98b96e5b3d0d5ab3dc77526527739d56
4
+ data.tar.gz: e5861ad1c3ce71eef31c619fe6ec00f4edbd58df53741ec9c6e302516276d1bc
5
5
  SHA512:
6
- metadata.gz: 3e01934881a975c45ca0b2e874694fe8fa7dcde5c5ef83e67bce31fba3f27b630a35a9790ab380c6915790f22ae95d313d967bc6e7efbbe17047d1b6d0fa3adc
7
- data.tar.gz: 8acb71fac65eaa6389e70f821ef3c5eda2477c1de8265815ad9f703b7edfc506dce5ebcb5ff959e8c0494d8f3eb98d6e93c77ba1227574364ed94738fb346a38
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 interpolated?(token)
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 interpolated?(current_token)
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.rindex { |r| r.type == :DQPRE }
104
- title_end_idx = tokens.rindex { |r| r.type == :DQPOST }
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 interpolated?(token)
118
- INTERPOLATED_STRINGS.include?(token.type)
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
@@ -1,4 +1,4 @@
1
1
  # version of this gem
2
2
  class CheckUnsafeInterpolations
3
- VERSION ||= '0.0.3'.freeze
3
+ VERSION ||= '0.0.5'.freeze
4
4
  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(2).problems
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(msg)
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
@@ -1,3 +1,4 @@
1
1
  require 'puppet-lint'
2
+ require 'rspec/collection_matchers'
2
3
 
3
4
  PuppetLint::Plugins.load_spec_helper
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.3
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: 2022-12-09 00:00:00.000000000 Z
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: '1.0'
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.7'
51
+ version: '2.5'
58
52
  required_rubygems_version: !ruby/object:Gem::Requirement
59
53
  requirements:
60
54
  - - ">="