Skip to content

SSRF Vulnerability in SuperAGI #1476

@J1vvoo

Description

@J1vvoo

⚠️ Check for existing issues before proceeding. ⚠️

  • I have searched the existing issues, and there is no existing issue for my problem

Where are you using SuperAGI?

Linux

Which branch of SuperAGI are you using?

Dev (branch)

Do you use OpenAI GPT-3.5 or GPT-4?

GPT-3.5

Which area covers your issue best?

Installation and setup

Describe your issue.

Vulnerability Description


Vulnerability Overview

The SuperAGI backend (superagi-backend) contains a Server-Side Request Forgery (SSRF) vulnerability in the /verify_end_point endpoint of models_controller.

The endpoint accepts a user-supplied query parameter end_point and forwards it without validation into an internal HuggingFace object, which performs an outbound requests.post() to self.end_point. Because there is no input sanitization, normalization, or domain whitelist, an attacker can supply arbitrary URLs — including link-local or internal metadata endpoints such as http://169.254.169.254/ — causing the backend to initiate requests to internal resources.

Vulnerable Code

  1. The endpoint /models_controller/verify_end_point accepts the end_point query parameter and forwards it to ModelsHelper.validate_end_point() without validation.
    https://github.com/TransformerOptimus/SuperAGI/blob/main/superagi/controllers/models_controller.py#L64-L70

    @router.get("/verify_end_point", status_code=200)
    async def verify_end_point(model_api_key: str = None, end_point: str = None, model_provider: str = None):
        try:
            return ModelsHelper.validate_end_point(model_api_key, end_point, model_provider)
        except Exception as e:
            logging.error(f"Error validating Endpoint: {str(e)}")
            raise HTTPException(status_code=500, detail="Internal Server Error")

    end_point is user-supplied via the query string and is forwarded downstream with no filtering, normalization, or domain restrictions.

  2. ModelsHelper.validate_end_point() constructs a HuggingFace instance using the untrusted end_point and immediately calls .verify_end_point().

    https://github.com/TransformerOptimus/SuperAGI/blob/main/superagi/helper/models_helper.py#L3-L17

    class ModelsHelper:
        @staticmethod
        def validate_end_point(model_api_key, end_point, model_provider):
            response = {"success": True}
    
            if model_provider == 'Hugging Face':
                try:
                    result = HuggingFace(api_key=model_api_key, end_point=end_point).verify_end_point()
                except Exception as e:
                    response['success'] = False
                    response['error'] = str(e)
                else:
                    response['result'] = result
    
            return response

    → No sanitization, normalization, or domain whitelist is applied to end_point prior to usage.

  3. Inside the HuggingFace class, the attacker-controlled end_point becomes self.end_point and is directly used as the destination of an outbound HTTP request.

    https://github.com/TransformerOptimus/SuperAGI/blob/main/superagi/llms/hugging_face.py#L107-L111

    class HuggingFace(BaseLlm):
        def verify_end_point(self):
            data = json.dumps({"inputs": "validating end_point"})
            response = requests.post(self.end_point, headers=self.headers, data=data)
            return response.json()

    self.end_point is derived entirely from user input and is passed to requests.post() without validation, making this a direct SSRF sink.

  4. This flow allows arbitrary outbound requests from the backend server to any URL, including internal or link-local addresses such as http://169.254.169.254/.

    The complete taint flow:

    User-controlled input: end_point
      ↓
    models_controller.verify_end_point()
      ↓
    ModelsHelper.validate_end_point()
      ↓
    HuggingFace(api_key, end_point)
      ↓
    requests.post(self.end_point, headers, data)
    

    → Because the backend performs the HTTP call using the host’s network stack, an attacker can leverage this to reach internal services (including metadata endpoints), enabling SSRF-based information disclosure or other attacks.

How to replicate your Issue?

PoC


PoC Description
I spun up a metadata server locally on the host (listening on port 9000), then invoked the backend verification endpoint with the end_point parameter pointing to the host gateway reachable from the container plus the metadata path. The SuperAGI backend runs in the superagi-backend-1 Docker container and serves on port 8001; from the container the Docker bridge gateway 172.17.0.1 is reachable.

PoC

curl -v "http://localhost:8001/models_controller/verify_end_point?end_point=http://172.17.0.1:9000/latest/meta-data/instance-id&model_provider=Hugging%20Face"
Image

Impact


  • Cloud credential theft (High): SSRF to 169.254.169.254 can expose IAM tokens / temporary credentials, enabling access to cloud resources (S3, databases, etc.).
  • Internal data/service disclosure: Attackers can read internal-only endpoints (admin panels, internal APIs, DB endpoints).
  • Lateral movement & privilege escalation: Leaked credentials or internal data can be used to move across the network or escalate access.
  • Reconnaissance & abuse: SSRF enables internal service discovery, port probing, and can be used to overload internal services or poison logs.
  • Wide attack surface if unauthenticated: Since the endpoint is callable without strong auth, the risk and attack surface increase significantly.

Upload Error Log Content

Blank

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions