Every CVE Search/ Get API key

CVE-2026-55640

Nextcloud MCP Server: Unauthenticated `POST /webhooks/nextcloud` allows arbitrary vector data deletion when `WEBHOOK_SECRET` is unset ( default )

9.1 CriticalFix available

Nextcloud MCP Server is a production-ready MCP server that connects AI assistants to a Nextcloud instance. Prior to 0.117.2, the POST /webhooks/nextcloud endpoint in nextcloud_mcp_server/vector/webhook_receiver.py has no authentication by default because WEBHOOK_SECRET defaults to None and startup validation does not require it. When WEBHOOK_SECRET is unset, handle_nextcloud_webhook() accepts unauthenticated requests. The payload["user"]["uid"] field parsed in nextcloud_mcp_server/vector/webhook_parser.py is attacker-controlled and is used without an authenticated-session cross-check for Qdrant operations, allowing a network attacker to delete or trigger re-indexing of vector embeddings for any user and to destroy the semantic search index by sending forged deletion events. This issue is fixed in version 0.117.2.

Attack profile

How easy it is to exploit

Attack vector
Network
Complexity
Low
Privileges needed
None
User interaction
None

What an attacker can affect

Confidentiality
None
Integrity
High
Availability
High

Exploit likelihood

0.73%Up 0.2 points since Aug 26, 2026
90%50%10%1%

What each source reports

CVE List Score used 9.1

Nextcloud MCP Server: Unauthenticated `POST /webhooks/nextcloud` allows arbitrary vector data deletion when `WEBHOOK_SECRET` is unset ( default )

Nextcloud MCP Server is a production-ready MCP server that connects AI assistants to a Nextcloud instance. Prior to 0.117.2, the POST /webhooks/nextcloud endpoint in nextcloud_mcp_server/vector/webhook_receiver.py has no authentication by default because WEBHOOK_SECRET defaults to None and startup validation does not require it. When WEBHOOK_SECRET is unset, handle_nextcloud_webhook() accepts unauthenticated requests. The payload["user"]["uid"] field parsed in nextcloud_mcp_server/vector/webhook_parser.py is attacker-controlled and is used without an authenticated-session cross-check for Qdrant operations, allowing a network attacker to delete or trigger re-indexing of vector embeddings for any user and to destroy the semantic search index by sending forged deletion events. This issue is fixed in version 0.117.2.

Record
CVE-2026-55640
CVSS 3.1
9.1 CriticalCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:H
Weakness
CWE-306
Updated
2026-11-02
EUVDEUVD-2026-65596 9.1

Nextcloud MCP Server is a production-ready MCP server that connects AI assistants to a Nextcloud instance. Prior to 0.117.2, the POST /webhooks/nextcloud endpoint in nextcloud_mcp_server/vector/webhook_receiver.py has no authentication by default because WEBHOOK_SECRET defaults to None and startup validation does not require it. When WEBHOOK_SECRET is unset, handle_nextcloud_webhook() accepts unauthenticated requests. The payload["user"]["uid"] field parsed in nextcloud_mcp_server/vector/webhook_parser.py is attacker-controlled and is used without an authenticated-session cross-check for Qdrant operations, allowing a network attacker to delete or trigger re-indexing of vector embeddings for any user and to destroy the semantic search index by sending forged deletion events. This issue is fixed in version 0.117.2.

Record
EUVD-2026-65596
CVSS 3.1
9.1 CriticalCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:H
Updated
2026-11-02
GitHub AdvisoriesGHSA-8vh3-g2qg-2h2c 9.1

nextcloud-mcp-server: Unauthenticated `POST /webhooks/nextcloud` allows arbitrary vector data deletion when `WEBHOOK_SECRET` is unset ( default )

Summary

The POST /webhooks/nextcloud endpoint has no authentication by default: WEBHOOK_SECRET defaults to None and is never required by startup validation. When unset, the receiver accepts any unauthenticated POST. The user_id is taken directly from the attacker-supplied payload and passed to Qdrant, allowing an unauthenticated attacker to delete or corrupt vector embeddings for any user.

