Public mode

No access to your tenant or devices. Every item links to its source. What this means

Some sources, documents or advisories need attention: 274/275 feeds/APIs · 469/469 docs · 8/9 advisories · checked 22:09 UTC Customize Public modeDiscuss ChangeIntel on Discord

Cloudreve: SSRF guard bypass: checkIP does not decode IPv6-transition wrappers (NAT64, IPv4-compatible, 6to4) reaching internal and cloud-metadata addresses

Collected exploitation and prediction evidence

Risk source coverage

CISA KEV is observed exploitation evidence. FIRST EPSS is a dated prediction of exploitation in the next 30 days. Missing scores are unknown. This collector requests predictions only for explicit CVE aliases in the public NuGet archive; Microsoft release views retain their existing prediction scope.

No collected risk observation for these identifiers. This does not establish absence of exploitation or a zero probability.

cve-program · CVE-2026-79913

Published

Cloudreve is a self-hosted file management and sharing system. Prior to 4.18.0, the ValidateExternalURL server-side request forgery guard in pkg/request/ssrf.go passes resolved addresses to checkIP without decoding NAT64, IPv4-compatible, and 6to4 IPv4-in-IPv6 transition forms. An authenticated user with remote-download access can provide SrcUri through RemoteDownloadTask.createDownloadTask so a wrapper embedding a loopback, private, link-local, or cloud metadata IPv4 address is classified as public and fetched, exposing internal service responses and cloud instance credentials. IPv4-mapped IPv6 addresses remain blocked because Go converts that form with net.IP.To4. This issue is fixed in version 4.18.0.

Source published
22 Sep 2026 15:24:33 UTC
Source modified
22 Sep 2026 17:44:01 UTC
Observed here
23 Oct 2026 15:48:27 UTC
Source terms
CVE Program Terms of Use

Original source record · Cite this exact observation · Complete original publisher JSON

This view projects the publisher's source fields for reading; the original JSON retains additional fields and CVE enrichment containers. Attribution: cve-program · CVE Program Terms of Use. Source text is retained; field grouping and change labels are provided by ChangeIntel.

CVSS 3.1 · 6.5 CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N

euvd · EUVD-2026-84527

Published

Cloudreve is a self-hosted file management and sharing system. Prior to 4.18.0, the ValidateExternalURL server-side request forgery guard in pkg/request/ssrf.go passes resolved addresses to checkIP without decoding NAT64, IPv4-compatible, and 6to4 IPv4-in-IPv6 transition forms. An authenticated user with remote-download access can provide SrcUri through RemoteDownloadTask.createDownloadTask so a wrapper embedding a loopback, private, link-local, or cloud metadata IPv4 address is classified as public and fetched, exposing internal service responses and cloud instance credentials. IPv4-mapped IPv6 addresses remain blocked because Go converts that form with net.IP.To4. This issue is fixed in version 4.18.0.

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.

Original publisher date fields

datePublished: Sep 22, 2026, 3:24:33 PM

dateUpdated: Sep 22, 2026, 5:44:01 PM

Source published
Sep 22, 2026, 3:24:33 PM (timezone not stated)
Source modified
Sep 22, 2026, 5:44:01 PM (timezone not stated)
Observed here
11 Nov 2026 16:10:06 UTC
Source terms
ENISA EUVD · source terms and attribution apply

Original source record · Cite this exact observation · Complete original publisher JSON

This view projects the publisher's source fields for reading; the original JSON retains additional fields and CVE enrichment containers. Attribution: euvd · ENISA EUVD · source terms and attribution apply. Source text is retained; field grouping and change labels are provided by ChangeIntel.

EUVD CVSS 3.1 · 6.5 CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N

nvd · CVE-2026-79913

Published

Cloudreve is a self-hosted file management and sharing system. Prior to 4.18.0, the ValidateExternalURL server-side request forgery guard in pkg/request/ssrf.go passes resolved addresses to checkIP without decoding NAT64, IPv4-compatible, and 6to4 IPv4-in-IPv6 transition forms. An authenticated user with remote-download access can provide SrcUri through RemoteDownloadTask.createDownloadTask so a wrapper embedding a loopback, private, link-local, or cloud metadata IPv4 address is classified as public and fetched, exposing internal service responses and cloud instance credentials. IPv4-mapped IPv6 addresses remain blocked because Go converts that form with net.IP.To4. This issue is fixed in version 4.18.0.

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.

