GHSA-FGX4-P8XF-QHP9

Vulnerability from github – Published: 2025-10-17 17:46 – Updated: 2025-10-17 21:32
VLAI?
Summary
Lobe Chat vulnerable to Server-Side Request Forgery with native web fetch module
Details

Vulnerability Description


Vulnerability Overview

  • When the client sends an arbitrary URL array and impl: ["naive"] to the tRPC endpoint tools.search.crawlPages, the server issues outbound HTTP requests directly to those URLs. There is no defensive logic that restricts or validates requests to internal networks (127.0.0.1, localhost, private ranges) or metadata endpoints (169.254.169.254).

  • Flow: client input (urls, impls) → service invocation in the tRPC router → the service passes the URLs to Crawler.crawl → the Crawler prioritizes the user-specified impls (naive) → the naive implementation performs a server-side fetch(url) as-is (SSRF) → the server collects responses from internal resources.

  • In the dev environment, authentication can be bypassed using the lobe-auth-dev-backend-api: 1 header (production requires a valid token). In the PoC, this was used to successfully retrieve the internal API at localhost:8889 from the server side.

Vulnerable Code

https://github.com/lobehub/lobe-chat/blob/d942a635b36a231156c60d824afa573af8032572/packages/web-crawler/src/crawImpl/naive.ts#L39-L45

PoC


