diff --git a/lib/json-schema/validator.rb b/lib/json-schema/validator.rb index dd27ac9a..0e029feb 100644 --- a/lib/json-schema/validator.rb +++ b/lib/json-schema/validator.rb @@ -145,6 +145,9 @@ def load_ref_schema(parent_schema,ref) end if Validator.schemas[uri.to_s].nil? + # After resolution against the parent schema this must be an absolute URI + message = 'Schema references must yield an absolute URI when resolved against the parent schema' + raise JSON::Schema::SchemaError.new(message) unless ['ftp', 'http', 'https'].include? uri.normalize.scheme schema = JSON::Schema.new(JSON::Validator.parse(open(uri.to_s.chomp('#')).read), uri, @options[:version]) Validator.add_schema(schema) build_schemas(schema) diff --git a/test/test_bad_schema_ref.rb b/test/test_bad_schema_ref.rb index 0f02c4b2..7dc52b9f 100644 --- a/test/test_bad_schema_ref.rb +++ b/test/test_bad_schema_ref.rb @@ -12,30 +12,24 @@ def teardown WebMock.disable_net_connect! end - def test_bad_uri_ref - schema = { + def test_resolved_relative_refs + schema_1 = { "$schema" => "http://json-schema.org/draft-04/schema#", "type" => "array", - "items" => { "$ref" => "../google.json"} + "items" => { "$ref" => "/etc/passwd"} } - data = [1,2,3] - assert_raises(Errno::ENOENT) do - JSON::Validator.validate(schema,data) - end - end - - def test_malicious_ref - schema = { + schema_2 = { "$schema" => "http://json-schema.org/draft-04/schema#", "type" => "array", "items" => { "$ref" => "../../../../../../../../../../../../etc/passwd"} } data = [1,2,3] - assert_raises(Errno::ENOENT) do - JSON::Validator.validate(schema,data) - end + message = 'Schema references must yield an absolute URI when resolved against the parent schema' + + assert_error(schema_1, data, JSON::Schema::SchemaError, message) + assert_error(schema_2, data, JSON::Schema::SchemaError, message) end def test_bad_host_ref diff --git a/test/test_helper.rb b/test/test_helper.rb index 962eeb38..a28d0621 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -33,4 +33,11 @@ def refute_valid(schema, data, options = {}) errors = JSON::Validator.fully_validate(schema, data, options) refute_equal([], errors, "#{data.inspect} should be invalid for schema:\n#{schema.inspect}") end + + def assert_error(schema, data, error_class, message = nil) + error = assert_raises(error_class) do + JSON::Validator.validate!(schema, data) + end + assert_equal(error.message, message) unless message.nil? + end end