From 1139087e071c971308d107352cc41219710886c9 Mon Sep 17 00:00:00 2001 From: Lucas McDonald Date: Mon, 27 Jul 2026 17:40:33 +0000 Subject: [PATCH 1/6] fix: return a decryption error for malformed material description --- gems/aws-sdk-s3/CHANGELOG.md | 2 ++ .../encryptionV2/kms_cipher_provider.rb | 9 +++++- .../encryptionV2/kms_cipher_provider_spec.rb | 29 +++++++++++++++++++ 3 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 gems/aws-sdk-s3/spec/encryptionV2/kms_cipher_provider_spec.rb diff --git a/gems/aws-sdk-s3/CHANGELOG.md b/gems/aws-sdk-s3/CHANGELOG.md index 2385d906d8e..6c2443440c9 100644 --- a/gems/aws-sdk-s3/CHANGELOG.md +++ b/gems/aws-sdk-s3/CHANGELOG.md @@ -1,6 +1,8 @@ Unreleased Changes ------------------ +* Issue - Return a decryption error for a malformed material description. + 1.228.1 (2026-07-23) ------------------ diff --git a/gems/aws-sdk-s3/lib/aws-sdk-s3/encryptionV2/kms_cipher_provider.rb b/gems/aws-sdk-s3/lib/aws-sdk-s3/encryptionV2/kms_cipher_provider.rb index 65970395b8c..1caa93ff177 100644 --- a/gems/aws-sdk-s3/lib/aws-sdk-s3/encryptionV2/kms_cipher_provider.rb +++ b/gems/aws-sdk-s3/lib/aws-sdk-s3/encryptionV2/kms_cipher_provider.rb @@ -50,7 +50,7 @@ def encryption_cipher(options = {}) # @return [Cipher] Given an encryption envelope, returns a # decryption cipher. def decryption_cipher(envelope, options = {}) - encryption_context = Json.load(envelope['x-amz-matdesc']) + encryption_context = extract_encryption_context(envelope['x-amz-matdesc']) cek_alg = envelope['x-amz-cek-alg'] case envelope['x-amz-wrap-alg'] @@ -115,6 +115,13 @@ def decryption_cipher(envelope, options = {}) private + # Raise a decryption error for a malformed material description. + def extract_encryption_context(matdesc) + Json.load(matdesc) + rescue Aws::Json::ParseError, EncodingError + raise Errors::DecryptionError, 'Malformed material description' + end + def validate_key_wrap(key_wrap_schema) case key_wrap_schema when :kms_context then 'kms+context' diff --git a/gems/aws-sdk-s3/spec/encryptionV2/kms_cipher_provider_spec.rb b/gems/aws-sdk-s3/spec/encryptionV2/kms_cipher_provider_spec.rb new file mode 100644 index 00000000000..9396e81bb6f --- /dev/null +++ b/gems/aws-sdk-s3/spec/encryptionV2/kms_cipher_provider_spec.rb @@ -0,0 +1,29 @@ +require_relative '../spec_helper' + +module Aws + module S3 + module EncryptionV2 + describe KmsCipherProvider do + let(:provider) do + KmsCipherProvider.new( + kms_key_id: 'kms-key-id', + kms_client: KMS::Client.new(stub_responses: true), + key_wrap_schema: :kms_context, + content_encryption_schema: :aes_gcm_no_padding + ) + end + + describe '#decryption_cipher' do + # A malformed material description raises DecryptionError. + ["abc\xFF", '=?utf-8?B?gA==?='].each do |matdesc| + it "raises DecryptionError (#{matdesc.inspect})" do + expect do + provider.decryption_cipher('x-amz-matdesc' => matdesc) + end.to raise_error(Errors::DecryptionError, /Malformed material description/) + end + end + end + end + end + end +end From 4dc45d564e3d456e7429b4db0a171c0803844773 Mon Sep 17 00:00:00 2001 From: Lucas McDonald Date: Mon, 27 Jul 2026 18:13:10 +0000 Subject: [PATCH 2/6] fix: treat non-object or absent material descriptions as malformed extract_encryption_context now raises Errors::DecryptionError when the material description parses to a non-Hash JSON value (e.g. [], true, "str", 123) or is absent, instead of leaking a downstream TypeError or NoMethodError from encryption context handling. --- .../aws-sdk-s3/encryptionV2/kms_cipher_provider.rb | 10 ++++++++-- .../spec/encryptionV2/kms_cipher_provider_spec.rb | 14 ++++++++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/gems/aws-sdk-s3/lib/aws-sdk-s3/encryptionV2/kms_cipher_provider.rb b/gems/aws-sdk-s3/lib/aws-sdk-s3/encryptionV2/kms_cipher_provider.rb index 1caa93ff177..edeaca5aba8 100644 --- a/gems/aws-sdk-s3/lib/aws-sdk-s3/encryptionV2/kms_cipher_provider.rb +++ b/gems/aws-sdk-s3/lib/aws-sdk-s3/encryptionV2/kms_cipher_provider.rb @@ -115,9 +115,15 @@ def decryption_cipher(envelope, options = {}) private - # Raise a decryption error for a malformed material description. + # Raise a decryption error for a malformed material description. A + # material description must be a JSON object. def extract_encryption_context(matdesc) - Json.load(matdesc) + context = Json.load(matdesc) if matdesc.is_a?(String) + unless context.is_a?(Hash) + raise Errors::DecryptionError, 'Malformed material description' + end + + context rescue Aws::Json::ParseError, EncodingError raise Errors::DecryptionError, 'Malformed material description' end diff --git a/gems/aws-sdk-s3/spec/encryptionV2/kms_cipher_provider_spec.rb b/gems/aws-sdk-s3/spec/encryptionV2/kms_cipher_provider_spec.rb index 9396e81bb6f..adac384a00f 100644 --- a/gems/aws-sdk-s3/spec/encryptionV2/kms_cipher_provider_spec.rb +++ b/gems/aws-sdk-s3/spec/encryptionV2/kms_cipher_provider_spec.rb @@ -22,6 +22,20 @@ module EncryptionV2 end.to raise_error(Errors::DecryptionError, /Malformed material description/) end end + + # Valid JSON that isn't an object, or an absent matdesc, is malformed. + ['[]', 'true', '"str"', '123', nil].each do |matdesc| + it "raises DecryptionError (#{matdesc.inspect})" do + envelope = { + 'x-amz-matdesc' => matdesc, + 'x-amz-wrap-alg' => 'kms+context', + 'x-amz-cek-alg' => 'AES/GCM/NoPadding' + } + expect do + provider.decryption_cipher(envelope) + end.to raise_error(Errors::DecryptionError, /Malformed material description/) + end + end end end end From 17a325b2a2e1f34af5b5adf693ace2db6aa98dec Mon Sep 17 00:00:00 2001 From: Lucas McDonald Date: Mon, 27 Jul 2026 19:49:41 +0000 Subject: [PATCH 3/6] fix: return a decryption error for malformed material description on the V3 path --- .../encryptionV3/kms_cipher_provider.rb | 9 +++++- .../encryptionv3/kms_cipher_provider_spec.rb | 29 +++++++++++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 gems/aws-sdk-s3/spec/encryptionv3/kms_cipher_provider_spec.rb diff --git a/gems/aws-sdk-s3/lib/aws-sdk-s3/encryptionV3/kms_cipher_provider.rb b/gems/aws-sdk-s3/lib/aws-sdk-s3/encryptionV3/kms_cipher_provider.rb index 38c61240c62..43f6d0a0e13 100644 --- a/gems/aws-sdk-s3/lib/aws-sdk-s3/encryptionV3/kms_cipher_provider.rb +++ b/gems/aws-sdk-s3/lib/aws-sdk-s3/encryptionV3/kms_cipher_provider.rb @@ -54,7 +54,7 @@ def decryption_cipher(envelope, options = {}) cek_alg = envelope['x-amz-c'] encryption_context = if !envelope['x-amz-t'].nil? - Json.load(envelope['x-amz-t']) + extract_encryption_context(envelope['x-amz-t']) else ##= ../specification/s3-encryption/data-format/content-metadata.md#v3-only ##% If the mapkey x-amz-t is not present, the default Material Description value MUST be set to an empty map (`{}`). @@ -102,6 +102,13 @@ def decryption_cipher(envelope, options = {}) private + # Raise a decryption error for a malformed material description. + def extract_encryption_context(matdesc) + Json.load(matdesc) + rescue Aws::Json::ParseError, EncodingError + raise Errors::DecryptionError, 'Malformed material description' + end + def validate_key_wrap(key_wrap_schema) case key_wrap_schema when :kms_context then '12' diff --git a/gems/aws-sdk-s3/spec/encryptionv3/kms_cipher_provider_spec.rb b/gems/aws-sdk-s3/spec/encryptionv3/kms_cipher_provider_spec.rb new file mode 100644 index 00000000000..c7651f80785 --- /dev/null +++ b/gems/aws-sdk-s3/spec/encryptionv3/kms_cipher_provider_spec.rb @@ -0,0 +1,29 @@ +require_relative '../spec_helper' + +module Aws + module S3 + module EncryptionV3 + describe KmsCipherProvider do + let(:provider) do + KmsCipherProvider.new( + kms_key_id: 'kms-key-id', + kms_client: KMS::Client.new(stub_responses: true), + key_wrap_schema: :kms_context, + content_encryption_schema: :alg_aes_256_gcm_hkdf_sha512_commit_key + ) + end + + describe '#decryption_cipher' do + # A malformed material description raises DecryptionError. + ["abc\xFF", '=?utf-8?B?gA==?='].each do |matdesc| + it "raises DecryptionError (#{matdesc.inspect})" do + expect do + provider.decryption_cipher('x-amz-w' => '12', 'x-amz-t' => matdesc) + end.to raise_error(Errors::DecryptionError, /Malformed material description/) + end + end + end + end + end + end +end From c84e5dfc1d2fb4c2009030ed5015c36f8ef04eb6 Mon Sep 17 00:00:00 2001 From: Lucas McDonald Date: Mon, 27 Jul 2026 19:55:56 +0000 Subject: [PATCH 4/6] fix: reject non-object material descriptions on the V3 path --- .../lib/aws-sdk-s3/encryptionV3/kms_cipher_provider.rb | 7 ++++++- .../spec/encryptionv3/kms_cipher_provider_spec.rb | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/gems/aws-sdk-s3/lib/aws-sdk-s3/encryptionV3/kms_cipher_provider.rb b/gems/aws-sdk-s3/lib/aws-sdk-s3/encryptionV3/kms_cipher_provider.rb index 43f6d0a0e13..f5458a26ebe 100644 --- a/gems/aws-sdk-s3/lib/aws-sdk-s3/encryptionV3/kms_cipher_provider.rb +++ b/gems/aws-sdk-s3/lib/aws-sdk-s3/encryptionV3/kms_cipher_provider.rb @@ -104,7 +104,12 @@ def decryption_cipher(envelope, options = {}) # Raise a decryption error for a malformed material description. def extract_encryption_context(matdesc) - Json.load(matdesc) + context = Json.load(matdesc) if matdesc.is_a?(String) + unless context.is_a?(Hash) + raise Errors::DecryptionError, 'Malformed material description' + end + + context rescue Aws::Json::ParseError, EncodingError raise Errors::DecryptionError, 'Malformed material description' end diff --git a/gems/aws-sdk-s3/spec/encryptionv3/kms_cipher_provider_spec.rb b/gems/aws-sdk-s3/spec/encryptionv3/kms_cipher_provider_spec.rb index c7651f80785..a78f8e040b7 100644 --- a/gems/aws-sdk-s3/spec/encryptionv3/kms_cipher_provider_spec.rb +++ b/gems/aws-sdk-s3/spec/encryptionv3/kms_cipher_provider_spec.rb @@ -15,7 +15,7 @@ module EncryptionV3 describe '#decryption_cipher' do # A malformed material description raises DecryptionError. - ["abc\xFF", '=?utf-8?B?gA==?='].each do |matdesc| + ["abc\xFF", '=?utf-8?B?gA==?=', '[]', '123'].each do |matdesc| it "raises DecryptionError (#{matdesc.inspect})" do expect do provider.decryption_cipher('x-amz-w' => '12', 'x-amz-t' => matdesc) From a371f336be9aa96b53af605bcc92e77e83f6b684 Mon Sep 17 00:00:00 2001 From: Lucas McDonald Date: Mon, 27 Jul 2026 22:15:52 +0000 Subject: [PATCH 5/6] test: align malformed material description cases --- gems/aws-sdk-s3/spec/encryptionV2/kms_cipher_provider_spec.rb | 4 ++-- gems/aws-sdk-s3/spec/encryptionv3/kms_cipher_provider_spec.rb | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/gems/aws-sdk-s3/spec/encryptionV2/kms_cipher_provider_spec.rb b/gems/aws-sdk-s3/spec/encryptionV2/kms_cipher_provider_spec.rb index adac384a00f..2f896ae0929 100644 --- a/gems/aws-sdk-s3/spec/encryptionV2/kms_cipher_provider_spec.rb +++ b/gems/aws-sdk-s3/spec/encryptionV2/kms_cipher_provider_spec.rb @@ -15,7 +15,7 @@ module EncryptionV2 describe '#decryption_cipher' do # A malformed material description raises DecryptionError. - ["abc\xFF", '=?utf-8?B?gA==?='].each do |matdesc| + ['=?utf-8?B?gA==?=', '=?utf-8?B?/w==?=', '=?utf-8?B?YWJj/w==?=', "abc\xFF"].each do |matdesc| it "raises DecryptionError (#{matdesc.inspect})" do expect do provider.decryption_cipher('x-amz-matdesc' => matdesc) @@ -24,7 +24,7 @@ module EncryptionV2 end # Valid JSON that isn't an object, or an absent matdesc, is malformed. - ['[]', 'true', '"str"', '123', nil].each do |matdesc| + ['123', nil].each do |matdesc| it "raises DecryptionError (#{matdesc.inspect})" do envelope = { 'x-amz-matdesc' => matdesc, diff --git a/gems/aws-sdk-s3/spec/encryptionv3/kms_cipher_provider_spec.rb b/gems/aws-sdk-s3/spec/encryptionv3/kms_cipher_provider_spec.rb index a78f8e040b7..38bbab26735 100644 --- a/gems/aws-sdk-s3/spec/encryptionv3/kms_cipher_provider_spec.rb +++ b/gems/aws-sdk-s3/spec/encryptionv3/kms_cipher_provider_spec.rb @@ -15,7 +15,7 @@ module EncryptionV3 describe '#decryption_cipher' do # A malformed material description raises DecryptionError. - ["abc\xFF", '=?utf-8?B?gA==?=', '[]', '123'].each do |matdesc| + ['=?utf-8?B?gA==?=', '=?utf-8?B?/w==?=', '=?utf-8?B?YWJj/w==?=', "abc\xFF", '123'].each do |matdesc| it "raises DecryptionError (#{matdesc.inspect})" do expect do provider.decryption_cipher('x-amz-w' => '12', 'x-amz-t' => matdesc) From 4cf6a30bf5c992f66388eb7e38891529ccd6b7f3 Mon Sep 17 00:00:00 2001 From: Lucas McDonald Date: Wed, 29 Jul 2026 11:59:07 -0700 Subject: [PATCH 6/6] Update CHANGELOG.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: José Corella <39066999+josecorella@users.noreply.github.com> --- gems/aws-sdk-s3/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gems/aws-sdk-s3/CHANGELOG.md b/gems/aws-sdk-s3/CHANGELOG.md index 6c2443440c9..27be70afbca 100644 --- a/gems/aws-sdk-s3/CHANGELOG.md +++ b/gems/aws-sdk-s3/CHANGELOG.md @@ -1,7 +1,7 @@ Unreleased Changes ------------------ -* Issue - Return a decryption error for a malformed material description. +* Issue - S3 Encryption Client, encryptionV2 and encryptionV3, returns a decryption error for a malformed material description. 1.228.1 (2026-07-23) ------------------