Firefox DNS Lookups with the browser.dns.resolve() API

This article provides an overview of how the browser.dns.resolve() API functions within the Mozilla Firefox web browser to empower privacy and security extensions. By granting extensions the ability to perform direct Domain Name System (DNS) lookups, this API allows developers to inspect IP addresses, uncover disguised trackers, and verify encrypted DNS usage. We will cover the mechanics of the API, the required permissions, and the specific ways security tools use it to protect users from malicious network activity before a web connection is fully established.

Understanding the browser.dns.resolve() API

In standard web environments, browser extensions are largely restricted from seeing the underlying network resolution process. They can see the URL a browser requests, but not the actual IP address or DNS records associated with that URL.

Firefox bridges this gap with the browser.dns.resolve() API. To use it, an extension must first declare the "dns" permission in its manifest.json file. Once granted, the extension can pass a hostname into the function, which then queries the browser's internal DNS service and returns a Promise.

When the Promise resolves, it provides an object containing:

  • addresses: An array of IPv4 and/or IPv6 addresses associated with the hostname.
  • canonicalName: The canonical name (CNAME) for the queried host, if requested.
  • isTRR: A boolean indicating whether the resolution was performed using a Trusted Recursive Resolver, such as DNS over HTTPS (DoH).

Customizing Lookups with Flags

The API accepts an optional array of flags as a second parameter to modify how the DNS lookup is performed. The most relevant flags for security extensions include:

  • canonical_name: Requests the canonical name of the host in addition to its IP addresses.
  • bypass_cache: Forces the browser to perform a fresh DNS lookup rather than relying on the local DNS cache.
  • disable_trr: Instructs the browser not to use the Trusted Recursive Resolver (DoH) for this specific query, falling back to the operating system's resolver.
  • offline: Only checks the browser's internal DNS cache without sending any packets over the network.

How Privacy and Security Extensions Use the API

By integrating browser.dns.resolve() with other browser APIs—most notably the webRequest API—extensions can intercept network traffic, resolve the destination domain, and decide whether to allow or block the connection based on the DNS data.

1. Defeating CNAME Cloaking

Trackers frequently bypass traditional ad-blockers using a technique called CNAME cloaking. A website will create a first-party subdomain (e.g., metrics.example.com) and use a DNS CNAME record to point it to a third-party tracking server (e.g., tracker.adnetwork.com). Standard extensions only see the safe-looking first-party URL.

By using browser.dns.resolve() with the canonical_name flag, Firefox privacy extensions can unmask the true destination of the subdomain. If the returned canonicalName matches a known tracker list, the extension blocks the request.

2. IP-Based Threat Intelligence

Malicious actors often register new domains rapidly to evade domain-based blocklists, while hosting these domains on the same underlying server infrastructure. Security extensions can resolve a newly encountered domain to retrieve its addresses array. If the resulting IP address belongs to a known malicious subnet, a botnet command-and-control server, or a restricted geographical region, the extension can terminate the connection before any data is exchanged.

3. Preventing DNS Spoofing and Ensuring Encryption

Because the API returns the isTRR boolean, security extensions can monitor whether a user's DNS queries are safely routed through Firefox’s encrypted DNS over HTTPS (DoH) feature. If an extension detects that sensitive domains are being resolved with isTRR returning false, it can alert the user that their DNS queries are being handled by the local network and may be vulnerable to ISP snooping or local DNS spoofing.

4. Detecting Local Network Fingerprinting

Malicious scripts on public websites sometimes attempt to scan a user's local network by making requests to public domains that resolve to local, private IP addresses (such as 192.168.1.1 or 127.0.0.1), a technique known as DNS rebinding. Extensions use browser.dns.resolve() to check if an external domain resolves to a private IP address space. If it does, the extension blocks the request, preventing the external website from interacting with the user's local router or devices.

5. Respecting Browser Proxy Settings

Unlike external applications that use the operating system's network stack, browser.dns.resolve() operates strictly within the context of the Firefox browser. This means any lookups performed by the extension automatically respect the user's configured Firefox proxy settings and DoH configurations, preventing accidental DNS leaks that could compromise user anonymity.