From 2bb77cd33c42e90f03cfb56dd072cc0f07f62ce2 Mon Sep 17 00:00:00 2001 From: Darwin Chowdary <39110935+imabhichow@users.noreply.github.com> Date: Fri, 12 Dec 2025 10:00:33 -0800 Subject: [PATCH 1/2] chore: fuzz test --- .../amazon/encryption/s3/RoundTripTests.java | 84 +++++++++++++++++++ 1 file changed, 84 insertions(+) diff --git a/test-server/java-tests/src/it/java/software/amazon/encryption/s3/RoundTripTests.java b/test-server/java-tests/src/it/java/software/amazon/encryption/s3/RoundTripTests.java index cf45006e..15f6457d 100644 --- a/test-server/java-tests/src/it/java/software/amazon/encryption/s3/RoundTripTests.java +++ b/test-server/java-tests/src/it/java/software/amazon/encryption/s3/RoundTripTests.java @@ -15,9 +15,11 @@ import java.nio.charset.StandardCharsets; import java.security.KeyPair; import java.security.KeyPairGenerator; +import java.util.Base64; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Random; import com.amazonaws.services.s3.AmazonS3EncryptionClientV2; import com.amazonaws.services.s3.AmazonS3EncryptionV2; @@ -28,6 +30,7 @@ import org.junit.jupiter.params.provider.MethodSource; import org.opentest4j.TestAbortedException; import software.amazon.awssdk.core.ResponseBytes; +import software.amazon.awssdk.core.sync.RequestBody; import software.amazon.awssdk.services.s3.S3Client; import software.amazon.awssdk.services.s3.model.GetObjectResponse; import software.amazon.encryption.s3.TestUtils.LanguageServerTarget; @@ -59,6 +62,87 @@ public static void setup() { validateServersRunning(); } + /** + * Verifies input validation via fuzzing of commitment parameters. + * - Iterates multiple times with random garbage in critical metadata fields. + * - Ensures client handles invalid input gracefully (throws exception, doesn't + * crash). + */ + @ParameterizedTest(name = "{displayName}: Fuzzing {0}") + @MethodSource("software.amazon.encryption.s3.TestUtils#improvedClientsForTest") + public void testCommitmentParameterFuzzing(TestUtils.LanguageServerTarget target) throws Exception { + S3ECTestServerClient testClient = TestUtils.testServerClientFor(target); + final String objectKey = TestUtils.appendTestSuffix("fuzzing-" + target); + final String testInput = "fuzzing metadata"; + KeyMaterial kmsKeyArn = KeyMaterial.builder().kmsKeyId(TestUtils.KMS_KEY_ARN).build(); + + // 1. Create Valid Object + String clientId = testClient.createClient(CreateClientInput.builder() + .config(S3ECConfig.builder() + .keyMaterial(kmsKeyArn) + .commitmentPolicy(CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT) + .build()) + .build()).getClientId(); + + testClient.putObject(PutObjectInput.builder() + .clientID(clientId) + .bucket(TestUtils.BUCKET) + .key(objectKey) + .body(ByteBuffer.wrap(testInput.getBytes(StandardCharsets.UTF_8))) + .build()); + + // 2. Get Original Metadata + S3Client s3Client = S3Client.create(); + ResponseBytes objectBytes = s3Client + .getObjectAsBytes(b -> b.bucket(TestUtils.BUCKET).key(objectKey)); + Map originalMetadata = objectBytes.response().metadata(); + + // 3. Fuzzing Loop + Random random = new Random(); + String[] fieldsToFuzz = { "x-amz-c", "x-amz-i", "x-amz-3" }; + + for (int i = 0; i < 20; i++) { + String field = fieldsToFuzz[random.nextInt(fieldsToFuzz.length)]; + Map fuzzedMetadata = new HashMap<>(originalMetadata); + + // Generate random garbage + byte[] garbage = new byte[random.nextInt(50) + 1]; + random.nextBytes(garbage); + String garbageStr = Base64.getEncoder().encodeToString(garbage); + + // Occasionally inject non-Base64 garbage + if (random.nextBoolean()) { + garbageStr = "INVALID_BASE64_!@#$%^&*()"; + } + + fuzzedMetadata.put(field, garbageStr); + + // Upload with fuzzed metadata + s3Client.putObject(software.amazon.awssdk.services.s3.model.PutObjectRequest.builder() + .bucket(TestUtils.BUCKET) + .key(objectKey) // Overwrite + .metadata(fuzzedMetadata) + .build(), + RequestBody.fromBytes(objectBytes.asByteArray())); + + // Attempt Decryption + try { + testClient.getObject(GetObjectInput.builder() + .clientID(clientId) + .bucket(TestUtils.BUCKET) + .key(objectKey) + .build()); + fail("Should fail with fuzzed metadata field: " + field); + } catch (S3EncryptionClientError e) { + // Expected + } + } + + // cleanup + s3Client.close(); + } + + @ParameterizedTest(name = "{displayName} for Encrypt: {0}, Decrypt: {1}") @MethodSource("software.amazon.encryption.s3.TestUtils#crossLanguageClients") public void crossLanguageTestKms(LanguageServerTarget encLang, LanguageServerTarget decLang) { From 36e1c96e95b1e91b1661ee439e38f66f06b9afd5 Mon Sep 17 00:00:00 2001 From: Darwin Chowdary <39110935+imabhichow@users.noreply.github.com> Date: Fri, 12 Dec 2025 10:49:47 -0800 Subject: [PATCH 2/2] m --- .../it/java/software/amazon/encryption/s3/RoundTripTests.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test-server/java-tests/src/it/java/software/amazon/encryption/s3/RoundTripTests.java b/test-server/java-tests/src/it/java/software/amazon/encryption/s3/RoundTripTests.java index 15f6457d..b5f8ef2c 100644 --- a/test-server/java-tests/src/it/java/software/amazon/encryption/s3/RoundTripTests.java +++ b/test-server/java-tests/src/it/java/software/amazon/encryption/s3/RoundTripTests.java @@ -135,6 +135,10 @@ public void testCommitmentParameterFuzzing(TestUtils.LanguageServerTarget target fail("Should fail with fuzzed metadata field: " + field); } catch (S3EncryptionClientError e) { // Expected + // throw exception + if (e.getMessage().contains("null") || e.getMessage().contains("Cannot invoke")) { + throw e; + } } }