VAITP Dataset

← Back to the dataset

CVE-2026-33234

SSRF in AutoGPT's SendEmailBlock allows internal network port scanning.

  • CVSS 5.0
  • CWE-918
  • Design Defects
  • Remote

AutoGPT is a workflow automation platform for creating, deploying, and managing continuous artificial intelligence agents. In versions 0.1.0 through 0.6.51, SendEmailBlock in autogpt_platform/backend/backend/blocks/email_block.py accepts a user-supplied smtp_server (string) and smtp_port (integer) as per-execution block inputs, then passes them directly to Python's smtplib.SMTP() to open a raw TCP connection with no IP address validation. This completely bypasses the platform's hardened SSRF protections in backend/util/request.py — the validate_url_host() function and BLOCKED_IP_NETWORKS blocklist that every other block uses to block connections to private, loopback, link-local, and cloud metadata addresses. An authenticated user on a shared AutoGPT deployment can use this to perform non-blind internal network port scanning and service fingerprinting: smtplib reads the target's TCP banner on connect and embeds it in the exception message, which is persisted as user-visible block output via the execution framework. This issue has been fixed in version 0.6.52.

CVSS base score
5.0
Published
2026-05-19
OWASP
A10 Server-Side Request Forgery
Orthogonal defect classification
Checking
Code defect classification
Missing Check
Category
Design Defects
Subcategory
Server-Side Request Forgery (SSRF)
Accessibility scope
Remote
Impact
Information Disclosure
Affected component
AutoGPT
Fixed by upgrading
Yes

Solution

Upgrade to AutoGPT version 0.6.52 or later.

Vulnerable code sample

import smtplib

class SendEmailBlock:
    """
    A block for sending an email.
    """

    def execute(self, inputs: dict) -> str:
        """
        Sends an email using the provided SMTP server and credentials.
        """
        smtp_server = inputs.get("smtp_server")
        smtp_port = inputs.get("smtp_port")
        
        try:
            # The vulnerability is here: smtp_server and smtp_port are used directly
            # without validation, bypassing the platform's SSRF protections.
            with smtplib.SMTP(smtp_server, smtp_port, timeout=5) as server:
                # In a real use case, this would be followed by login, sendmail, etc.
                # For the exploit, the connection attempt is sufficient.
                pass
            return "Successfully connected to the SMTP server."
        except Exception as e:
            # The exception, which may contain the target's banner, is returned
            # to the user, leaking internal network information.
            return f"Failed to connect: {e}"

Patched code sample

import smtplib
import socket
import ipaddress
from typing import List

# Simplified representation of the platform's SSRF protection blocklist,
# as mentioned in the CVE description.
BLOCKED_IP_NETWORKS: List[ipaddress.IPv4Network | ipaddress.IPv6Network] = [
    ipaddress.ip_network("127.0.0.0/8"),  # Loopback
    ipaddress.ip_network("10.0.0.0/8"),  # Private
    ipaddress.ip_network("172.16.0.0/12"),  # Private
    ipaddress.ip_network("192.168.0.0/16"),  # Private
    ipaddress.ip_network("169.254.0.0/16"),  # Link-local
    ipaddress.ip_network("0.0.0.0/8"),  # Reserved
    ipaddress.ip_network("::1/128"),  # IPv6 Loopback
    ipaddress.ip_network("fc00::/7"),  # IPv6 Unique Local
    ipaddress.ip_network("fe80::/10"),  # IPv6 Link-local
]


def validate_host_ip(host: str):
    """
    Resolves a hostname to an IP address and checks it against the blocklist.
    This function represents the core of the fix, applying security checks
    that were previously bypassed.
    """
    try:
        ip_info = socket.getaddrinfo(host, 0, family=socket.AF_UNSPEC)
        # Use the first resolved IP address for validation
        ip_str = ip_info[0][4][0]
        ip_addr = ipaddress.ip_address(ip_str)

        for blocked_net in BLOCKED_IP_NETWORKS:
            if ip_addr in blocked_net:
                raise ConnectionRefusedError(
                    f"Connection to {host} ({ip_addr}) is forbidden."
                )
    except socket.gaierror as e:
        raise ConnectionRefusedError(f"Could not resolve hostname: {host}") from e


class SendEmailBlock:
    """
    A representative example of the fixed SendEmailBlock.
    """
    def execute(self, smtp_server: str, smtp_port: int):
        """
        Executes the email sending logic with SSRF protection.
        """
        try:
            # FIX: The user-supplied smtp_server is now validated against a
            # blocklist of reserved IP ranges before any connection is attempted.
            validate_host_ip(smtp_server)

            # The original vulnerable call, now safe to execute after validation.
            with smtplib.SMTP(smtp_server, smtp_port, timeout=5) as server:
                # In a real implementation, server.login() and server.sendmail()
                # would be called here.
                print(f"Successfully connected to {smtp_server}:{smtp_port}")
                return "Connection successful (simulation)."

        except (ConnectionRefusedError, smtplib.SMTPException, socket.timeout) as e:
            # The exception now comes from our validation or a legitimate
            # connection issue, not from scanning an internal network.
            print(f"Failed to connect: {e}")
            return f"Failed to connect: {e}"

# Example Usage:
# if __name__ == "__main__":
#     fixed_block = SendEmailBlock()
#
#     # This call will be blocked by the new validation logic.
#     print("--- Attempting to connect to a blocked address ---")
#     fixed_block.execute(smtp_server="127.0.0.1", smtp_port=25)
#
#     print("\n--- Attempting to connect to a valid public address ---")
#     # This call will pass validation but may fail to connect if the server
#     # is not a real SMTP server, which is expected behavior.
#     fixed_block.execute(smtp_server="smtp.gmail.com", smtp_port=587)

Payload

{
  "block_id": "send_email",
  "inputs": {
    "from_address": "attacker@example.com",
    "to_address": "victim@example.com",
    "subject": "SSRF Port Scan",
    "body": "Scanning internal port.",
    "smtp_server": "127.0.0.1",
    "smtp_port": 22,
    "smtp_username": "",
    "smtp_password": ""
  }
}

Cite this entry

@misc{vaitp:cve202633234,
  title        = {{SSRF in AutoGPT's SendEmailBlock allows internal network port scanning.}},
  author       = {Bogaerts, Fr\'ed\'eric and Ivaki, Naghmeh and Fonseca, Jos\'e},
  year         = {2026},
  note         = {VAITP Python Vulnerability Dataset, entry CVE-2026-33234},
  howpublished = {\url{https://netpack.pt/vaitp/vulnerability/CVE-2026-33234/}}
}
Introducing the "VAITP dataset": a specialized repository of Python vulnerabilities and patches, meticulously compiled for the use of the security research community. As Python's prominence grows, understanding and addressing potential security vulnerabilities become crucial. Crafted by and for the cybersecurity community, this dataset offers a valuable resource for researchers, analysts, and developers to analyze and mitigate the security risks associated with Python. Through the comprehensive exploration of vulnerabilities and corresponding patches, the VAITP dataset fosters a safer and more resilient Python ecosystem, encouraging collaborative advancements in programming security.

The supreme art of war is to subdue the enemy without fighting.

Sun Tzu – “The Art of War”

:: Shaping the future through research and ingenuity ::