Source analysis status: Deferred

Weakness classifications: CWE-697 · CWE-918

Original publisher date fields

published: 2026-09-22T16:17:57.033

lastModified: 2026-09-22T18:17:19.667

Source published
22 Sep 2026 16:17:57 UTC
Source modified
22 Sep 2026 18:17:19 UTC
Observed here
25 Oct 2026 16:19:10 UTC
Source terms
NIST NVD usage terms; underlying source attribution retained

Original source record · Cite this exact observation · Complete original publisher JSON

This view projects the publisher's source fields for reading; the original JSON retains additional fields and CVE enrichment containers. Attribution: nvd · NIST NVD usage terms; underlying source attribution retained. Source text is retained; field grouping and change labels are provided by ChangeIntel.

CVSS 3.1 · [email protected] · Secondary · 6.5 CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N

osv · GHSA-jvh5-97xg-v99f

Published

**Summary** Cloudreve's server-side request forgery guard `ValidateExternalURL` (`pkg/request/ssrf.go`) resolves a user-supplied URL host and rejects it when any resolved IP is a loopback, private, link-local, multicast, unspecified, CGNAT, or the cloud-metadata address. The classification is performed by `checkIP`, which uses Go's `net.IP` builtins (`IsLoopback`, `IsPrivate`, `IsLinkLocalUnicast`, ...) directly on the resolved address. These builtins inspect only the outer IPv6 address and do not decode IPv4-in-IPv6 transition wrappers. An attacker who controls a hostname's AAAA record (or, on a DNS64/NAT64 network, any hostname) can point the remote-download URL at a NAT64 well-known-prefix address (`64:ff9b::a.b.c.d`, RFC 6052), an IPv4-compatible address (`::a.b.c.d`, RFC 4291), or a 6to4 address (`2002:AABB:CCDD::`, RFC 3056) that wraps an internal IPv4. Go classifies these wrappers as ordinary global IPv6 addresses, so `checkIP` accepts them; the network then delivers the request to the embedded internal IPv4 (loopback, RFC 1918, or the cloud instance metadata service `169.254.169.254`). This bypasses the SSRF guard that was added to block direct access to internal services. **Affected component and versions** - Component: `pkg/request/ssrf.go` (`ValidateExternalURL` / `checkIP`), reached from the remote-download workflow `pkg/filemanager/workflows/remote_download.go` (`RemoteDownloadTask.createDownloadTask`, which passes the user-supplied `SrcUri` to `ValidateExternalURL`). - Affected: Cloudreve `<= 4.17.0` (latest release at time of report) and current `main`. - Reachable by an authenticated remote-download user; administrative privileges are not required. **Vulnerable form vs correctly-guarded sibling** `checkIP` DOES block IPv4-mapped IPv6 (`::ffff:a.b.c.d`), because Go's `net.IP.To4()` returns the embedded IPv4 for that form and the standard checks then fire. It does NOT block the other IPv4-in-IPv6 transition forms, because for those `To4()` returns nil and every `net.IP` classifier reports the wrapper as a normal global IPv6 address: - NAT64 well-known prefix `64:ff9b::/96` (RFC 6052): `64:ff9b::a9fe:a9fe` embeds `169.254.169.254`. - IPv4-compatible `::a.b.c.d` (RFC 4291): `::a9fe:a9fe` embeds `169.254.169.254`. - 6to4 `2002::/16` (RFC 3056): `2002:a9fe:a9fe::` embeds `169.254.169.254`. The fix is to canonicalize the resolved address to its embedded IPv4 before classification, symmetric to how IPv4-mapped addresses are already handled by `To4()`. The same gap was fixed correctly in a sibling project: `makeplane/plane` `apps/api/plane/utils/ip_address.py` `_embedded_ipv4()` decodes IPv4-mapped, 6to4, Teredo and NAT64 before classifying; Cloudreve's guard is the unpatched twin of that pattern. **Severity** An authenticated low-privilege user can force the server to fetch attacker-chosen internal URLs and read the responses, including cloud instance-metadata credentials, producing a scope change from the download subsystem to the internal network and the host's cloud identity. **Proof of concept** The guard file `pkg/request/ssrf.go` imports only the Go standard library, so `ValidateExternalURL` was compiled and called verbatim from tag `4.17.0`. The remote-download workflow calls it as `ValidateExternalURL(ctx, SrcUri, opt)` with default options. Direction 1 (shipped guard accepts the internal-embedding wrappers): ``` === Cloudreve v4.17.0 ValidateExternalURL (shipped, unmodified) === [ACCEPTED] NAT64 -> 169.254.169.254 (cloud metadata) http://[64:ff9b::a9fe:a9fe]/latest/meta-data/ [ACCEPTED] NAT64 -> 127.0.0.1 (loopback) http://[64:ff9b::7f00:1]/ [ACCEPTED] NAT64 -> 10.0.0.1 (RFC1918) http://[64:ff9b::a00:1]/ [ACCEPTED] IPv4-compatible -> 169.254.169.254 http://[::a9fe:a9fe]/latest/meta-data/ [ACCEPTED] IPv4-compatible -> 127.0.0.1 http://[::7f00:1]/ [ACCEPTED] 6to4 -> encodes 169.254.169.254 http://[2002:a9fe:a9fe::]/ [BLOCKED ] IPv4-mapped -> 127.0.0.1 (CONTROL, should block) http://[::ffff:127.0.0.1]/ -> loopback address 127.0.0.1: URL is not allowed [BLOCKED ] IPv4-mapped -> 169.254.169.254 (CONTROL, should block) http://[::ffff:169.254.169.254]/ -> link-local address 169.254.169.254: URL is not allowed [ACCEPTED] public 1.1.1.1 (CONTROL, should pass) http://1.1.1.1/ SSRF BYPASS COUNT (guard accepted an internal-embedding wrapper): 6 ``` Full reach-and-return (guard accepts, and the fetch returns the internal secret with HTTP 200). A loopback HTTP server serves a unique token standing in for the cloud metadata service; on a DNS64/NAT64 host the kernel routes `64:ff9b::a9fe:a9fe` to `169.254.169.254`, and because no NAT64 gateway exists in the test host the final hop is emulated by dialing the loopback server. The guard acceptance above is real and unmodified. ``` [*] Fake internal metadata server (stands in for 169.254.169.254) at http://127.0.0.1:63569 [*] Unique secret it serves: IMDS-SECRET-TOKEN-a9fe-2f31c7d4e9 [*] Attacker remote-download SrcUri: http://[64:ff9b::a9fe:a9fe]:63569/latest/meta-data/iam/security-credentials/ [*] 64:ff9b::a9fe:a9fe = NAT64(169.254.169.254) [+] SHIPPED GUARD ValidateExternalURL ACCEPTED the URL. checkIP classified 64:ff9b::a9fe:a9fe as a safe public address (the bug) [+] FETCH REACHED THE INTERNAL SERVER. HTTP 200 [+] Response body (exfiltrated internal secret): iam-role-credentials AccessKeyId=ASIA... SecretToken=IMDS-SECRET-TOKEN-a9fe-2f31c7d4e9 [RESULT] SSRF CONFIRMED: shipped guard PASSED a NAT64-wrapped internal IP, fetch returned internal secret "IMDS-SECRET-TOKEN-a9fe-2f31c7d4e9" with HTTP 200. ``` Direction 2 (after applying the fix below, the same inputs are blocked and public destinations still pass): ``` === Cloudreve guard WITH FIX applied === [BLOCKED ] NAT64 -> 169.254.169.254 -> link-local address 169.254.169.254: URL is not allowed [BLOCKED ] NAT64 -> 127.0.0.1 -> loopback address 127.0.0.1: URL is not allowed [BLOCKED ] NAT64 -> 10.0.0.1 -> private address 10.0.0.1: URL is not allowed [BLOCKED ] IPv4-compatible -> 169.254.169.254 -> link-local address 169.254.169.254: URL is not allowed [BLOCKED ] IPv4-compatible -> 127.0.0.1 -> loopback address 127.0.0.1: URL is not allowed [BLOCKED ] 6to4 -> 169.254.169.254 -> link-local address 169.254.169.254: URL is not allowed [BLOCKED ] IPv4-mapped -> 127.0.0.1 (control) -> loopback address 127.0.0.1: URL is not allowed [ACCEPTED] public 1.1.1.1 (control, should PASS) [ACCEPTED] public 8.8.8.8 (control, should PASS) Remaining bypasses after fix: 0 (expect 0) ``` **Impact** An authenticated remote-download user can make the server issue HTTP(S) requests to arbitrary internal addresses and read the responses. On cloud deployments this includes the instance metadata service `169.254.169.254`, from which the attacker can retrieve IAM role credentials, leading to escalation into the cloud account. It also exposes internal-only services (databases, admin panels, other microservices) that rely on network position for their security, and enables internal network reconnaissance. This is a scope change from the download subsystem to the internal network and the host's cloud identity. **Suggested fix** Canonicalize the resolved address to its embedded IPv4 before the range checks, so `checkIP` classifies the address the request will actually reach rather than the routable IPv6 wrapper. Minimal patch: ```diff --- a/pkg/request/ssrf.go +++ b/pkg/request/ssrf.go @@ func checkIPWithAllowlist ... return checkIP(ip) } + +// effectiveIP unwraps IPv4-in-IPv6 transition forms to the IPv4 address the +// packet ultimately reaches, so checkIP classifies the real target rather than +// the (often globally-routable) IPv6 wrapper. Covers IPv4-mapped +// (::ffff:a.b.c.d), NAT64 well-known prefix (64:ff9b::/96, RFC 6052), +// 6to4 (2002::/16, RFC 3056) and IPv4-compatible (::a.b.c.d). +func effectiveIP(ip net.IP) net.IP { + if v4 := ip.To4(); v4 != nil { + return v4 + } + v6 := ip.To16() + if v6 == nil { + return ip + } + if v6[0] == 0x00 && v6[1] == 0x64 && v6[2] == 0xff && v6[3] == 0x9b && + v6[4] == 0 && v6[5] == 0 && v6[6] == 0 && v6[7] == 0 && + v6[8] == 0 && v6[9] == 0 && v6[10] == 0 && v6[11] == 0 { + return net.IPv4(v6[12], v6[13], v6[14], v6[15]).To4() + } + if v6[0] == 0x20 && v6[1] == 0x02 { + return net.IPv4(v6[2], v6[3], v6[4], v6[5]).To4() + } + allZeroTop := true + for i := 0; i < 12; i++ { + if v6[i] != 0 { + allZeroTop = false + break + } + } + if allZeroTop { + last := uint32(v6[12])<<24 | uint32(v6[13])<<16 | uint32(v6[14])<<8 | uint32(v6[15]) + if last > 1 { + return net.IPv4(v6[12], v6[13], v6[14], v6[15]).To4() + } + } + return ip +} + func checkIP(ip net.IP) error { + ip = effectiveIP(ip) if ip == nil { return fmt.Errorf("invalid IP: %w", ErrUnsafeURL) } ``` As defense in depth, consider rejecting all non-IPv4-mapped IPv4-embedding IPv6 forms outright unless the deployment intentionally uses NAT64. **Credit** tonghuaroot ([email protected]).

