Dragonfly scheduler v1 and v2 gRPC unauthenticated SSRF via attacker-controlled PeerHost in DownloadTinyFile (CVE-2026-54637)
## Summary The Dragonfly **scheduler**'s v1 gRPC service contains an unauthenticated Server-Side Request Forgery (SSRF). When a peer reports a successful download of a TINY task, the scheduler calls `Peer.DownloadTinyFile()` and issues an HTTP `GET` to a host and port taken verbatim from the attacker-controlled `PeerHost.Ip` / `PeerHost.DownPort` fields of the gRPC request body. The HTTP client uses a bare `http.Transport` with no address validation, so a remote, unauthenticated client can force the scheduler to connect to arbitrary internal addresses, including `127.0.0.1` (loopback), `169.254.0.0/16` (link-local, e.g. cloud metadata), and RFC1918 ranges. The fetched response is stored in `Task.DirectPiece` and can subsequently be served to other peers, making this a read-SSRF with a data-exfiltration path. The manager's preheat code path already wraps its HTTP client with `nethttp.NewSafeDialer()` (which rejects non-global-unicast destinations); the scheduler's `DownloadTinyFile` path is missing this guard (sibling gap). ## Severity Medium. The attack requires no authentication (the scheduler gRPC server runs with insecure transport credentials by default and has no auth interceptor), and the destination is fully attacker-controlled. Impact is limited to read-SSRF: blind reachability probing of internal hosts/ports plus exfiltration of up to `TinyFileSize` (128) bytes per task from internal HTTP services into `Task.DirectPiece`. It is not remote code execution, and `PeerHost.DownPort` is constrained by proto validation to `>= 1024`, which excludes destination port 80. ## Affected component - Repository: `dragonflyoss/dragonfly` - Go module: `d7y.io/dragonfly/v2` - Component: scheduler, v1 gRPC protocol - Affected file: `scheduler/resource/standard/peer.go` (`DownloadTinyFile`), reached via `scheduler/service/service_v1.go` (`storeHost`, `RegisterPeerTask`, `ReportPeerResult`, `handlePeerSuccess`) - Verified against: latest release `v2.4.4-rc.2` (commit `0822e3aecc3369017d6b25c9441ff6f318129b31`) ## Description / Root cause The scheduler exposes the v1 gRPC service without authentication by default: - In [`scheduler/scheduler.go` lines 235-246](https://github.com/dragonflyoss/dragonfly/blob/0822e3aecc3369017d6b25c9441ff6f318129b31/scheduler/scheduler.go#L235-L246), mTLS is only configured when `cfg.Server.TLS != nil`; otherwise the server is created with `rpc.NewInsecureCredentials()`. - The default configuration produced by [`scheduler/config/config.go` `New()` (line 336)](https://github.com/dragonflyoss/dragonfly/blob/0822e3aecc3369017d6b25c9441ff6f318129b31/scheduler/config/config.go#L336-L355) does not set `Server.TLS`, so the default deployment uses insecure credentials. - The gRPC interceptor chain in [`pkg/rpc/scheduler/server/server.go` lines 71-86](https://github.com/dragonflyoss/dragonfly/blob/0822e3aecc3369017d6b25c9441ff6f318129b31/pkg/rpc/scheduler/server/server.go#L71-L86) contains ratelimit, error-conversion, prometheus, zap-logging, validator, and recovery interceptors, but **no authentication interceptor**. A remote client can therefore invoke `RegisterPeerTask` and `ReportPeerResult` without credentials. The `PeerHost` message carried in the request is consumed by [`storeHost` in `scheduler/service/service_v1.go` lines 816-845](https://github.com/dragonflyoss/dragonfly/blob/0822e3aecc3369017d6b25c9441ff6f318129b31/scheduler/service/service_v1.go#L816-L845), which copies `peerHost.Ip` and `peerHost.DownPort` directly into `resource.Host.IP` and `resource.Host.DownloadPort` with no destination-address restriction. The proto validator only requires `PeerHost.Ip` to be a syntactically valid IP (`net.ParseIP != nil`) and `DownPort` in `[1024, 65535)`; it does not restrict the address to global-unicast, so `127.0.0.1`, `169.254.169.254`, and RFC1918 addresses all pass validation. When the reported peer is a TINY task, [`handlePeerSuccess` lines 1176-1202](https://github.com/dragonflyoss/dragonfly/blob/0822e3aecc3369017d6b25c9441ff6f318129b31/scheduler/service/service_v1.go#L1176-L1202) calls `peer.DownloadTinyFile()` and stores the result in `peer.Task.DirectPiece`. The sink, [`DownloadTinyFile` lines 435-478](https://github.com/dragonflyoss/dragonfly/blob/0822e3aecc3369017d6b25c9441ff6f318129b31/scheduler/resource/standard/peer.go#L435-L478), builds the URL from `net.JoinHostPort(p.Host.IP, p.Host.DownloadPort)` and dispatches it through a bare `http.Transport` (`TLSClientConfig: InsecureSkipVerify: true`) with no `DialContext`/socket control: ```golang targetURL := url.URL{ Scheme: "http", Host: net.JoinHostPort(p.Host.IP, strconv.Itoa(int(p.Host.DownloadPort))), Path: fmt.Sprintf("download/%s/%s", p.Task.ID[:3], p.Task.ID), RawQuery: fmt.Sprintf("peerId=%s", p.ID), } req, err := http.NewRequestWithContext(ctx, http.MethodGet, targetURL.String(), nil) if err != nil { return []byte{}, err } req.Header.Set(headers.Range, fmt.Sprintf("bytes=%d-%d", 0,
AI Analysis
Technical Summary
The Dragonfly scheduler's v1 gRPC service exposes an unauthenticated SSRF via the DownloadTinyFile function. When a peer reports a successful tiny task download, the scheduler issues an HTTP GET request to the IP and port specified in the attacker-controlled PeerHost.Ip and PeerHost.DownPort fields without validating the destination address. The HTTP client uses a bare http.Transport with no address filtering, allowing requests to internal IPs including loopback, link-local, and RFC1918 ranges. The fetched response is stored in Task.DirectPiece and can be served to other peers, enabling data exfiltration of up to 128 bytes per request. The scheduler runs with insecure transport credentials by default and lacks authentication interceptors, allowing remote unauthenticated clients to invoke vulnerable RPC methods. The port is restricted to >=1024 by proto validation, excluding port 80. This vulnerability was verified in version 2.4.4-rc.3.
Potential Impact
An unauthenticated remote attacker can exploit this SSRF vulnerability to make the scheduler connect to arbitrary internal network addresses and ports (>=1024). This enables blind reachability probing of internal hosts and limited data exfiltration (up to 128 bytes) from internal HTTP services into the scheduler's Task.DirectPiece field, which can then be served to other peers. There is no remote code execution or write capability. The impact is limited to information disclosure and network reconnaissance within the internal environment accessible to the scheduler.
Mitigation Recommendations
Patch status is not yet confirmed — check the vendor advisory for current remediation guidance. Until a fix is available, users should avoid deploying the scheduler with default insecure transport credentials and should enable mTLS or other authentication mechanisms to restrict access to the gRPC service. Additionally, network-level controls should restrict access to the scheduler service to trusted clients only. Review and update the scheduler configuration to enable TLS and authentication interceptors to prevent unauthenticated access.
Dragonfly scheduler v1 and v2 gRPC unauthenticated SSRF via attacker-controlled PeerHost in DownloadTinyFile (CVE-2026-54637)
Description
## Summary The Dragonfly **scheduler**'s v1 gRPC service contains an unauthenticated Server-Side Request Forgery (SSRF). When a peer reports a successful download of a TINY task, the scheduler calls `Peer.DownloadTinyFile()` and issues an HTTP `GET` to a host and port taken verbatim from the attacker-controlled `PeerHost.Ip` / `PeerHost.DownPort` fields of the gRPC request body. The HTTP client uses a bare `http.Transport` with no address validation, so a remote, unauthenticated client can force the scheduler to connect to arbitrary internal addresses, including `127.0.0.1` (loopback), `169.254.0.0/16` (link-local, e.g. cloud metadata), and RFC1918 ranges. The fetched response is stored in `Task.DirectPiece` and can subsequently be served to other peers, making this a read-SSRF with a data-exfiltration path. The manager's preheat code path already wraps its HTTP client with `nethttp.NewSafeDialer()` (which rejects non-global-unicast destinations); the scheduler's `DownloadTinyFile` path is missing this guard (sibling gap). ## Severity Medium. The attack requires no authentication (the scheduler gRPC server runs with insecure transport credentials by default and has no auth interceptor), and the destination is fully attacker-controlled. Impact is limited to read-SSRF: blind reachability probing of internal hosts/ports plus exfiltration of up to `TinyFileSize` (128) bytes per task from internal HTTP services into `Task.DirectPiece`. It is not remote code execution, and `PeerHost.DownPort` is constrained by proto validation to `>= 1024`, which excludes destination port 80. ## Affected component - Repository: `dragonflyoss/dragonfly` - Go module: `d7y.io/dragonfly/v2` - Component: scheduler, v1 gRPC protocol - Affected file: `scheduler/resource/standard/peer.go` (`DownloadTinyFile`), reached via `scheduler/service/service_v1.go` (`storeHost`, `RegisterPeerTask`, `ReportPeerResult`, `handlePeerSuccess`) - Verified against: latest release `v2.4.4-rc.2` (commit `0822e3aecc3369017d6b25c9441ff6f318129b31`) ## Description / Root cause The scheduler exposes the v1 gRPC service without authentication by default: - In [`scheduler/scheduler.go` lines 235-246](https://github.com/dragonflyoss/dragonfly/blob/0822e3aecc3369017d6b25c9441ff6f318129b31/scheduler/scheduler.go#L235-L246), mTLS is only configured when `cfg.Server.TLS != nil`; otherwise the server is created with `rpc.NewInsecureCredentials()`. - The default configuration produced by [`scheduler/config/config.go` `New()` (line 336)](https://github.com/dragonflyoss/dragonfly/blob/0822e3aecc3369017d6b25c9441ff6f318129b31/scheduler/config/config.go#L336-L355) does not set `Server.TLS`, so the default deployment uses insecure credentials. - The gRPC interceptor chain in [`pkg/rpc/scheduler/server/server.go` lines 71-86](https://github.com/dragonflyoss/dragonfly/blob/0822e3aecc3369017d6b25c9441ff6f318129b31/pkg/rpc/scheduler/server/server.go#L71-L86) contains ratelimit, error-conversion, prometheus, zap-logging, validator, and recovery interceptors, but **no authentication interceptor**. A remote client can therefore invoke `RegisterPeerTask` and `ReportPeerResult` without credentials. The `PeerHost` message carried in the request is consumed by [`storeHost` in `scheduler/service/service_v1.go` lines 816-845](https://github.com/dragonflyoss/dragonfly/blob/0822e3aecc3369017d6b25c9441ff6f318129b31/scheduler/service/service_v1.go#L816-L845), which copies `peerHost.Ip` and `peerHost.DownPort` directly into `resource.Host.IP` and `resource.Host.DownloadPort` with no destination-address restriction. The proto validator only requires `PeerHost.Ip` to be a syntactically valid IP (`net.ParseIP != nil`) and `DownPort` in `[1024, 65535)`; it does not restrict the address to global-unicast, so `127.0.0.1`, `169.254.169.254`, and RFC1918 addresses all pass validation. When the reported peer is a TINY task, [`handlePeerSuccess` lines 1176-1202](https://github.com/dragonflyoss/dragonfly/blob/0822e3aecc3369017d6b25c9441ff6f318129b31/scheduler/service/service_v1.go#L1176-L1202) calls `peer.DownloadTinyFile()` and stores the result in `peer.Task.DirectPiece`. The sink, [`DownloadTinyFile` lines 435-478](https://github.com/dragonflyoss/dragonfly/blob/0822e3aecc3369017d6b25c9441ff6f318129b31/scheduler/resource/standard/peer.go#L435-L478), builds the URL from `net.JoinHostPort(p.Host.IP, p.Host.DownloadPort)` and dispatches it through a bare `http.Transport` (`TLSClientConfig: InsecureSkipVerify: true`) with no `DialContext`/socket control: ```golang targetURL := url.URL{ Scheme: "http", Host: net.JoinHostPort(p.Host.IP, strconv.Itoa(int(p.Host.DownloadPort))), Path: fmt.Sprintf("download/%s/%s", p.Task.ID[:3], p.Task.ID), RawQuery: fmt.Sprintf("peerId=%s", p.ID), } req, err := http.NewRequestWithContext(ctx, http.MethodGet, targetURL.String(), nil) if err != nil { return []byte{}, err } req.Header.Set(headers.Range, fmt.Sprintf("bytes=%d-%d", 0,
CVSS v4.0
Affected software
Run on your own infrastructure? Check whether these packages are installed with threat-finder — our free open-source scanner.
Weaknesses
AI-Powered Analysis
Machine-generated threat intelligence
Technical Analysis
The Dragonfly scheduler's v1 gRPC service exposes an unauthenticated SSRF via the DownloadTinyFile function. When a peer reports a successful tiny task download, the scheduler issues an HTTP GET request to the IP and port specified in the attacker-controlled PeerHost.Ip and PeerHost.DownPort fields without validating the destination address. The HTTP client uses a bare http.Transport with no address filtering, allowing requests to internal IPs including loopback, link-local, and RFC1918 ranges. The fetched response is stored in Task.DirectPiece and can be served to other peers, enabling data exfiltration of up to 128 bytes per request. The scheduler runs with insecure transport credentials by default and lacks authentication interceptors, allowing remote unauthenticated clients to invoke vulnerable RPC methods. The port is restricted to >=1024 by proto validation, excluding port 80. This vulnerability was verified in version 2.4.4-rc.3.
Potential Impact
An unauthenticated remote attacker can exploit this SSRF vulnerability to make the scheduler connect to arbitrary internal network addresses and ports (>=1024). This enables blind reachability probing of internal hosts and limited data exfiltration (up to 128 bytes) from internal HTTP services into the scheduler's Task.DirectPiece field, which can then be served to other peers. There is no remote code execution or write capability. The impact is limited to information disclosure and network reconnaissance within the internal environment accessible to the scheduler.
Mitigation Recommendations
Patch status is not yet confirmed — check the vendor advisory for current remediation guidance. Until a fix is available, users should avoid deploying the scheduler with default insecure transport credentials and should enable mTLS or other authentication mechanisms to restrict access to the gRPC service. Additionally, network-level controls should restrict access to the scheduler service to trusted clients only. Review and update the scheduler configuration to enable TLS and authentication interceptors to prevent unauthenticated access.
Technical Details
- Gcve Source
- db.gcve.eu
- Osv Id
- GHSA-chwm-m7g7-685g
- Osv Schema Version
- 1.4.0
- Aliases
- ["CVE-2026-54637"]
- Ecosystems
- ["Go"]
- Database Specific Severity
- MODERATE
- Cvss Version
- 4.0
Threat ID: 6a4c340327e9c797195f5f4a
Added to database: 07/06/2026, 23:02:27 UTC
Last enriched: 07/06/2026, 23:12:52 UTC
Last updated: 07/20/2026, 04:09:03 UTC
Views: 21
Community Reviews
0 reviewsCrowdsource mitigation strategies, share intel context, and vote on the most helpful responses. Sign in to add your voice and help keep defenders ahead.
Want to contribute mitigation steps or threat intel context? Sign in or create an account to join the community discussion.
Actions
Updates to AI analysis require Pro Console access. Upgrade inside Console → Billing.
Need more coverage?
Upgrade to Pro Console for AI refresh and higher limits.
For incident response and remediation, OffSeq services can help resolve threats faster.
Latest Threats
Check if your credentials are on the dark web
Instant breach scanning across billions of leaked records. Free tier available.