Skip to content

Commit d804782

Browse files
committed
Reject directory traversal in store report processor
1 parent 34b9c0b commit d804782

File tree

2 files changed

+41
-6
lines changed

2 files changed

+41
-6
lines changed

Diff for: lib/puppet/reports/store.rb

+13-6
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
require 'fileutils'
33
require 'tempfile'
44

5+
SEPARATOR = [Regexp.escape(File::SEPARATOR.to_s), Regexp.escape(File::ALT_SEPARATOR.to_s)].join
6+
57
Puppet::Reports.register_report(:store) do
68
desc "Store the yaml report on disk. Each host sends its report as a YAML dump
79
and this just stores the file on disk, in the `reportdir` directory.
@@ -13,9 +15,11 @@
1315
def process
1416
# We don't want any tracking back in the fs. Unlikely, but there
1517
# you go.
16-
client = self.host.gsub("..",".")
18+
if host =~ Regexp.union(/[#{SEPARATOR}]/, /\A\.\.?\Z/)
19+
raise ArgumentError, "Invalid node name #{host.inspect}"
20+
end
1721

18-
dir = File.join(Puppet[:reportdir], client)
22+
dir = File.join(Puppet[:reportdir], host)
1923

2024
if ! FileTest.exists?(dir)
2125
FileUtils.mkdir_p(dir)
@@ -42,17 +46,20 @@ def process
4246
FileUtils.mv(f.path, file)
4347
rescue => detail
4448
puts detail.backtrace if Puppet[:trace]
45-
Puppet.warning "Could not write report for #{client} at #{file}: #{detail}"
49+
Puppet.warning "Could not write report for #{host} at #{file}: #{detail}"
4650
end
4751

4852
# Only testing cares about the return value
4953
file
5054
end
5155

52-
# removes all reports for a given host
56+
# removes all reports for a given host?
5357
def self.destroy(host)
54-
client = host.gsub("..",".")
55-
dir = File.join(Puppet[:reportdir], client)
58+
if host =~ Regexp.union(/[#{SEPARATOR}]/, /\A\.\.?\Z/)
59+
raise ArgumentError, "Invalid node name #{host.inspect}"
60+
end
61+
62+
dir = File.join(Puppet[:reportdir], host)
5663

5764
if File.exists?(dir)
5865
Dir.entries(dir).each do |file|

Diff for: spec/unit/reports/store_spec.rb

+28
Original file line numberDiff line numberDiff line change
@@ -44,5 +44,33 @@
4444
FileUtils.expects(:mv).in_sequence(writeseq).with(File.join(Dir.tmpdir, "foo123"), File.join(Puppet[:reportdir], @report.host, "201101061200.yaml"))
4545
@report.process
4646
end
47+
48+
['..', 'hello/', '/hello', 'he/llo', 'hello/..', '.'].each do |node|
49+
it "rejects #{node.inspect}" do
50+
@report.host = node
51+
expect { @report.process }.to raise_error(ArgumentError, /Invalid node/)
52+
end
53+
end
54+
55+
['.hello', 'hello.', '..hi', 'hi..'].each do |node|
56+
it "accepts #{node.inspect}" do
57+
@report.host = node
58+
@report.process
59+
end
60+
end
61+
end
62+
63+
describe "::destroy" do
64+
['..', 'hello/', '/hello', 'he/llo', 'hello/..', '.'].each do |node|
65+
it "rejects #{node.inspect}" do
66+
expect { processor.destroy(node) }.to raise_error(ArgumentError, /Invalid node/)
67+
end
68+
end
69+
70+
['.hello', 'hello.', '..hi', 'hi..'].each do |node|
71+
it "accepts #{node.inspect}" do
72+
processor.destroy(node)
73+
end
74+
end
4775
end
4876
end

0 commit comments

Comments
 (0)