Zennoxa Shield
Rules / Swift
SHIELD-SWIFT-014

SSRF via dynamic URL request

highSwiftCWE-918CVSS 7.7

What it detects

A URLSession request targets a URL constructed from variable input.

How to fix

Validate the host against an allowlist before issuing outbound requests.

Vulnerable — Shield flags thisAvatarFetcher.swift
import Foundation

func fetchAvatar(from urlString: String, completion: @escaping (Data?) -> Void) {
    // urlString is user-controlled
    guard let url = URL(string: urlString) else { return }
    URLSession.shared.dataTask(with: url) { data, _, _ in
        completion(data)
    }.resume()
}
Fixed — scans cleanAvatarFetcher.swift
import Foundation

let allowedHosts: Set<String> = ["cdn.example.com"]

func fetchAvatar(from urlString: String, completion: @escaping (Data?) -> Void) {
    guard let comps = URLComponents(string: urlString),
          comps.scheme == "https",
          let host = comps.host, allowedHosts.contains(host),
          let url = comps.url else { return }
    URLSession.shared.dataTask(with: url) { data, _, _ in
        completion(data)
    }.resume()
}

Both snippets are verified against the shipped scanner: the vulnerable one triggers SHIELD-SWIFT-014, the fixed one does not.

SHIELD-SWIFT-014: SSRF via dynamic URL request — Zennoxa Shield