PoC Description

  • In dev mode, we made a single tRPC call using the auth-bypass header lobe-auth-dev-backend-api: 1. Since tRPC requires the body to be in the form {"json": { ... }}, we placed urls and impls: ["naive"] inside json to induce the server to request the internal URL (http://localhost:8889/internel-api).

  • The response follows tRPC’s wrapping structure, so the actual body of the internal API is included as a string (JSON string) at result.data.json.results[0].data.content. We post-process it with jq for readability.

curl Example

curl -sS -X POST 'http://localhost:3010/trpc/tools/search.crawlPages' \
  -H 'Content-Type: application/json' \
  -H 'lobe-auth-dev-backend-api: 1' \
  --data '{"json":{"urls":["http://localhost:8889/internal-api"],"impls":["naive"]}}' | jq -r '.result.data.json.results[0].data.content' | jq .

poc

Impact


  • Since the server performs outbound requests to internal networks, localhost, and metadata endpoints, an attacker can abuse the server’s network position to access internal resources (internal APIs, management ports, cloud metadata, etc.).

  • As a result, this can lead to exposure of internal system information, leakage of authentication tokens/secret keys (e.g., IMDSv1/v2), misuse of internal admin interfaces, and provide a foothold for further lateral movement.

  • By leveraging user-supplied impls to force the unfiltered naive implementation, SSRF defenses—such as blocking private/metadata IPs, DNS re-validation/re-resolution, and redirect restrictions—can be bypassed.

Show details on source website

{
  "affected": [
    {
      "database_specific": {
        "last_known_affected_version_range": "\u003c= 1.136.1"
      },
      "package": {
        "ecosystem": "npm",
        "name": "@lobehub/chat"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "1.136.2"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2025-62505"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-918"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2025-10-17T17:46:09Z",
    "nvd_published_at": "2025-10-17T19:15:38Z",
    "severity": "LOW"
  },
  "details": "### Vulnerability Description\n---\n\nVulnerability Overview\n \n- When\u00a0the client sends an arbitrary\u00a0URL\u00a0array and\u00a0impl:\u00a0[\"naive\"]\u00a0to the tRPC endpoint\u00a0tools.search.crawlPages, the server\u00a0issues outbound HTTP requests\u00a0directly to those URLs. There is no\u00a0defensive logic that restricts or validates requests to internal networks (127.0.0.1, localhost, private ranges) or\u00a0metadata endpoints (169.254.169.254).\n\n- Flow: client input (urls,\u00a0impls) \u2192 service\u00a0invocation in the tRPC router\u00a0\u2192 the service passes the URLs\u00a0to\u00a0Crawler.crawl\u00a0\u2192 the\u00a0Crawler\u00a0prioritizes the user-specified\u00a0impls\u00a0(naive)\u00a0\u2192 the\u00a0naive\u00a0implementation performs a server-side\u00a0fetch(url)\u00a0as-is\u00a0(SSRF) \u2192 the\u00a0server collects responses from\u00a0internal resources.\n\n- In the\u00a0dev environment, authentication can\u00a0be bypassed using the\u00a0lobe-auth-dev-backend-api: 1\u00a0header (production\u00a0requires a valid\u00a0token). In the PoC, this was used to successfully retrieve\u00a0the internal API at\u00a0localhost:8889\u00a0from the server side.\n\nVulnerable\u00a0Code\n \n\nhttps://github.com/lobehub/lobe-chat/blob/d942a635b36a231156c60d824afa573af8032572/packages/web-crawler/src/crawImpl/naive.ts#L39-L45\n\n\n### PoC\n---\n\nPoC Description\n\n- In\u00a0dev\u00a0mode, we made a single tRPC call using the auth-bypass header\u00a0lobe-auth-dev-backend-api: 1. Since tRPC requires the\u00a0body to\u00a0be\u00a0in the form\u00a0{\"json\": {\u00a0... }}, we\u00a0placed\u00a0urls\u00a0and\u00a0impls: [\"naive\"]\u00a0inside\u00a0json\u00a0to\u00a0induce the\u00a0server to\u00a0request the\u00a0internal URL\u00a0(http://localhost:8889/internel-api).\n\n- The\u00a0response follows\u00a0tRPC\u2019s wrapping\u00a0structure, so\u00a0the actual body\u00a0of\u00a0the internal\u00a0API is\u00a0included\u00a0as a\u00a0string\u00a0(JSON string) at\u00a0result.data.json.results[0].data.content. We\u00a0post-process\u00a0it\u00a0with\u00a0jq\u00a0for\u00a0readability.\n\ncurl Example \n\n```bash\ncurl -sS -X POST \u0027http://localhost:3010/trpc/tools/search.crawlPages\u0027 \\\n  -H \u0027Content-Type: application/json\u0027 \\\n  -H \u0027lobe-auth-dev-backend-api: 1\u0027 \\\n  --data \u0027{\"json\":{\"urls\":[\"http://localhost:8889/internal-api\"],\"impls\":[\"naive\"]}}\u0027 | jq -r \u0027.result.data.json.results[0].data.content\u0027 | jq .\n```\n\u003cimg width=\"1916\" height=\"851\" alt=\"poc\" src=\"https://github.com/user-attachments/assets/f3ad34da-f8ac-4e29-9360-3cf1d1f706d8\" /\u003e\n\n\n### Impact\n---\n\n- Since the server performs outbound requests to internal networks, localhost, and metadata endpoints, an attacker can abuse the server\u2019s\u00a0network position to access internal resources (internal APIs, management ports, cloud metadata, etc.).\n\n- As a result, this can lead\u00a0to exposure of internal system information, leakage of authentication tokens/secret keys (e.g., IMDSv1/v2), misuse of internal admin interfaces, and\u00a0provide a foothold for further lateral movement.\n\n- By leveraging user-supplied\u00a0impls\u00a0to force the unfiltered\u00a0naive\u00a0implementation, SSRF defenses\u2014such as blocking private/metadata IPs, DNS re-validation/re-resolution, and\u00a0redirect restrictions\u2014can be bypassed.",
  "id": "GHSA-fgx4-p8xf-qhp9",
  "modified": "2025-10-17T21:32:47Z",
  "published": "2025-10-17T17:46:09Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/lobehub/lobe-chat/security/advisories/GHSA-fgx4-p8xf-qhp9"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2025-62505"
    },
    {
      "type": "WEB",
      "url": "https://github.com/lobehub/lobe-chat/commit/8d59583dca16f218b99213d641733d8ba77f182c"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/lobehub/lobe-chat"
    },
    {
      "type": "WEB",
      "url": "https://github.com/lobehub/lobe-chat/blob/d942a635b36a231156c60d824afa573af8032572/packages/web-crawler/src/crawImpl/naive.ts#L39-L45"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:H/PR:H/UI:N/S:C/C:L/I:N/A:N",
      "type": "CVSS_V3"
    }
  ],
  "summary": "Lobe Chat vulnerable to Server-Side Request Forgery with native web fetch module"
}


Log in or create an account to share your comment.




Tags
Taxonomy of the tags.


Loading…

Loading…

Loading…

Sightings

Author Source Type Date

Nomenclature

  • Seen: The vulnerability was mentioned, discussed, or observed by the user.
  • Confirmed: The vulnerability has been validated from an analyst's perspective.
  • Published Proof of Concept: A public proof of concept is available for this vulnerability.
  • Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
  • Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
  • Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
  • Not confirmed: The user expressed doubt about the validity of the vulnerability.
  • Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.


Loading…

Detection rules are retrieved from Rulezet.

Loading…

Loading…