Jeff Johnson (My apps, PayPal.Me, Mastodon)

Feedback Assistant Boycott

Advanced tracking and fingerprinting protection breaks Safari extensions

June 15 2024

Advanced tracking and fingerprinting protection is in the Safari Advanced Settings on both iOS and macOS. The setting has three options: disabled, enabled in private browsing, or enabled in all browsing. Last year I wrote about why I disabled advanced tracking and fingerprinting protection in Safari. This year I found another reason: it breaks my Safari extension StopTheMadness Pro! To see why, enable advanced tracking and fingerprinting protection, then click this example link: https://underpassapp.com/test/gtag.html?q=search

Here's the source code of gtag.html:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1.0">
<title>Google Analytics Example</title>
</head>
<body>
<script src="https://www.googletagmanager.com/gtag/js"></script>
<script src="https://underpassapp.com/test/gtag.js"></script>
<script src="https://lapcatsoftware.com/test/gtag.js"></script>
</body>
</html>

Here's the source code of gtag.js:

var div = document.createElement("div");
div.innerHTML = `
<p><code>document.currentScript.src = "${document.currentScript.src}"</code></p>
<p><code>location.href = "${location.href}"</code></p>
<p><code>location.search = "${location.search}"</code></p>
<hr>
`;
document.body.append(div);

And here's the output:

document.currentScript.src = "https://underpassapp.com/test/gtag.js"

location.href = "https://underpassapp.com/test/gtag.html?q=search"

location.search = "?q=search"


document.currentScript.src = "https://lapcatsoftware.com/test/gtag.js"

location.href = "https://underpassapp.com/test/gtag.html"

location.search = ""


Notice that the query string ?q=search is available to the first-party script but not to the third-party script, even though the script has the same source code in both cases. I've discovered that this divergence occurs whenever a web page loads a "known tracker", as defined by Safari advanced tracking and fingerprinting protection. The list of known trackers is stored in a file on your device. To reveal this file in macOS Finder, run the following command in Terminal app:

open -R $(getconf DARWIN_USER_CACHE_DIR)com.apple.WebPrivacy/URL_FILTER.wplist

The file consists of Safari content blocker rules. For example, here's the content blocker rule corresponding to the script https://www.googletagmanager.com/gtag/js loaded by my test page:

{"trigger":{"resource-type":["fetch","image","other","script"],"url-filter":"^[^:]+://+([^:/]+\\.)?googletagmanager\\.com\\/gtag\\/js","url-filter-is-case-sensitive":1,"load-type":["third-party"],"unless-domain":["*novaivf.com"]},"action":{"type":"block"}}

If you open the web inspector console on my test page, you'll see a message that says, "Blocked connection to known tracker https://www.googletagmanager.com/gtag/js".

For some bizarre reason, the domain novaivf.com is exempted from the content blocker rule. Nova IVF are "Fertility Specialists & Individualized IVF Protocols located in Mountain View, CA".

The way advanced tracking and fingerprinting protection appears to work is that if it blocks at least one third-party tracking script on a web page, then it also prevents every third-party script on the page from accessing the URL query string. The assumption seems to be that the existence of one confirmed tracking script on the page raises the odds of other tracking scripts that are not (yet) included in the list of known trackers. I'm guessing that the URL query string is made inaccessible because the query string could include tracking parameters, some of which are also blocked by advanced tracking and fingerprinting protection, as explained by my blog post about Safari link tracking protection.

The problem with this "protection" is that it can break innocent third-party scripts. Even worse, Safari extension content scripts are treated as third party! As a consequence, advanced tracking and fingerprinting protection breaks several features of StopTheMadness Pro. For example, there's a keyboard shortcut to copy the page URL, but the extension is prevented from accessing the full, correct URL.

The query-hiding behavior that I've described in this blog post is not documented by Safari, as far as I know. I had to discover everything through a long process of trial and error after a strange bug report from a customer. By the way, it happens only as the result of a link click. If you copy the URL https://underpassapp.com/test/gtag.html?q=search and paste it into the Safari address bar, the googletagmanager script still gets blocked, but other third-party scripts, including Safari extensions, get proper access to the URL query. The difference seems a bit odd, because if all third-party scripts are considered suspect in one case, why are they considered innocent in the other case?

Feedback Assistant Boycott

Jeff Johnson (My apps, PayPal.Me, Mastodon)