VYPR
Medium severity6.3GHSA Advisory· Published May 14, 2026· Updated May 14, 2026

CVE-2026-44308

CVE-2026-44308

Description

Spring Cloud AWS simplifies using AWS managed services in a Spring and Spring Boot applications. From 3.0.0 to 4.0.1, pplications using Spring Cloud AWS SNS HTTP/HTTPS endpoint support (@NotificationMessageMapping, @NotificationSubscriptionMapping, @NotificationUnsubscribeConfirmationMapping) did not verify the signature of incoming SNS messages. An unauthenticated attacker who knows the endpoint URL could send crafted HTTP POST requests mimicking SNS Notification or SubscriptionConfirmation messages. This vulnerability is fixed in 4.0.2.

Affected products

1

Patches

1
6ab2efd97891

Introduce SNS header verification (#1614)

https://github.com/awspring/spring-cloud-awsMatejNedicApr 28, 2026via ghsa
16 files changed · +212 32
  • docs/src/main/asciidoc/_configprops.adoc+1 0 modified
    @@ -93,6 +93,7 @@
     |spring.cloud.aws.sns.enabled | `+++true+++` | Enables SNS integration.
     |spring.cloud.aws.sns.endpoint |  | Overrides the default endpoint.
     |spring.cloud.aws.sns.region |  | Overrides the default region.
    +|spring.cloud.aws.sns.verification | `+++true+++` | Defines if SNS massages will be verified. By default, verification is used.
     |spring.cloud.aws.sqs.dualstack-enabled |  | Configure whether the AWS client should use the AWS dualstack endpoint. Note that not each AWS service supports dual-stack. For complete list check <a href="https://docs.aws.amazon.com/vpc/latest/userguide/aws-ipv6-support.html">AWS services that support IPv6</a>
     |spring.cloud.aws.sqs.enabled | `+++true+++` | Enables SQS integration.
     |spring.cloud.aws.sqs.endpoint |  | Overrides the default endpoint.
    
  • docs/src/main/asciidoc/sns.adoc+7 0 modified
    @@ -179,6 +179,13 @@ SNS sends three type of requests to an HTTP topic listener endpoint, for each of
     * Notification request -> `@NotificationMessageMapping`
     * Unsubscription request -> `@NotificationUnsubscribeMapping`
     
    +[NOTE]
    +====
    +Since version 4.0.2 verification has been introduced for Notification request and is turned on by default. Verification uses same region as `SNSClient`.
    +To turn off verification simply set property `spring.cloud.aws.sns.verification=false`.
    +For more information about SNS verification https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/messagemanager/sns/SnsMessageManager.html[here].
    +====
    +
     HTTP endpoints are based on Spring MVC controllers. Spring Cloud AWS added some custom argument resolvers to extract the message and subject out of the notification requests.
     
     Example of integration:
    
  • spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/sns/SnsAutoConfiguration.java+19 4 modified
    @@ -48,6 +48,7 @@
     import org.springframework.messaging.support.ChannelInterceptor;
     import org.springframework.web.method.support.HandlerMethodArgumentResolver;
     import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
    +import software.amazon.awssdk.messagemanager.sns.SnsMessageManager;
     import software.amazon.awssdk.services.sns.SnsClient;
     import tools.jackson.databind.json.JsonMapper;
     
    @@ -81,6 +82,17 @@ public SnsClient snsClient(SnsProperties properties, AwsClientBuilderConfigurer
     				.build();
     	}
     
    +	@ConditionalOnProperty(name = "spring.cloud.aws.sns.verification", havingValue = "true", matchIfMissing = true)
    +	@ConditionalOnMissingBean
    +	@Bean
    +	public SnsMessageManager snsMessageManager(SnsProperties snsProperties,
    +			ObjectProvider<AwsConnectionDetails> connectionDetails,
    +			AwsClientBuilderConfigurer awsClientBuilderConfigurer) {
    +		return SnsMessageManager.builder()
    +				.region(awsClientBuilderConfigurer.resolveRegion(snsProperties, connectionDetails.getIfAvailable()))
    +				.build();
    +	}
    +
     	@ConditionalOnMissingBean(SnsSmsOperations.class)
     	@Bean
     	public SnsSmsTemplate snsSmsTemplate(SnsClient snsClient) {
    @@ -129,25 +141,28 @@ public SnsTemplate snsTemplate(SnsClient snsClient, Optional<ObjectMapper> objec
     	static class SnsWebConfiguration {
     
     		@Bean
    -		public WebMvcConfigurer snsWebMvcConfigurer(SnsClient snsClient) {
    +		public WebMvcConfigurer snsWebMvcConfigurer(SnsClient snsClient,
    +				ObjectProvider<SnsMessageManager> snsMessageManager) {
     			if (JacksonPresent.isJackson3Present()) {
     				return new WebMvcConfigurer() {
     					@Override
     					public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
    -						resolvers.add(getNotificationHandlerMethodArgumentResolver(snsClient));
    +						resolvers.add(getNotificationHandlerMethodArgumentResolver(snsClient,
    +								snsMessageManager.getIfAvailable()));
     					}
     				};
     			}
     			else if (JacksonPresent.isJackson2Present()) {
     				return new WebMvcConfigurer() {
     					@Override
     					public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
    -						resolvers.add(getNotificationHandlerMethodArgumentResolverLegacyJackson2(snsClient));
    +						resolvers.add(getNotificationHandlerMethodArgumentResolverLegacyJackson2(snsClient,
    +								snsMessageManager.getIfAvailable()));
     					}
     				};
     			}
     			throw new IllegalStateException(
    -					"SecretsManagerPropertySource requires a Jackson 2 or Jackson 3 library on the classpath");
    +					"SnsWebMvc integration requires a Jackson 2 or Jackson 3 library on the classpath");
     		}
     	}
     
    
  • spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/sns/SnsProperties.java+13 0 modified
    @@ -31,4 +31,17 @@ public class SnsProperties extends AwsClientProperties {
     	 * The prefix used for AWS SNS configuration.
     	 */
     	public static final String PREFIX = "spring.cloud.aws.sns";
    +
    +	/**
    +	 * Defines if SNS massages will be verified. By default, verification is used.
    +	 */
    +	private boolean verification = true;
    +
    +	public boolean getVerification() {
    +		return verification;
    +	}
    +
    +	public void setVerification(boolean verification) {
    +		this.verification = verification;
    +	}
     }
    
  • spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/sns/SnsAutoConfigurationTest.java+21 1 modified
    @@ -38,6 +38,7 @@
     import org.springframework.messaging.support.ChannelInterceptor;
     import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
     import software.amazon.awssdk.arns.Arn;
    +import software.amazon.awssdk.messagemanager.sns.SnsMessageManager;
     import software.amazon.awssdk.services.sns.SnsClient;
     
     /**
    @@ -67,13 +68,31 @@ void snsAutoConfigurationIsEnabled() {
     			assertThat(context).hasSingleBean(SnsTemplate.class);
     			assertThat(context).hasSingleBean(SnsSmsTemplate.class);
     			assertThat(context).hasBean("snsWebMvcConfigurer");
    +			assertThat(context).hasSingleBean(SnsMessageManager.class);
     
     			ConfiguredAwsClient client = new ConfiguredAwsClient(context.getBean(SnsClient.class));
     			assertThat(client.getEndpoint()).isEqualTo(URI.create("https://sns.eu-west-1.amazonaws.com"));
     
     		});
     	}
     
    +	@Test
    +	void snsAutoConfigurationIsEnabledAndVerifyIsDisabled() {
    +		this.contextRunner
    +				.withPropertyValues("spring.cloud.aws.sns.enabled:true", "spring.cloud.aws.sns.verification:false")
    +				.run(context -> {
    +					assertThat(context).hasSingleBean(SnsClient.class);
    +					assertThat(context).hasSingleBean(SnsTemplate.class);
    +					assertThat(context).hasSingleBean(SnsSmsTemplate.class);
    +					assertThat(context).hasBean("snsWebMvcConfigurer");
    +					assertThat(context).doesNotHaveBean(SnsMessageManager.class);
    +
    +					ConfiguredAwsClient client = new ConfiguredAwsClient(context.getBean(SnsClient.class));
    +					assertThat(client.getEndpoint()).isEqualTo(URI.create("https://sns.eu-west-1.amazonaws.com"));
    +
    +				});
    +	}
    +
     	@Test
     	void withCustomEndpoint() {
     		this.contextRunner.withPropertyValues("spring.cloud.aws.sns.endpoint:http://localhost:8090").run(context -> {
    @@ -98,6 +117,7 @@ void doesNotConfigureArgumentResolversWhenSpringWebNotOnTheClasspath() {
     			assertThat(context).hasSingleBean(SnsClient.class);
     			assertThat(context).hasSingleBean(SnsTemplate.class);
     			assertThat(context).hasSingleBean(SnsSmsTemplate.class);
    +			assertThat(context).hasSingleBean(SnsMessageManager.class);
     			assertThat(context).doesNotHaveBean("snsWebMvcConfigurer");
     		});
     	}
    @@ -127,7 +147,7 @@ void customChannelInterceptorCanBeConfigured() {
     	static class CustomTopicArnResolverConfiguration {
     
     		@Bean
    -		TopicArnResolver customS3OutputStreamProvider() {
    +		TopicArnResolver customTopicArnResolver() {
     			return new CustomTopicArnResolver();
     		}
     
    
  • spring-cloud-aws-dependencies/pom.xml+1 2 modified
    @@ -24,8 +24,7 @@
     
     	<properties>
     		<spotless.version>2.31.0</spotless.version>
    -		<awssdk-v2.version>2.41.5</awssdk-v2.version>
    -		<awssdk-v2.version>2.41.18</awssdk-v2.version>
    +		<awssdk-v2.version>2.42.36</awssdk-v2.version>
     		<kcl.version>3.1.3</kcl.version>
     		<kpl.version>1.0.7</kpl.version>
     		<amazon.dax.version>2.0.7</amazon.dax.version>
    
  • spring-cloud-aws-sns/pom.xml+4 0 modified
    @@ -27,6 +27,10 @@
     			<groupId>org.springframework</groupId>
     			<artifactId>spring-messaging</artifactId>
     		</dependency>
    +		<dependency>
    +			<groupId>software.amazon.awssdk</groupId>
    +			<artifactId>sns-message-manager</artifactId>
    +		</dependency>
     		<dependency>
     			<groupId>com.fasterxml.jackson.core</groupId>
     			<artifactId>jackson-databind</artifactId>
    
  • spring-cloud-aws-sns/src/main/java/io/awspring/cloud/sns/configuration/NotificationHandlerMethodArgumentResolverConfigurationUtils.java+27 6 modified
    @@ -21,9 +21,11 @@
     import io.awspring.cloud.sns.handlers.legacy.LegacyJackson2NotificationMessageHandlerMethodArgumentResolver;
     import io.awspring.cloud.sns.handlers.legacy.LegacyJackson2NotificationStatusHandlerMethodArgumentResolver;
     import io.awspring.cloud.sns.handlers.legacy.LegacyJackson2NotificationSubjectHandlerMethodArgumentResolver;
    +import org.jspecify.annotations.Nullable;
     import org.springframework.util.Assert;
     import org.springframework.web.method.support.HandlerMethodArgumentResolver;
     import org.springframework.web.method.support.HandlerMethodArgumentResolverComposite;
    +import software.amazon.awssdk.messagemanager.sns.SnsMessageManager;
     import software.amazon.awssdk.services.sns.SnsClient;
     
     /**
    @@ -39,21 +41,40 @@ private NotificationHandlerMethodArgumentResolverConfigurationUtils() {
     		throw new IllegalStateException("Can't instantiate a utility class");
     	}
     
    -	public static HandlerMethodArgumentResolver getNotificationHandlerMethodArgumentResolver(SnsClient snsClient) {
    +	public static HandlerMethodArgumentResolver getNotificationHandlerMethodArgumentResolver(SnsClient snsClient,
    +			@Nullable SnsMessageManager snsMessageManager) {
     		Assert.notNull(snsClient, "snsClient is required");
     		HandlerMethodArgumentResolverComposite composite = new HandlerMethodArgumentResolverComposite();
    -		composite.addResolver(new NotificationStatusHandlerMethodArgumentResolver(snsClient));
    -		composite.addResolver(new NotificationMessageHandlerMethodArgumentResolver());
    +
    +		if (snsMessageManager != null) {
    +			composite.addResolver(new NotificationStatusHandlerMethodArgumentResolver(snsClient, snsMessageManager));
    +			composite.addResolver(new NotificationMessageHandlerMethodArgumentResolver(
    +					NotificationMessageHandlerMethodArgumentResolver.converters, snsMessageManager));
    +		}
    +		else {
    +			composite.addResolver(new NotificationStatusHandlerMethodArgumentResolver(snsClient));
    +			composite.addResolver(new NotificationMessageHandlerMethodArgumentResolver());
    +		}
     		composite.addResolver(new NotificationSubjectHandlerMethodArgumentResolver());
    +
     		return composite;
     	}
     
     	public static HandlerMethodArgumentResolver getNotificationHandlerMethodArgumentResolverLegacyJackson2(
    -			SnsClient snsClient) {
    +			SnsClient snsClient, @Nullable SnsMessageManager snsMessageManager) {
     		Assert.notNull(snsClient, "snsClient is required");
     		HandlerMethodArgumentResolverComposite composite = new HandlerMethodArgumentResolverComposite();
    -		composite.addResolver(new LegacyJackson2NotificationStatusHandlerMethodArgumentResolver(snsClient));
    -		composite.addResolver(new LegacyJackson2NotificationMessageHandlerMethodArgumentResolver());
    +		if (snsMessageManager != null) {
    +			composite.addResolver(
    +					new LegacyJackson2NotificationStatusHandlerMethodArgumentResolver(snsClient, snsMessageManager));
    +			composite.addResolver(new LegacyJackson2NotificationMessageHandlerMethodArgumentResolver(
    +					LegacyJackson2NotificationMessageHandlerMethodArgumentResolver.converters, snsMessageManager));
    +		}
    +		else {
    +			composite.addResolver(new LegacyJackson2NotificationStatusHandlerMethodArgumentResolver(snsClient));
    +			composite.addResolver(new LegacyJackson2NotificationMessageHandlerMethodArgumentResolver());
    +		}
    +
     		composite.addResolver(new LegacyJackson2NotificationSubjectHandlerMethodArgumentResolver());
     		return composite;
     	}
    
  • spring-cloud-aws-sns/src/main/java/io/awspring/cloud/sns/handlers/legacy/LegacyJackson2NotificationMessageHandlerMethodArgumentResolver.java+22 1 modified
    @@ -23,6 +23,7 @@
     import java.nio.charset.StandardCharsets;
     import java.util.Arrays;
     import java.util.List;
    +import org.jspecify.annotations.Nullable;
     import org.springframework.core.MethodParameter;
     import org.springframework.http.HttpHeaders;
     import org.springframework.http.HttpInputMessage;
    @@ -32,6 +33,7 @@
     import org.springframework.http.converter.StringHttpMessageConverter;
     import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
     import org.springframework.util.StringUtils;
    +import software.amazon.awssdk.messagemanager.sns.SnsMessageManager;
     
     /**
      * Handles conversion of SNS notification value to a variable that is annotated with {@link NotificationMessage}.
    @@ -46,12 +48,24 @@ public class LegacyJackson2NotificationMessageHandlerMethodArgumentResolver
     
     	private final List<HttpMessageConverter<?>> messageConverter;
     
    +	@Nullable
    +	private final SnsMessageManager snsMessageManager;
    +
    +	public static final List<HttpMessageConverter<?>> converters = Arrays
    +			.asList(new MappingJackson2HttpMessageConverter(), new StringHttpMessageConverter());
    +
     	public LegacyJackson2NotificationMessageHandlerMethodArgumentResolver() {
    -		this(Arrays.asList(new MappingJackson2HttpMessageConverter(), new StringHttpMessageConverter()));
    +		this(converters);
     	}
     
     	public LegacyJackson2NotificationMessageHandlerMethodArgumentResolver(
     			List<HttpMessageConverter<?>> messageConverter) {
    +		this(messageConverter, null);
    +	}
    +
    +	public LegacyJackson2NotificationMessageHandlerMethodArgumentResolver(
    +			List<HttpMessageConverter<?>> messageConverter, @Nullable SnsMessageManager snsMessageManager) {
    +		this.snsMessageManager = snsMessageManager;
     		this.messageConverter = messageConverter;
     	}
     
    @@ -83,6 +97,9 @@ protected Object doResolveArgumentFromNotificationMessage(JsonNode content, Http
     
     		MediaType mediaType = getMediaType(content);
     		String messageContent = content.findPath("Message").asText();
    +		if (snsMessageManager != null) {
    +			verifySignature(content.toString());
    +		}
     		for (HttpMessageConverter<?> converter : this.messageConverter) {
     			if (converter.canRead(parameterType, mediaType)) {
     				try {
    @@ -100,6 +117,10 @@ protected Object doResolveArgumentFromNotificationMessage(JsonNode content, Http
     				"Error converting notification message with payload:" + messageContent, request);
     	}
     
    +	private void verifySignature(String payload) {
    +		snsMessageManager.parseMessage(payload);
    +	}
    +
     	public static final class ByteArrayHttpInputMessage implements HttpInputMessage {
     
     		private final String content;
    
  • spring-cloud-aws-sns/src/main/java/io/awspring/cloud/sns/handlers/legacy/LegacyJackson2NotificationStatusHandlerMethodArgumentResolver.java+20 0 modified
    @@ -17,8 +17,10 @@
     
     import com.fasterxml.jackson.databind.JsonNode;
     import io.awspring.cloud.sns.handlers.NotificationStatus;
    +import org.jspecify.annotations.Nullable;
     import org.springframework.core.MethodParameter;
     import org.springframework.http.HttpInputMessage;
    +import software.amazon.awssdk.messagemanager.sns.SnsMessageManager;
     import software.amazon.awssdk.services.sns.SnsClient;
     import software.amazon.awssdk.services.sns.model.ConfirmSubscriptionRequest;
     
    @@ -34,8 +36,17 @@ public class LegacyJackson2NotificationStatusHandlerMethodArgumentResolver
     
     	private final SnsClient snsClient;
     
    +	@Nullable
    +	private final SnsMessageManager snsMessageManager;
    +
     	public LegacyJackson2NotificationStatusHandlerMethodArgumentResolver(SnsClient snsClient) {
    +		this(snsClient, null);
    +	}
    +
    +	public LegacyJackson2NotificationStatusHandlerMethodArgumentResolver(SnsClient snsClient,
    +			@Nullable SnsMessageManager snsMessageManager) {
     		this.snsClient = snsClient;
    +		this.snsMessageManager = snsMessageManager;
     	}
     
     	@Override
    @@ -51,10 +62,19 @@ protected Object doResolveArgumentFromNotificationMessage(JsonNode content, Http
     			throw new IllegalArgumentException(
     					"NotificationStatus is only available for subscription and unsubscription requests");
     		}
    +
    +		if (snsMessageManager != null) {
    +			verifySignature(content.toString());
    +		}
    +
     		return new AmazonSnsNotificationStatus(this.snsClient, content.get("TopicArn").asText(),
     				content.get("Token").asText());
     	}
     
    +	private void verifySignature(String payload) {
    +		snsMessageManager.parseMessage(payload);
    +	}
    +
     	public static final class AmazonSnsNotificationStatus implements NotificationStatus {
     
     		private final SnsClient snsClient;
    
  • spring-cloud-aws-sns/src/main/java/io/awspring/cloud/sns/handlers/NotificationMessageHandlerMethodArgumentResolver.java+23 2 modified
    @@ -22,6 +22,7 @@
     import java.nio.charset.StandardCharsets;
     import java.util.Arrays;
     import java.util.List;
    +import org.jspecify.annotations.Nullable;
     import org.springframework.core.MethodParameter;
     import org.springframework.http.HttpHeaders;
     import org.springframework.http.HttpInputMessage;
    @@ -31,6 +32,7 @@
     import org.springframework.http.converter.StringHttpMessageConverter;
     import org.springframework.http.converter.json.JacksonJsonHttpMessageConverter;
     import org.springframework.util.StringUtils;
    +import software.amazon.awssdk.messagemanager.sns.SnsMessageManager;
     import tools.jackson.databind.JsonNode;
     
     /**
    @@ -46,18 +48,30 @@ public class NotificationMessageHandlerMethodArgumentResolver
     
     	private final List<HttpMessageConverter<?>> messageConverter;
     
    +	@Nullable
    +	private final SnsMessageManager snsMessageManager;
    +
    +	public static final List<HttpMessageConverter<?>> converters = Arrays.asList(new JacksonJsonHttpMessageConverter(),
    +			new StringHttpMessageConverter());
    +
     	public NotificationMessageHandlerMethodArgumentResolver() {
    -		this(Arrays.asList(new JacksonJsonHttpMessageConverter(), new StringHttpMessageConverter()));
    +		this(converters);
     	}
     
     	public NotificationMessageHandlerMethodArgumentResolver(List<HttpMessageConverter<?>> messageConverter) {
    +		this(messageConverter, null);
    +	}
    +
    +	public NotificationMessageHandlerMethodArgumentResolver(List<HttpMessageConverter<?>> messageConverter,
    +			@Nullable SnsMessageManager snsMessageManager) {
    +		this.snsMessageManager = snsMessageManager;
     		this.messageConverter = messageConverter;
     	}
     
     	private static MediaType getMediaType(JsonNode content) {
     		JsonNode contentTypeNode = content.findPath("MessageAttributes").findPath("contentType");
     		if (contentTypeNode.isObject()) {
    -			String contentType = contentTypeNode.findPath("Value").asText();
    +			String contentType = contentTypeNode.findPath("Value").asString();
     			if (StringUtils.hasText(contentType)) {
     				return MediaType.parseMediaType(contentType);
     			}
    @@ -82,6 +96,9 @@ protected Object doResolveArgumentFromNotificationMessage(JsonNode content, Http
     
     		MediaType mediaType = getMediaType(content);
     		String messageContent = content.findPath("Message").asString();
    +		if (snsMessageManager != null) {
    +			verifySignature(content.toString());
    +		}
     		for (HttpMessageConverter<?> converter : this.messageConverter) {
     			if (converter.canRead(parameterType, mediaType)) {
     				try {
    @@ -99,6 +116,10 @@ protected Object doResolveArgumentFromNotificationMessage(JsonNode content, Http
     				"Error converting notification message with payload:" + messageContent, request);
     	}
     
    +	private void verifySignature(String payload) {
    +		snsMessageManager.parseMessage(payload);
    +	}
    +
     	public static final class ByteArrayHttpInputMessage implements HttpInputMessage {
     
     		private final String content;
    
  • spring-cloud-aws-sns/src/main/java/io/awspring/cloud/sns/handlers/NotificationStatusHandlerMethodArgumentResolver.java+20 0 modified
    @@ -15,8 +15,10 @@
      */
     package io.awspring.cloud.sns.handlers;
     
    +import org.jspecify.annotations.Nullable;
     import org.springframework.core.MethodParameter;
     import org.springframework.http.HttpInputMessage;
    +import software.amazon.awssdk.messagemanager.sns.SnsMessageManager;
     import software.amazon.awssdk.services.sns.SnsClient;
     import software.amazon.awssdk.services.sns.model.ConfirmSubscriptionRequest;
     import tools.jackson.databind.JsonNode;
    @@ -33,8 +35,17 @@ public class NotificationStatusHandlerMethodArgumentResolver
     
     	private final SnsClient snsClient;
     
    +	@Nullable
    +	private final SnsMessageManager snsMessageManager;
    +
     	public NotificationStatusHandlerMethodArgumentResolver(SnsClient snsClient) {
    +		this(snsClient, null);
    +	}
    +
    +	public NotificationStatusHandlerMethodArgumentResolver(SnsClient snsClient,
    +			@Nullable SnsMessageManager snsMessageManager) {
     		this.snsClient = snsClient;
    +		this.snsMessageManager = snsMessageManager;
     	}
     
     	@Override
    @@ -50,10 +61,19 @@ protected Object doResolveArgumentFromNotificationMessage(JsonNode content, Http
     			throw new IllegalArgumentException(
     					"NotificationStatus is only available for subscription and unsubscription requests");
     		}
    +
    +		if (snsMessageManager != null) {
    +			verifySignature(content.toString());
    +		}
    +
     		return new AmazonSnsNotificationStatus(this.snsClient, content.get("TopicArn").asString(),
     				content.get("Token").asString());
     	}
     
    +	private void verifySignature(String payload) {
    +		snsMessageManager.parseMessage(payload);
    +	}
    +
     	public static final class AmazonSnsNotificationStatus implements NotificationStatus {
     
     		private final SnsClient snsClient;
    
  • spring-cloud-aws-sns/src/test/java/io/awspring/cloud/sns/endpoint/ComplexNotificationEndpointControllerTest.java+11 2 modified
    @@ -50,6 +50,7 @@
     import org.springframework.web.method.support.HandlerMethodArgumentResolver;
     import org.springframework.web.servlet.config.annotation.EnableWebMvc;
     import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
    +import software.amazon.awssdk.messagemanager.sns.SnsMessageManager;
     import software.amazon.awssdk.services.sns.SnsClient;
     import software.amazon.awssdk.services.sns.model.ConfirmSubscriptionRequest;
     
    @@ -68,6 +69,9 @@ class ComplexNotificationEndpointControllerTest {
     	@Autowired
     	private SnsClient snsClient;
     
    +	@Autowired
    +	private SnsMessageManager snsMessageManager;
    +
     	@Autowired
     	private ComplexNotificationTestController notificationTestController;
     
    @@ -163,17 +167,22 @@ void reSubscriptionCalledByController() throws Exception {
     	@Import(ComplexNotificationTestController.class)
     	static class Config {
     
    +		@Bean
    +		SnsMessageManager snsMessageManager() {
    +			return Mockito.mock(SnsMessageManager.class);
    +		}
    +
     		@Bean
     		SnsClient snsClient() {
     			return Mockito.mock(SnsClient.class);
     		}
     
     		@Bean
    -		public WebMvcConfigurer snsWebMvcConfigurer(SnsClient snsClient) {
    +		public WebMvcConfigurer snsWebMvcConfigurer(SnsClient snsClient, SnsMessageManager snsMessageManager) {
     			return new WebMvcConfigurer() {
     				@Override
     				public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
    -					argumentResolvers.add(getNotificationHandlerMethodArgumentResolver(snsClient));
    +					argumentResolvers.add(getNotificationHandlerMethodArgumentResolver(snsClient, snsMessageManager));
     				}
     			};
     		}
    
  • spring-cloud-aws-sns/src/test/java/io/awspring/cloud/sns/endpoint/MethodEndpointControllerTest.java+1 1 modified
    @@ -149,7 +149,7 @@ public WebMvcConfigurer snsWebMvcConfigurer(SnsClient snsClient) {
     			return new WebMvcConfigurer() {
     				@Override
     				public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
    -					argumentResolvers.add(getNotificationHandlerMethodArgumentResolver(snsClient));
    +					argumentResolvers.add(getNotificationHandlerMethodArgumentResolver(snsClient, null));
     				}
     			};
     		}
    
  • spring-cloud-aws-sns/src/test/java/io/awspring/cloud/sns/endpoint/NotificationEndpointControllerTest.java+8 2 modified
    @@ -49,6 +49,7 @@
     import org.springframework.web.method.support.HandlerMethodArgumentResolver;
     import org.springframework.web.servlet.config.annotation.EnableWebMvc;
     import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
    +import software.amazon.awssdk.messagemanager.sns.SnsMessageManager;
     import software.amazon.awssdk.services.sns.SnsClient;
     import software.amazon.awssdk.services.sns.model.ConfirmSubscriptionRequest;
     
    @@ -144,11 +145,16 @@ SnsClient snsClient() {
     		}
     
     		@Bean
    -		public WebMvcConfigurer snsWebMvcConfigurer(SnsClient snsClient) {
    +		SnsMessageManager snsMessageManager() {
    +			return Mockito.mock(SnsMessageManager.class);
    +		}
    +
    +		@Bean
    +		public WebMvcConfigurer snsWebMvcConfigurer(SnsClient snsClient, SnsMessageManager snsMessageManager) {
     			return new WebMvcConfigurer() {
     				@Override
     				public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
    -					argumentResolvers.add(getNotificationHandlerMethodArgumentResolver(snsClient));
    +					argumentResolvers.add(getNotificationHandlerMethodArgumentResolver(snsClient, snsMessageManager));
     				}
     			};
     		}
    
  • spring-cloud-aws-sqs/src/test/java/io/awspring/cloud/sqs/integration/SqsTemplateFifoTracingIntegrationTest.java+14 11 modified
    @@ -15,6 +15,8 @@
      */
     package io.awspring.cloud.sqs.integration;
     
    +import static org.assertj.core.api.Assertions.assertThat;
    +
     import io.awspring.cloud.sqs.operations.SqsTemplate;
     import io.micrometer.observation.Observation;
     import io.micrometer.observation.ObservationRegistry;
    @@ -29,6 +31,10 @@
     import io.micrometer.tracing.propagation.Propagator;
     import io.micrometer.tracing.test.simple.SimpleTraceContext;
     import io.micrometer.tracing.test.simple.SimpleTracer;
    +import java.time.Duration;
    +import java.util.List;
    +import java.util.Map;
    +import java.util.UUID;
     import org.junit.jupiter.api.AfterEach;
     import org.junit.jupiter.api.BeforeAll;
     import org.junit.jupiter.api.Test;
    @@ -41,13 +47,6 @@
     import software.amazon.awssdk.services.sqs.SqsAsyncClient;
     import software.amazon.awssdk.services.sqs.model.QueueAttributeName;
     
    -import java.time.Duration;
    -import java.util.List;
    -import java.util.Map;
    -import java.util.UUID;
    -
    -import static org.assertj.core.api.Assertions.assertThat;
    -
     /**
      * Integration tests for trace context propagation in FIFO queues with SqsTemplate.
      * <p>
    @@ -76,8 +75,10 @@ public class SqsTemplateFifoTracingIntegrationTest extends BaseSqsIntegrationTes
     	@BeforeAll
     	static void beforeTests() {
     		var client = createAsyncClient();
    -		createFifoQueue(client, FIFO_QUEUE_NAME, Map.of(QueueAttributeName.CONTENT_BASED_DEDUPLICATION, "false")).join();
    -		createFifoQueue(client, FIFO_CACHE_HIT_QUEUE_NAME, Map.of(QueueAttributeName.CONTENT_BASED_DEDUPLICATION, "true")).join();
    +		createFifoQueue(client, FIFO_QUEUE_NAME, Map.of(QueueAttributeName.CONTENT_BASED_DEDUPLICATION, "false"))
    +				.join();
    +		createFifoQueue(client, FIFO_CACHE_HIT_QUEUE_NAME,
    +				Map.of(QueueAttributeName.CONTENT_BASED_DEDUPLICATION, "true")).join();
     
     	}
     
    @@ -119,7 +120,8 @@ void sendAsync_toFifoQueue_shouldCreateObservationOnCallingThreadAfterCacheHit()
     		sqsTemplate.sendAsync(FIFO_CACHE_HIT_QUEUE_NAME, warmupPayload).join();
     
     		// Drain the warmup message
    -		sqsTemplate.receive(from -> from.queue(FIFO_CACHE_HIT_QUEUE_NAME).pollTimeout(Duration.ofSeconds(5)), TestEvent.class);
    +		sqsTemplate.receive(from -> from.queue(FIFO_CACHE_HIT_QUEUE_NAME).pollTimeout(Duration.ofSeconds(5)),
    +				TestEvent.class);
     
     		// Given - Start a NEW observation for the actual test
     		var observation = Observation.start("test-send-second", observationRegistry);
    @@ -138,7 +140,8 @@ void sendAsync_toFifoQueue_shouldCreateObservationOnCallingThreadAfterCacheHit()
     		logger.info("expectedTraceId={}", expectedTraceId);
     
     		var receivedMessage = sqsTemplate
    -				.receive(from -> from.queue(FIFO_CACHE_HIT_QUEUE_NAME).pollTimeout(Duration.ofSeconds(5)), TestEvent.class)
    +				.receive(from -> from.queue(FIFO_CACHE_HIT_QUEUE_NAME).pollTimeout(Duration.ofSeconds(5)),
    +						TestEvent.class)
     				.orElseThrow(() -> new AssertionError("Expected message was not received"));
     
     		assertThat(receivedMessage.getPayload()).isEqualTo(payload);
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

5

News mentions

0

No linked articles in our index yet.