Details

Vulnerable file: nextcloud_mcp_server/vector/webhook_receiver.py, function handle_nextcloud_webhook(), lines 55-67

Root cause 1: Auth check is guarded by if secret: - skipped entirely when WEBHOOK_SECRET is unset.

Root cause 2: webhook_secret: str | None = None in config - no startup validator enforces it, even when vector sync is enabled.

Trusted field: payload["user"]["uid"] in webhook_parser.py is used as-is for all Qdrant operations - no cross-check against an authenticated session.

webhook_receiver.py, lines 55-67:

secret = get_settings().webhook_secret  # None by default
if secret:                           # skipped entirely when unset
    ... validate Bearer header ...
else:
    _warn_missing_secret_once()     # just logs, still processes

webhook_parser.py, line 57:

user_id = payload["user"]["uid"]     # attacker-controlled

PoC

No credentials required. Works on any deployment where WEBHOOK_SECRET is not explicitly set (the default).

POST /webhooks/nextcloud
Content-Type: application/json

{
  "event": {
    "class": "OCP\\Files\\Events\\Node\\BeforeNodeDeletedEvent",
    "node": { "path": "/victim/files/Notes/any.md", "id": 12345 }
  },
  "user": { "uid": "victim" },
  "time": 0
}

Result: Qdrant deletes all vector embeddings for victim doc 12345 with no authentication. Attacker can loop over doc IDs for mass deletion. All user targets accepted.

Impact

  • Anyone on the network with access to port 8000 - no credentials needed.
  • Attacker can delete or trigger re-index of any user's vector embeddings in Qdrant by spoofing user.uid in the payload.
  • Mass-sending delete events for all doc IDs destroys the entire semantic search index for all users, requiring a full re-scan to recover.

Recommend Fix

  1. Enforce WEBHOOK_SECRET at startup ( file config_validators.py )
if vector_sync_enabled and not settings.webhook_secret:
    raise ConfigurationError(
        "WEBHOOK_SECRET must be set when vector sync is enabled"
    )
  1. Reject requests when secret is unset ( file webhook_receiver.py )
secret = get_settings().webhook_secret
if not secret:
    return JSONResponse({"status": "unavailable"}, status_code=503)
provided = request.headers.get("authorization", "").encode()
if not hmac.compare_digest(provided, f"Bearer {secret}".encode()):
    return JSONResponse({"status": "unauthorized"}, status_code=401)
Record
GHSA-8vh3-g2qg-2h2c
CVSS 3.1
9.1 CriticalCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:H
Weakness
CWE-306
Updated
2026-11-02
NVD 9.1

Nextcloud MCP Server is a production-ready MCP server that connects AI assistants to a Nextcloud instance. Prior to 0.117.2, the POST /webhooks/nextcloud endpoint in nextcloud_mcp_server/vector/webhook_receiver.py has no authentication by default because WEBHOOK_SECRET defaults to None and startup validation does not require it. When WEBHOOK_SECRET is unset, handle_nextcloud_webhook() accepts unauthenticated requests. The payload["user"]["uid"] field parsed in nextcloud_mcp_server/vector/webhook_parser.py is attacker-controlled and is used without an authenticated-session cross-check for Qdrant operations, allowing a network attacker to delete or trigger re-indexing of vector embeddings for any user and to destroy the semantic search index by sending forged deletion events. This issue is fixed in version 0.117.2.

Record
CVE-2026-55640
CVSS 3.1
9.1 CriticalCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:H
Weakness
CWE-306
Updated
2026-11-02
OSV 9.1

Nextcloud MCP Server: Unauthenticated `POST /webhooks/nextcloud` allows arbitrary vector data deletion when `WEBHOOK_SECRET` is unset ( default )

