Skip to content

Commit bd24e3d

Browse files
authored
Merge pull request rails#51950 from zzak/51215-raise
Raise when using key which can't respond to `#to_sym` in EncryptedConfiguration
2 parents c9c3047 + 1571041 commit bd24e3d

File tree

3 files changed

+63
-2
lines changed

3 files changed

+63
-2
lines changed

activesupport/CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
* Raise when using key which can't respond to `#to_sym` in `EncryptedConfiguration`.
2+
3+
As is the case when trying to use an Integer or Float as a key, which is unsupported.
4+
5+
*zzak*
6+
17
* Deprecate addition and since between two `Time` and `ActiveSupport::TimeWithZone`.
28

39
Previously adding time instances together such as `10.days.ago + 10.days.ago` or `10.days.ago.since(10.days.ago)` produced a nonsensical future date. This behavior is deprecated and will be removed in Rails 8.1.

activesupport/lib/active_support/encrypted_configuration.rb

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,12 @@ def message
4343
end
4444
end
4545

46+
class InvalidKeyError < RuntimeError
47+
def initialize(content_path, key)
48+
super "Key '#{key}' is invalid, it must respond to '#to_sym' from configuration in '#{content_path}'."
49+
end
50+
end
51+
4652
delegate_missing_to :options
4753

4854
def initialize(config_path:, key_path:, env_key:, raise_if_missing_key:)
@@ -61,7 +67,11 @@ def read
6167
end
6268

6369
def validate! # :nodoc:
64-
deserialize(read)
70+
deserialize(read).each_key do |key|
71+
key.to_sym
72+
rescue NoMethodError
73+
raise InvalidKeyError.new(content_path, key)
74+
end
6575
end
6676

6777
# Returns the decrypted content as a Hash with symbolized keys.
@@ -73,14 +83,23 @@ def validate! # :nodoc:
7383
# # => { some_secret: 123, some_namespace: { another_secret: 789 } }
7484
#
7585
def config
76-
@config ||= deserialize(read).deep_symbolize_keys
86+
@config ||= deep_symbolize_keys(deserialize(read))
7787
end
7888

7989
def inspect # :nodoc:
8090
"#<#{self.class.name}:#{'%#016x' % (object_id << 1)}>"
8191
end
8292

8393
private
94+
def deep_symbolize_keys(hash)
95+
hash.deep_symbolize_keys
96+
hash.deep_transform_keys do |key|
97+
key.to_sym
98+
rescue NoMethodError
99+
raise InvalidKeyError.new(content_path, key)
100+
end
101+
end
102+
84103
def deep_transform(hash)
85104
return hash unless hash.is_a?(Hash)
86105

activesupport/test/encrypted_configuration_test.rb

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,42 @@ class EncryptedConfigurationTest < ActiveSupport::TestCase
9393
end
9494
end
9595

96+
test "raises helpful error when loading invalid content with unsupported keys" do
97+
@credentials.write("42: value")
98+
99+
assert_raise(ActiveSupport::EncryptedConfiguration::InvalidKeyError, match: /Key '42' is invalid, it must respond to '#to_sym' from configuration in '#{@credentials_config_path}'./) do
100+
@credentials.config
101+
end
102+
103+
@credentials.write("42.0: value")
104+
assert_raise(ActiveSupport::EncryptedConfiguration::InvalidKeyError, match: /Key '42.0' is invalid, it must respond to '#to_sym' from configuration in '#{@credentials_config_path}'./) do
105+
@credentials.config
106+
end
107+
108+
@credentials.write("Off: value")
109+
assert_raise(ActiveSupport::EncryptedConfiguration::InvalidKeyError, match: /Key 'false' is invalid, it must respond to '#to_sym' from configuration in '#{@credentials_config_path}'./) do
110+
@credentials.config
111+
end
112+
end
113+
114+
test "raises helpful error when validating invalid content with unsupported keys" do
115+
@credentials.write("42: value")
116+
117+
assert_raise(ActiveSupport::EncryptedConfiguration::InvalidKeyError, match: /Key '42' is invalid, it must respond to '#to_sym' from configuration in '#{@credentials_config_path}'./) do
118+
@credentials.validate!
119+
end
120+
121+
@credentials.write("42.0: value")
122+
assert_raise(ActiveSupport::EncryptedConfiguration::InvalidKeyError, match: /Key '42.0' is invalid, it must respond to '#to_sym' from configuration in '#{@credentials_config_path}'./) do
123+
@credentials.validate!
124+
end
125+
126+
@credentials.write("Off: value")
127+
assert_raise(ActiveSupport::EncryptedConfiguration::InvalidKeyError, match: /Key 'false' is invalid, it must respond to '#to_sym' from configuration in '#{@credentials_config_path}'./) do
128+
@credentials.validate!
129+
end
130+
end
131+
96132
test "raises key error when accessing config via bang method" do
97133
assert_raise(KeyError) { @credentials.something! }
98134
end

0 commit comments

Comments
 (0)