Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed: Vault warns when valid JSON contains special character sequences #416

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 0 additions & 38 deletions lib/chef/knife/mixin/helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -39,48 +39,10 @@ def values_from_file(file)
end

def values_from_json(json)
validate_json(json)
JSON.parse(json)
rescue JSON::ParserError
raise JSON::ParserError, "#{json} is not valid JSON!"
end

# I/P: json string
# Raises `InvalidValue` if any of the json's values contain non-printable characters.
def validate_json(json)
begin
parsed_json = JSON.parse(json)
rescue JSON::ParserError
raise ChefVault::Exceptions::InvalidValue, "#{json} is not valid JSON!"
end

check_value(parsed_json) # Start checking from the root of the parsed JSON
end

def check_value(value, parent_key = nil)
if value.is_a?(Array)
value.each { |item| check_value(item, parent_key) }
elsif value.is_a?(Hash)
value.each do |key, nested_value|
next if key == "password" # Skip the password key

check_value(nested_value, key)
end
else
unless printable?(value.to_s)
msg = "Value '#{value}' of key '#{parent_key}' contains non-printable characters."
ChefVault::Log.warn(msg)
end
end
end

# I/P: String
# O/P: true/false
# returns true if string is free of non-printable characters (escape sequences)
# this returns false for whitespace escape sequences as well, e.g. \n\t
def printable?(string)
!/[[:^print:]]/.match?(string) # Returns true if the string is printable
end
end
end
end
34 changes: 22 additions & 12 deletions spec/chef/helper_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,34 @@
RSpec.describe ChefVault::Mixin::Helper do
include ChefVault::Mixin::Helper

let(:json) { { "username": "root" } }
let(:json_data) { '{"username": "root", "password": "abcabc"}' }
let(:buggy_json_data) { '{"username": "root", "password": "abc\abc"' }
before do
allow(ChefVault::Log).to receive(:warn)
end

let(:json_base) { { "username": "root" } }
let(:valid_json) { '{"username": "root", "password": "abcabc"}' }
let(:malformed_json) { '{"username": ' }
let(:valid_json_with_special_character) { { "Data": "Null->\u0000<-Byte" } }

describe "#validate_json" do
it "Raises InvalidValue Exception when invalid data provided" do
expect { validate_json(buggy_json_data) }.to raise_error(ChefVault::Exceptions::InvalidValue)
describe "#values_from_json" do
it "should raise error when invalid JSON provided" do
expect { values_from_json(malformed_json) }.to raise_error(JSON::ParserError)
end

it "Not to raise error if valid data provided" do
expect { validate_json(json_data) }.to_not raise_error
it "should not raise error when valid JSON provided" do
expect { values_from_json(valid_json) }.to_not raise_error
end

it "not to raise error if data consist of tab/new line OR space" do
%w{abc\tabc abc\nabc}.each do |pass|
json_data_with_slash = json.merge("password": pass)
expect { validate_json(json_data_with_slash.to_json) }.to_not raise_error
it "should not raise error if JSON contains tab, newline, or space characters" do
["abc\tabc", "abc\nabc", "abc abc"].each do |pass|
json_data_with_slash = json_base.merge("password": pass)
expect { values_from_json(json_data_with_slash.to_json) }.to_not raise_error
end
end

it "should not warn or error when JSON contains special character sequences" do
expect(ChefVault::Log).to_not receive(:warn)
expect { values_from_json(valid_json_with_special_character.to_json) }.to_not raise_error
end
end
end
Loading