From dbca8c0e5ab083588ac1a6aae9362ef32cb95065 Mon Sep 17 00:00:00 2001 From: Josh Cooper Date: Fri, 28 Apr 2017 12:09:11 -0700 Subject: [PATCH] (PUP-7483) Reject all fact formats except PSON Previously, an authenticated user could cause the master to execute YAML.load on user-specified input, as well as MessagePack.unpack if the msgpack gem was installed. Since 3.2.2, agents have always sent facts as PSON. There is no reason to support other formats, so reject all fact formats except PSON. (cherry picked from commit 06d8c51367ca932b9da5d9b01958cfc0adf0f2ea) --- lib/puppet/indirector/catalog/compiler.rb | 6 +++-- spec/unit/indirector/catalog/compiler_spec.rb | 36 ++++++++++++++++++++++++--- 2 files changed, 36 insertions(+), 6 deletions(-) diff --git a/lib/puppet/indirector/catalog/compiler.rb b/lib/puppet/indirector/catalog/compiler.rb index 6f4e2f3e4..ed2c3bc39 100644 --- a/lib/puppet/indirector/catalog/compiler.rb +++ b/lib/puppet/indirector/catalog/compiler.rb @@ -22,9 +22,11 @@ class Puppet::Resource::Catalog::Compiler < Puppet::Indirector::Code # in Network::HTTP::Handler will automagically deserialize the value. if text_facts.is_a?(Puppet::Node::Facts) facts = text_facts - else + elsif format == 'pson' # We unescape here because the corresponding code in Puppet::Configurer::FactHandler escapes - facts = Puppet::Node::Facts.convert_from(format, CGI.unescape(text_facts)) + facts = Puppet::Node::Facts.convert_from('pson', CGI.unescape(text_facts)) + else + raise ArgumentError, "Unsupported facts format" end unless facts.name == request.key diff --git a/spec/unit/indirector/catalog/compiler_spec.rb b/spec/unit/indirector/catalog/compiler_spec.rb index 4aaecd664..faf95f757 100755 --- a/spec/unit/indirector/catalog/compiler_spec.rb +++ b/spec/unit/indirector/catalog/compiler_spec.rb @@ -138,10 +138,10 @@ describe Puppet::Resource::Catalog::Compiler do @facts = Puppet::Node::Facts.new('hostname', "fact" => "value", "architecture" => "i386") end - def a_request_that_contains(facts) + def a_request_that_contains(facts, format = :pson) request = Puppet::Indirector::Request.new(:catalog, :find, "hostname", nil) - request.options[:facts_format] = "pson" - request.options[:facts] = CGI.escape(facts.render(:pson)) + request.options[:facts_format] = format.to_s + request.options[:facts] = CGI.escape(facts.render(format)) request end @@ -163,7 +163,7 @@ describe Puppet::Resource::Catalog::Compiler do facts.timestamp.should == now end - it "should convert the facts into a fact instance and save it" do + it "accepts PSON facts" do request = a_request_that_contains(@facts) options = { @@ -175,6 +175,34 @@ describe Puppet::Resource::Catalog::Compiler do @compiler.extract_facts_from_request(request) end + + it "rejects YAML facts" do + request = a_request_that_contains(@facts, :yaml) + + options = { + :environment => request.environment, + :transaction_uuid => request.options[:transaction_uuid], + } + + expect { + @compiler.extract_facts_from_request(request) + }.to raise_error(ArgumentError, /Unsupported facts format/) + end + + it "rejects unknown fact formats" do + request = a_request_that_contains(@facts) + request.options[:facts_format] = 'unknown-format' + + options = { + :environment => request.environment, + :transaction_uuid => request.options[:transaction_uuid], + } + + expect { + @compiler.extract_facts_from_request(request) + }.to raise_error(ArgumentError, /Unsupported facts format/) + end + end describe "when finding nodes" do