From 3d9172868ba15bf443c6017e6b5b22b5078fe902 Mon Sep 17 00:00:00 2001 From: Beth Skurrie Date: Tue, 13 Dec 2022 10:34:05 +1100 Subject: [PATCH] feat: do not allow JSON request bodies that are not Objects or Arrays --- .../api/resources/base_resource.rb | 8 +++++- .../api/resources/base_resource_spec.rb | 25 +++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/lib/pact_broker/api/resources/base_resource.rb b/lib/pact_broker/api/resources/base_resource.rb index 0f6dc1eb4..77cf0c2cc 100644 --- a/lib/pact_broker/api/resources/base_resource.rb +++ b/lib/pact_broker/api/resources/base_resource.rb @@ -120,11 +120,17 @@ def params(options = {}) return options[:default] if options.key?(:default) && request_body.empty? symbolize_names = !options.key?(:symbolize_names) || options[:symbolize_names] - if symbolize_names + parsed_params = if symbolize_names @params_with_symbol_keys ||= JSON.parse(request_body, { symbolize_names: true }.merge(PACT_PARSING_OPTIONS)) #Not load! Otherwise it will try to load Ruby classes. else @params_with_string_keys ||= JSON.parse(request_body, { symbolize_names: false }.merge(PACT_PARSING_OPTIONS)) #Not load! Otherwise it will try to load Ruby classes. end + + if !parsed_params.is_a?(Hash) && !parsed_params.is_a?(Array) + raise "Expected JSON Object in request body but found #{parsed_params.class.name}" + end + + parsed_params rescue StandardError => e raise InvalidJsonError.new(e.message) end diff --git a/spec/lib/pact_broker/api/resources/base_resource_spec.rb b/spec/lib/pact_broker/api/resources/base_resource_spec.rb index 6312dd355..dd977e2d6 100644 --- a/spec/lib/pact_broker/api/resources/base_resource_spec.rb +++ b/spec/lib/pact_broker/api/resources/base_resource_spec.rb @@ -65,6 +65,31 @@ def process_post end end + context "when a JSON string value is provided" do + let(:body_string) { "".to_json } + + it "raises an error, but maybe change this later if this should be allowed currently no resources accept strings" do + expect { subject.params }.to raise_error InvalidJsonError + end + end + + context "when a JSON number value is provided" do + let(:body_string) { 1.to_json } + + it "raises an error, but maybe change this later if this should be allowed currently no resources accept numbers" do + expect { subject.params }.to raise_error InvalidJsonError + end + end + + context "when a JSON array value is provided" do + let(:body_string) { [].to_json } + + it "allows this only because, for historical reasons, the pact publishing endpoint allows publishing contracts as arrays" do + # possibly from when the very very first pact format was just an array of interactions, with no top level object + expect(subject.params).to eq [] + end + end + context "when symbolize_names is not set" do it "symbolizes the names" do expect(subject.params.keys).to eq [:foo]