Hardcoded HTTP URLs constructed with Foundation

Hardcoded HTTP URLs constructed with Foundation

Description

An http:// address created with Foundation.URL(string:) or a similar API can lead to a connection without TLS when used for communication. Constructing a URL object is not itself a network request; examine actual transmission and protection settings together.

Apple's URL Loading System blocks cleartext HTTP by default through App Transport Security (ATS), so a URLSession request normally fails without an exception. Settings such as NSAllowsArbitraryLoads or NSExceptionAllowsInsecureHTTPLoads can permit HTTP, while lower-level APIs such as Network or CFNetwork may not enforce ATS. Check the URL's use, ATS settings in Info.plist, and runtime traffic to assess actual exposure.

Potential impact

If the endpoint is reached without effective transport protection:

  • A network observer may read requests and responses.
  • An attacker may modify traffic or responses.
  • A peer may impersonate the server or redirect communication to the wrong endpoint.
  • Broad ATS exceptions may permit additional cleartext connections.

An HTTP-to-HTTPS redirect does not protect the initial HTTP request with TLS.

Remediation

  1. Use https: and confirm that the server directly provides the same resource over HTTPS. Do not rely on a redirect to protect the initial request.
  2. Keep ATS enabled and remove broad exceptions such as NSAllowsArbitraryLoads. Limit unavoidable domain exceptions to the required hosts and features, and remove them promptly.
  3. Keep development and test endpoints in separate environment configuration and out of production builds. Private or loopback addresses are not inherently secure.
  4. Retain certificate validation. Review Info.plist and actual runtime traffic to find any remaining successful HTTP connections.

Examples

Before

swift
import Foundation

func loadProfile() {
    guard let url = Foundation.URL(string: "http://api.example.com/profile") else {
        return
    }

    URLSession.shared.dataTask(with: url) { _, _, _ in }.resume()
}

After

swift
import Foundation

func loadProfile() {
    guard let url = Foundation.URL(string: "https://api.example.com/profile") else {
        return
    }

    URLSession.shared.dataTask(with: url) { _, _, _ in }.resume()
}

Explanation:

  • Before: The endpoint uses a hardcoded HTTP URL. ATS may block it, so check exceptions and whether communication actually succeeds.
  • After: A directly available HTTPS endpoint protects the request with TLS from the start.

References