Finding
TorznabClient::download checks only for a magnet: prefix before fetching the URL with the configured HTTP client. Any other URL — http://169.254.169.254/latest/meta-data/ (cloud metadata), http://localhost:6379/ (Redis), or any LAN-internal service — is fetched unconditionally. The url originates from SearchResult.download_url, which is populated from item.link in the indexer-supplied XML, a field a malicious or compromised indexer fully controls. NewznabClient::download has no scheme guard at all, not even the magnet check.
Evidence
crates/zetesis/src/client/torznab.rs:191 fetches any non-magnet URL with no further validation:
if url.starts_with("magnet:") {
return Ok(DownloadResponse::MagnetUri(url.to_string()));
}
let body = self.fetch_xml(url, ct).await?;
crates/zetesis/src/client/torznab.rs:110 shows the URL is attacker-controlled XML:
let download_url = item.link.unwrap_or_default();
crates/zetesis/src/client/newznab.rs:182 (NewznabClient::download) fetches with no scheme guard whatsoever.
Why this matters
A malicious indexer response drives the Harmonia process into HTTP requests against arbitrary internal addresses. In cloud environments this reaches instance-metadata APIs that vend credentials; on the LAN it reaches NAS management UIs, Synology, or other services that trust intra-network callers without authentication. The response body is recoverable to the attacker through the Torznab parse-error path, which surfaces the fetched body in error messages — turning blind SSRF into a data-exfiltration primitive.
Desired correction
Before calling fetch_xml in download(), validate that the URL scheme is http or https, and reject hosts that resolve to loopback, link-local, or private address ranges (mandatory under the LAN counter-surveillance threat model). Apply the same guard to NewznabClient::download. Done when: download() invoked with http://169.254.169.254/ or http://localhost/ returns an error without issuing any network request, and the guard is shared by both the Torznab and Newznab clients.
Finding
TorznabClient::downloadchecks only for amagnet:prefix before fetching the URL with the configured HTTP client. Any other URL —http://169.254.169.254/latest/meta-data/(cloud metadata),http://localhost:6379/(Redis), or any LAN-internal service — is fetched unconditionally. Theurloriginates fromSearchResult.download_url, which is populated fromitem.linkin the indexer-supplied XML, a field a malicious or compromised indexer fully controls.NewznabClient::downloadhas no scheme guard at all, not even the magnet check.Evidence
crates/zetesis/src/client/torznab.rs:191fetches any non-magnet URL with no further validation:crates/zetesis/src/client/torznab.rs:110shows the URL is attacker-controlled XML:crates/zetesis/src/client/newznab.rs:182(NewznabClient::download) fetches with no scheme guard whatsoever.Why this matters
A malicious indexer response drives the Harmonia process into HTTP requests against arbitrary internal addresses. In cloud environments this reaches instance-metadata APIs that vend credentials; on the LAN it reaches NAS management UIs, Synology, or other services that trust intra-network callers without authentication. The response body is recoverable to the attacker through the Torznab parse-error path, which surfaces the fetched body in error messages — turning blind SSRF into a data-exfiltration primitive.
Desired correction
Before calling
fetch_xmlindownload(), validate that the URL scheme ishttporhttps, and reject hosts that resolve to loopback, link-local, or private address ranges (mandatory under the LAN counter-surveillance threat model). Apply the same guard toNewznabClient::download. Done when:download()invoked withhttp://169.254.169.254/orhttp://localhost/returns an error without issuing any network request, and the guard is shared by both the Torznab and Newznab clients.