Source published
22 Sep 2026 20:40:41 UTC
Source modified
1 Oct 2026 20:56:00 UTC
Observed here
24 Oct 2026 13:19:41 UTC
Source terms
GitHub Advisory Database · CC-BY-4.0

Original source record · Cite this exact observation · Complete original publisher JSON

This view projects the publisher's source fields for reading; the original JSON retains additional fields and CVE enrichment containers. Attribution: osv · GitHub Advisory Database · CC-BY-4.0. Source text is retained; field grouping and change labels are provided by ChangeIntel.

CVSS_V3 · CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N

Publisher rating · MODERATE

osv · GO-2026-6572

Published

Cloudreve: SSRF guard bypass: checkIP does not decode IPv6-transition wrappers (NAT64, IPv4-compatible, 6to4) reaching internal and cloud-metadata addresses in github.com/cloudreve/Cloudreve

Source published
1 Oct 2026 20:23:38 UTC
Source modified
1 Oct 2026 20:45:14 UTC
Observed here
24 Oct 2026 13:19:41 UTC
Source terms
OSV · upstream source license applies

Original source record · Cite this exact observation · Complete original publisher JSON

This view projects the publisher's source fields for reading; the original JSON retains additional fields and CVE enrichment containers. Attribution: osv · OSV · upstream source license applies. Source text is retained; field grouping and change labels are provided by ChangeIntel.

ChangeIntel

An IT change radar: releases, security, known issues, retirements, documentation changes, and service status from public sources. Every item links to supporting evidence; dates and statuses can change after they are read.

Sources read 11 Nov 22:09 UTC · 274 of 275 readable · 272 fully read · documentation 469/469 current