Introduction
A gap in the AWS SNS documentation and sample code leads developers to potentially introduce Server-Side Request Forgeries (SSRF) in their applications. Tracing that pattern across the open-source ecosystem led to my discovery of CVE-2026-32096.
CVE-2019-6715 was the origin of this research, and what I believe to be the earliest occurrence of such behavior.
What is AWS SNS
AWS Simple Notification Service (SNS) is a pub/sub messaging service. SNS topics can deliver messages to a variety of subscriber types: Lambda functions, SQS queues, and external applications via HTTP/S endpoints. In this post, we focus on the setup using HTTP/S for external applications.
Before notifications start flowing, SNS needs to know where to send the data. When you subscribe your endpoint, AWS sends a SubscriptionConfirmation message containing a SubscribeURL. Your application makes a GET request to that URL, and the subscription is active.
This is a one-time step that verifies endpoint ownership, preventing someone from subscribing an arbitrary URL without the owner's consent.
After confirmation, every message published to the topic is automatically sent to your endpoint. Your application receives events (email bounces, transcoding results, alerts) without any further handshake.
The Bad Docs
As a developer implementing SNS, you would likely find documentation quickly. Confirm your Amazon SNS subscription describes the process:
After subscribing to an Amazon SNS topic, Amazon SNS sends a confirmation message to your endpoint. This message contains a
SubscribeURLthat you must use to confirm the subscription.Your endpoint must be set up to listen for incoming messages from Amazon SNS. When the confirmation message arrives, extract the
SubscribeURLfrom the message.Once you have the
SubscribeURL, you can confirm the subscription in one of two ways:
- Automatic confirmation — Your endpoint can automatically confirm the subscription by sending an HTTP GET request to the
SubscribeURL. This method does not require manual intervention.- Manual confirmation — If automatic confirmation is not set up, copy the
SubscribeURLfrom the confirmation message and paste it into your browser's address bar. This confirms the subscription manually.You can also verify the subscription status using the Amazon SNS console.
AWS's official example repository awsdocs/aws-doc-sdk-examples also includes an Elastic Transcoder notification handler that does exactly this:
// JobStatusNotificationsSampleNotificationHandler.php
// Read raw POST body
$data = file_get_contents('php://input');
$notification = json_decode($data, true);
if ($notification['Type'] == 'SubscriptionConfirmation') {
// ...
echo 'url: ', $notification['SubscribeURL'];
$response = file_get_contents($notification['SubscribeURL']);
// ...
}
With only this context, implementing automatic confirmation can effectively introduce SSRF into your application. An attacker who can reach the endpoint can control the SubscribeURL unless messages are validated first.
The Good Docs
Other AWS documentation does describe verifying SNS messages correctly:
- Step 1: Make sure your endpoint is ready to process Amazon SNS messages
- Verifying the signatures of Amazon SNS messages
When should you verify Amazon SNS signatures?
- When Amazon SNS sends a notification message to your HTTP(S) endpoint.
- When Amazon SNS sends a confirmation message to your endpoint after a Subscribe or Unsubscribe API call.
To correctly verify SNS message signatures, follow these best practices:
- Always retrieve the signing certificate using HTTPS to prevent interception.
- Check that the certificate is issued by Amazon SNS.
- Confirm that the certificate chain of trust is valid.
- Ensure the certificate URL is SNS-signed and expected.
- Do not trust certificate data from the message without validation.
- Reject messages with unexpected
TopicArnvalues.- Use AWS SDK validation logic when available.
Sample data sent from SNS:
{
"Type" : "SubscriptionConfirmation",
"MessageId" : "165545c9-2a5c-472c-8df2-7ff2be2b3b1b",
"Token" : "2336412f37f...",
"TopicArn" : "arn:aws:sns:us-west-2:123456789012:MyTopic",
"Message" : "You have chosen to subscribe to the topic...",
"SubscribeURL" : "https://sns.us-west-2.amazonaws.com/?Action=ConfirmSubscription&...",
"Timestamp" : "2012-04-26T20:45:04.751Z",
"SignatureVersion" : "1",
"Signature" : "EXAMPLEpH+...",
"SigningCertURL" : "https://sns.us-west-2.amazonaws.com/SimpleNotificationService-...pem"
}
Each message includes enough data for asymmetric signature verification. AWS signs with a private key, your application fetches a public key certificate from SigningCertURL, then verifies Signature against the signed message fields.
A minimal verification example:
import base64
import requests
from cryptography import x509
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import padding
cert = x509.load_pem_x509_certificate(requests.get(message["SigningCertURL"]).content)
public_key = cert.public_key()
public_key.verify(
base64.b64decode(message["Signature"]),
build_string_to_sign(message),
padding.PKCS1v15(),
hashes.SHA256() # or SHA1 for SignatureVersion 1
)
AWS has also published PHP and JavaScript validators that include host restrictions for certificate URLs:
private static $defaultHostPattern
= '/^sns\.[a-zA-Z0-9\-]{3,}\.amazonaws\.com(\.cn)?$/';
CVE-2026-32096
Using a few search dorks to test this pattern at scale, GitHub code search returned over a thousand hits:
SubscribeURL SubscriptionConfirmation language:php
SubscribeURL SubscriptionConfirmation language:python
SubscribeURL SubscriptionConfirmation language:...
After filtering by activity and relevance, and triaging candidates, I reported the issue to multiple projects. One of them was Plunk, an open-source email platform with ~4,900 stars on GitHub.
I submitted a security advisory for an SSRF vulnerability in its SNS webhook handler, which was assigned CVE-2026-32096.
Timeline
- March 2, 2026 - Vulnerability identified during SNS SSRF research
- March 3, 2026 - Reported to maintainer via GitHub security advisory
- March 3, 2026 - Fix committed (v0.7.0)
- March 5, 2026 - GHSA-xpqg-p8mp-7g44 published
- March 5, 2026 - CVE-2026-32096 assigned
Shoutout to @driaug for the quick response and patch.
I also submitted a report to AWS through HackerOne regarding insecure sample code in awsdocs/aws-doc-sdk-examples.
References
AWS Documentation
- AWS Simple Notification Service (SNS)
- Confirm your Amazon SNS subscription
- Make sure your endpoint is ready to process Amazon SNS messages
- Verifying the signatures of Amazon SNS messages
AWS Repositories
CVEs and Advisories
- CVE-2026-32096 - Plunk SSRF
- GHSA-xpqg-p8mp-7g44 - Plunk security advisory
- CVE-2019-6715 - W3 Total Cache WordPress SSRF