Nextcloud MCP Server is a production-ready MCP server that connects AI assistants to a Nextcloud instance. Prior to 0.117.2, the POST /webhooks/nextcloud endpoint in nextcloud_mcp_server/vector/webhook_receiver.py has no authentication by default because WEBHOOK_SECRET defaults to None and startup validation does not require it. When WEBHOOK_SECRET is unset, handle_nextcloud_webhook() accepts unauthenticated requests. The payload["user"]["uid"] field parsed in nextcloud_mcp_server/vector/webhook_parser.py is attacker-controlled and is used without an authenticated-session cross-check for Qdrant operations, allowing a network attacker to delete or trigger re-indexing of vector embeddings for any user and to destroy the semantic search index by sending forged deletion events. This issue is fixed in version 0.117.2.

Record
CVE-2026-55640
CVSS 3.1
9.1 CriticalCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:H
Weakness
CWE-306
Updated
2026-11-02
OSVGHSA-8vh3-g2qg-2h2c 9.1

nextcloud-mcp-server: Unauthenticated `POST /webhooks/nextcloud` allows arbitrary vector data deletion when `WEBHOOK_SECRET` is unset ( default )

Summary

The POST /webhooks/nextcloud endpoint has no authentication by default: WEBHOOK_SECRET defaults to None and is never required by startup validation. When unset, the receiver accepts any unauthenticated POST. The user_id is taken directly from the attacker-supplied payload and passed to Qdrant, allowing an unauthenticated attacker to delete or corrupt vector embeddings for any user.

Details

Vulnerable file: nextcloud_mcp_server/vector/webhook_receiver.py, function handle_nextcloud_webhook(), lines 55-67

Root cause 1: Auth check is guarded by if secret: - skipped entirely when WEBHOOK_SECRET is unset.

Root cause 2: webhook_secret: str | None = None in config - no startup validator enforces it, even when vector sync is enabled.

Trusted field: payload["user"]["uid"] in webhook_parser.py is used as-is for all Qdrant operations - no cross-check against an authenticated session.

webhook_receiver.py, lines 55-67:

secret = get_settings().webhook_secret  # None by default
if secret:                           # skipped entirely when unset
    ... validate Bearer header ...
else:
    _warn_missing_secret_once()     # just logs, still processes

webhook_parser.py, line 57:

user_id = payload["user"]["uid"]     # attacker-controlled

PoC

No credentials required. Works on any deployment where WEBHOOK_SECRET is not explicitly set (the default).

POST /webhooks/nextcloud
Content-Type: application/json

{
  "event": {
    "class": "OCP\\Files\\Events\\Node\\BeforeNodeDeletedEvent",
    "node": { "path": "/victim/files/Notes/any.md", "id": 12345 }
  },
  "user": { "uid": "victim" },
  "time": 0
}

Result: Qdrant deletes all vector embeddings for victim doc 12345 with no authentication. Attacker can loop over doc IDs for mass deletion. All user targets accepted.

Impact

  • Anyone on the network with access to port 8000 - no credentials needed.
  • Attacker can delete or trigger re-index of any user's vector embeddings in Qdrant by spoofing user.uid in the payload.
  • Mass-sending delete events for all doc IDs destroys the entire semantic search index for all users, requiring a full re-scan to recover.

Recommend Fix

  1. Enforce WEBHOOK_SECRET at startup ( file config_validators.py )
if vector_sync_enabled and not settings.webhook_secret:
    raise ConfigurationError(
        "WEBHOOK_SECRET must be set when vector sync is enabled"
    )
  1. Reject requests when secret is unset ( file webhook_receiver.py )
secret = get_settings().webhook_secret
if not secret:
    return JSONResponse({"status": "unavailable"}, status_code=503)
provided = request.headers.get("authorization", "").encode()
if not hmac.compare_digest(provided, f"Bearer {secret}".encode()):
    return JSONResponse({"status": "unauthorized"}, status_code=401)
Record
GHSA-8vh3-g2qg-2h2c
CVSS 3.1
9.1 CriticalCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:H
Weakness
CWE-306
Updated
2026-11-02
OSVPYSEC-2026-3866 9.1

nextcloud-mcp-server: Unauthenticated `POST /webhooks/nextcloud` allows arbitrary vector data deletion when `WEBHOOK_SECRET` is unset ( default )

Summary

