cd ../blog

CVE-2026-32096: When Documentation Becomes the Vulnerability

Vulnerability ResearchAndre HuMar 31, 20266 min read

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.

sequenceDiagram participant App as Application participant SNS as AWS SNS Note over App,SNS: One-time confirmation App->>SNS: 1. Subscribe endpoint to topic SNS->>App: 2. POST SubscriptionConfirmation (includes SubscribeURL) rect rgba(255, 0, 0, 0.1) App->>SNS: 3. GET SubscribeURL end SNS->>App: 4. Subscription confirmed Note over App,SNS: Ongoing notifications SNS->>App: 5. POST Notification SNS->>App: 6. POST Notification SNS->>App: ...

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:

  1. After subscribing to an Amazon SNS topic, Amazon SNS sends a confirmation message to your endpoint. This message contains a SubscribeURL that you must use to confirm the subscription.

  2. Your endpoint must be set up to listen for incoming messages from Amazon SNS. When the confirmation message arrives, extract the SubscribeURL from the message.

  3. 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 SubscribeURL from the confirmation message and paste it into your browser's address bar. This confirms the subscription manually.
  4. 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.

sequenceDiagram participant A as Attacker participant App as Vulnerable app participant T as "Target (internal / metadata / attacker)" Note over A,T: No valid SNS signature verified A->>App: POST fake SubscriptionConfirmation JSON rect rgba(255, 0, 0, 0.1) App->>T: GET SubscribeURL (SSRF) end T-->>App: Response (leaked metadata, scan, etc.)

The Good Docs

Other AWS documentation does describe verifying SNS messages correctly:

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 TopicArn values.
  • 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 Repositories

CVEs and Advisories

Security Resources

A

Andre Hu

PlatformSecurity Security Team

High-Impact Next Step

We find these before attackers do.

See what we would uncover in your stack with exploitability context and prioritized fixes your team can ship quickly.