The POST /webhooks/nextcloud endpoint has no authentication by default: WEBHOOK_SECRET defaults to None and is never required by startup validation. When unset, the receiver accepts any unauthenticated POST. The user_id is taken directly from the attacker-supplied payload and passed to Qdrant, allowing an unauthenticated attacker to delete or corrupt vector embeddings for any user.

Details

Vulnerable file: nextcloud_mcp_server/vector/webhook_receiver.py, function handle_nextcloud_webhook(), lines 55-67

Root cause 1: Auth check is guarded by if secret: - skipped entirely when WEBHOOK_SECRET is unset.

Root cause 2: webhook_secret: str | None = None in config - no startup validator enforces it, even when vector sync is enabled.

Trusted field: payload["user"]["uid"] in webhook_parser.py is used as-is for all Qdrant operations - no cross-check against an authenticated session.

webhook_receiver.py, lines 55-67:

secret = get_settings().webhook_secret  # None by default
if secret:                           # skipped entirely when unset
    ... validate Bearer header ...
else:
    _warn_missing_secret_once()     # just logs, still processes

webhook_parser.py, line 57:

user_id = payload["user"]["uid"]     # attacker-controlled

PoC

No credentials required. Works on any deployment where WEBHOOK_SECRET is not explicitly set (the default).

POST /webhooks/nextcloud
Content-Type: application/json

{
  "event": {
    "class": "OCP\\Files\\Events\\Node\\BeforeNodeDeletedEvent",
    "node": { "path": "/victim/files/Notes/any.md", "id": 12345 }
  },
  "user": { "uid": "victim" },
  "time": 0
}

Result: Qdrant deletes all vector embeddings for victim doc 12345 with no authentication. Attacker can loop over doc IDs for mass deletion. All user targets accepted.

Impact

  • Anyone on the network with access to port 8000 - no credentials needed.
  • Attacker can delete or trigger re-index of any user's vector embeddings in Qdrant by spoofing user.uid in the payload.
  • Mass-sending delete events for all doc IDs destroys the entire semantic search index for all users, requiring a full re-scan to recover.

Recommend Fix

  1. Enforce WEBHOOK_SECRET at startup ( file config_validators.py )
if vector_sync_enabled and not settings.webhook_secret:
    raise ConfigurationError(
        "WEBHOOK_SECRET must be set when vector sync is enabled"
    )
  1. Reject requests when secret is unset ( file webhook_receiver.py )
secret = get_settings().webhook_secret
if not secret:
    return JSONResponse({"status": "unavailable"}, status_code=503)
provided = request.headers.get("authorization", "").encode()
if not hmac.compare_digest(provided, f"Bearer {secret}".encode()):
    return JSONResponse({"status": "unauthorized"}, status_code=401)
Record
PYSEC-2026-3866
CVSS 3.1
9.1 CriticalCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:H
Updated
2026-11-02

Affected products

Affected packages

Affected packages
PackageAffectedFixed
nextcloud-mcp-server
PyPI
through 0.117.1
0.117.2
nextcloud-mcp-server
PyPI
before 0.117.2, plus listed versions
0.100.00.101.00.101.10.101.20.101.3
Show 45 moreShow less
0.101.40.102.00.103.00.104.00.104.10.105.00.106.00.107.00.108.00.108.10.108.20.108.30.109.00.109.10.110.00.110.10.110.20.111.00.112.00.113.00.113.10.114.00.115.00.115.10.116.00.117.00.117.10.17.10.65.30.65.40.66.00.66.10.66.20.67.00.68.00.68.10.68.20.68.30.68.40.69.00.70.00.70.10.70.20.70.30.70.4
0.117.2

History

History
RecordedChangedSources
first indexedCVE List, EUVD, GitHub Advisories, NVD, OSV

Dates are when Every CVE recorded each change. Upstream dates may differ.

In short

CVE-2026-55640 is a critical vulnerability (CVSS 9.1) in Cbcoutinho Nextcloud-mcp-server, published August 25, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.73%, the 54th percentile. Fixed in nextcloud-mcp-server 0.117.2.

References

This page doesn't list everything

Left out here: 68 versions. The JSON record has them.

MoveEnter Open