Skip to main content

Latest Post

What the heck is the Public Suffix List?

•

4,545 words

•

The Public Suffix List is a registry of domain names that browsers, password managers, certificate authorities, and a heck of a lot of other software use to know exactly where one website ends and another begins.

Mozilla started it back in 2007 to fix a problem with cookies. Browsers had no way to know that co.uk belonged to thousands of unrelated companies, not one. Nearly two decades later, every major browser bundles the list, and multi-tenant platforms like GitHub Pages, Vercel, and ngrok have added thousands of entries to keep their users apart.

And it’s maintained by a small group of volunteers. This year they’ve waded through a record number of pull requests, most of which were closed without merging, and maintainers are debating in public whether to make the list harder or easier to join. For at least one longtime maintainer, that burden is reaching a breaking point, and nobody agrees on the way out.

To see why this matters, let me start with something you’ve probably already done today.

You signed in.

Let’s say that when you log in to a website like shop.example.com, it sends your browser a session cookie to keep you authenticated. Pretty normal. It asks for that cookie to apply across example.com, including the account app at account.example.com.

shop.example.com
Example StoreSign in →
Desk lamp
Notebook
account.example.com
Example StoreSign in →

Your account

J
Your profileOrders · Preferences

Later, you pop over to your account. Your browser sends the saved cookie along, which means you’re automatically logged in to your account too! It feels seamless to you even though these are different apps being served on different subdomains, which means the cookie is working exactly as expected.

How does the browser know that scope is okay? It checks the Public Suffix List.

  1. 1.Read the requested scope

    The response from shop.example.com asks the browser to save a session cookie. Its Domain attribute asks to share that cookie with example.com and its subdomains.

    Set-Cookie: session=a3f82b; Domain=example.com
  2. 2.Find the public suffix

    Is com on the list? Yes. Is example.com on it? No. The most specific match is com, so that’s the public suffix.

    example.com (public suffix: com).

  3. 3.Compare the scope with the boundary

    The requested scope, example.com, is one label below the public suffix. The browser accepts and saves the cookie.

    example.com (public suffix: com; allowed scope: example.com).

  4. 4.Visit the account app

    When you visit account.example.com, it falls within the saved cookie’s scope. Your browser sends the cookie, and the account app recognizes your session.

    Host: account.example.com
    Cookie: session=a3f82b

Now consider yummy.ngrok.pizza and scrumptious.ngrok.pizza. These are two brand-new, competing pizza delivery apps run by Alice and Bob, respectively. They’re so brand-new that they didn’t even wait until having a custom domain name to start taking orders, and imagine that in Alice’s rush, her site sends a cookie asking for a scope of ngrok.pizza. That would include Bob’s site, too!

yummy.ngrok.pizza

Alice’s Yummy Pizza

Sign in →
scrumptious.ngrok.pizza

Scrumptious Pizza

Sign in →

Your browser rejects the cookie as soon as Alice’s site tries to set it. Why? Well, if it had been accepted, it would also be valid on scrumptious.ngrok.pizza. And if that were true, Bob could read your session identifier right out of the session cookie and use that to impersonate you, which is a terribly bad situation!

You later decide you want to try a different pizza and pop over to scrumptious.ngrok.pizza. Your browser has no shared cookie from Yummy to send, because it never stored it.

The browser checks the same list, but this time it finds a different boundary.

  1. 1.Read the requested scope

    Yummy asks the browser to save a session cookie with Domain=ngrok.pizza. That scope would include Scrumptious and every other site beneath ngrok.pizza.

    Set-Cookie: session=b7d91c; Domain=ngrok.pizza
  2. 2.Find the public suffix

    Is pizza on the list? Yes. Is ngrok.pizza on it? Also yes! The longer match wins, so the public suffix is ngrok.pizza itself.

    ngrok.pizza (shorter match: pizza; public suffix: ngrok.pizza).

  3. 3.Compare the scope with the boundary

    The requested scope matches the public suffix itself. The browser rejects the cookie when Yummy tries to set it.

    ngrok.pizza (public suffix: ngrok.pizza; requested scope: ngrok.pizza).

  4. 4.Visit Scrumptious

    When you later visit scrumptious.ngrok.pizza, the browser has no shared cookie from Yummy. It was never stored, so Bob’s site never receives it.

When the browser checks the Public Suffix List, what does it look for? In the case of ngrok.pizza, it’s a single line in a plaintext file. It first matches pizza itself, but ngrok.pizza wins out by precision. The other 10,000+ rules (as of writing) are other shared domains and every top-level domain in existence.

Both example.com and ngrok.pizza have two parts separated by a dot, but the meaning of those parts is very different. The former has multiple apps that can share sessions, but the latter has many apps run by people who very likely don’t trust each other. Your browser doesn’t know which is which just by the spelling.

That single line, in this single file, holds together one pillar of trust and security in the modern-day internet.

Now, let’s figure out what makes these two pairs of apps different.

What makes ngrok.pizza a boundary but not example.com?

Both sites asked for the same thing: a cookie scoped to their parent domain. Browsers will normally allow exactly that. The difference is that ngrok.pizza is a public suffix.

A public suffix is a domain on which users can directly register additional names. That means many independent parties control the various applications and services that run on those names, like the way Alice controls yummy.ngrok.pizza and Bob controls scrumptious.ngrok.pizza. These names might share a public suffix, but they shouldn’t share cookies.

But example.com is different. Only one organization owns it, and that organization chooses to share a user’s session, via a cookie, between multiple apps.

The Public Suffix List records these public suffixes. Browsers use those entries to reject cookie scopes that would otherwise jump happily—and dangerously—into sites controlled by others.

Let’s start with the names you’ve already seen. com and pizza are top-level domains (TLDs) and public suffixes.

com (TLD: com; public suffix: com). pizza (TLD: pizza; public suffix: pizza).

The boundary doesn’t necessarily stop with the last part of a name. co.uk puts it two labels deep: first the TLD, then a second-level domain (SLD). And as we’ve already seen, ngrok.pizza does the same.

co.uk (SLD: co; TLD: uk; public suffix: co.uk). ngrok.pizza (SLD: ngrok; TLD: pizza; public suffix: ngrok.pizza).

You might start to believe that two is a magic number here, but it’s not. The list also includes pvt.k12.ma.us, which is one public suffix with four labels.

pvt.k12.ma.us (SLD: ma; TLD: us; public suffix: pvt.k12.ma.us).

What I hope is clear by now is that the shape of a public suffix can vary. A lot. Your browser can’t perfectly determine the boundary between a domain name and the user-owned names/content that live beneath it by spelling and dot placement alone. Neither can you, try as you might.

Your browser then consults the Public Suffix List and its thousands of boundary rules to decide where a cookie can go. But handling cookies is just one place where software at large, far beyond browsers, needs to distinguish a shared platform from an individual organization’s site.

Once you know you can always consult the list for that distinction, it starts to become handy in some surprisingly common and complicated places.

The many ways public suffixes get used (and abused)

So how are public suffixes put to use, aside from protecting you from overambitious cookies? For starters, Firefox puts the list to work in your address bar. It uses a compiled copy to determine which part of an address to emphasize.

For the Example Store at shop.example.com that I started this article with, the most relevant part is example.com. You really do want to know you’re shopping on the right domain.

For shop.example.com, Firefox dims shop. and emphasizes example.com.

For Alice’s site, the relevance extends one dot and one name to yummy.ngrok.pizza. If Firefox only highlighted ngrok.pizza, you wouldn’t see a clear distinction between Alice’s page and anyone else’s site on ngrok.pizza.

Firefox emphasizes all of yummy.ngrok.pizza and all of scrumptious.ngrok.pizza. Each emphasized name is a registrable domain: a public suffix plus the preceding label.

A multi-tenancy must-have

A hosting platform that lets users host apps on a shared domain is one popular example of multi-tenancy, in that it serves many independent users, or tenants, who don’t share any sense of ownership, accounts, or trust. You’re probably most familiar with platforms like GitHub Pages or Vercel, where you can host your own apps beneath the github.io and vercel.app domains they respectively own.

These platforms can see (in their own systems for accounts) where the boundaries exist between users, but browsers can’t peek into those systems. Even if they could, they’d need a global standard for reading that data, one that’s always available and never slows down a page load, or…

… there’s the Public Suffix List.

By publishing correct boundaries in the list, providers like GitHub Pages, Vercel, and, of course, ngrok itself let browsers and other software recognize them and make the appropriate logical decisions around them.

Browsers aren’t the only software using those boundaries—not by a long shot. At ngrok, we use them in ways both incredibly close to the heart of the PSL’s original intent and, well, not so close, too.

Down the ngrok rabbit hole

The most obvious way we lean on the Public Suffix List is through reserving a domain. We give you two options: reserve a domain beneath one of our public suffixes, like ngrok.pizza, or bring your own domain. That has big implications for when you’re allowed to reserve a wildcard * on that domain, which, in turn, allows you to claim any other subdomain beneath that.

For example, maybe the owner of yummy.ngrok.pizza wants to claim a wildcard so they could deploy services on app.yummy.ngrok.pizza and blog.yummy.ngrok.pizza. Can they? Let’s walk through all the possibilities starting from the very top.

*.pizza. An ngrok user asks to reserve *.pizza. That would cover every name directly beneath pizza.
1 / 10

The PSL only tells us where the boundaries are. After the PSL check, ngrok’s own records decide which account holds which name.

We also use the PSL, through a well-maintained Go library, to group traffic for billing, to check the reputation of email domains at signup, and to pull a company’s name out of a work email address. None of those are what the list was built for, but it’s hard to resist a free, accurate map of where domain boundaries are!

Finding the right saved passwords for your current tab

You open a tab and pop over to a new website, and your password manager suggests just the right saved login. How does it know how to do that?

Bitwarden, for example, uses base-domain matching via the tldts library to distinguish between yummy.ngrok.pizza and scrumptious.ngrok.pizza, while still letting you share a single password on multiple subdomains of example.com. Other password managers, like KeePassXC and pass’s Browserpass integration, also use the PSL, but with different matching methods.

In the week of September 5–11, 2026, npm recorded 63.4 million package downloads of tldts alone.

login.example.com. You save a login for login.example.com. This example uses Bitwarden's base-domain matching.
1 / 7

You’d be right to think that sounds like a thin barrier between you and inadvertently dropping your credentials onto the wrong site. In 2023, Bitwarden fixed a misconfiguration that left private suffix rule parsing in tldts disabled, in turn opening users up to the possibility that unrelated sites could match the same credentials.

Not great.

Rate-limiting massive volumes of TLS certificates

To prevent abuse, Let’s Encrypt applies rate limits to registered domains, which it defines as the part you purchased from a registrar or claimed from a platform like ngrok. It uses the Public Suffix List, through the publicsuffix-go library, to find that registered domain and separate it from others.

www.example.com. You request a new certificate for www.example.com. Which registered-domain quota does it count toward?
1 / 7

This keeps yummy.ngrok.pizza and scrumptious.ngrok.pizza in separate buckets instead of competing for the same limit of 50 certificates for every 7 days. But this only works if nobody games the list. Anyone who controls a domain can ask to add it to the PSL, and an entry would give each of their subdomains its own bucket.

Simon Friedberger, a key maintainer of the PSL from Mozilla, wrote to me about this point: “Historically, there was an aspect of trying to support use-cases which need the PSL to be a gatekeeper but it never had a reasonable threat model.” So, any rate limit that depends on the list can’t stop a determined abuser. The PSL’s submission template says software “should be discouraged from use of the PSL as a rate-limiting tool,” and asks platforms to request rate limit increases directly from the third party instead.

But now that I’ve shown many of the ways the Public Suffix List gets used, you might be wondering: Is this really the best way of knowing where one domain boundary ends and another begins?

Why DNS hasn’t replaced the list… yet

The primary job of our beloved Domain Name System is to translate a domain name like yummy.ngrok.pizza into an IP address, which your browser or curl or whatever can use to communicate directly with the destination host.

But there is no standard DNS setting browsers use to recognize that “names below ngrok.pizza belong to different parties. Beware!” There’s also no standard DNS signal for the owner of yummy.ngrok.pizza (me, thank you very much) to say, “Hey, I have no control over that complete weirdo at scrumptious.ngrok.pizza!” (also me).

You can see all this for yourself right now. dig is a CLI tool for querying DNS for the records associated with domains, and these address records tell us nothing about whether the sites belong to the same tenant. When I captured these answers, each name returned 6 A records. Look closely! They’re the same 6 addresses, but in different orders.

dig +noall +answer for yummy.ngrok.pizza and for scrumptious.ngrok.pizza both return the same six A records, shown in different orders. The button simulates another query by rotating the captured addresses. Nothing in either answer says who runs each name.

Illustrated response 1. The same six addresses appear in both answers. First address for yummy: 54.241.22.131. First address for scrumptious: 13.56.186.207.

Nothing in these answers tells a browser where our shared infrastructure ends and our separate sites begin. It would be really nice if browsers could get a standard answer from DNS about cookie boundaries, but they can’t, so the browser folks wrote down all the answers themselves, by hand, into what’s now a roughly 0.3 MB text file.

Why didn’t DNS account for this from the get-go?

From RFC to Free Telecom and LiveJournal in two decades

In the mid-1980s, when the DNS specification was being written and actively iterated upon, it already did account for the concept of boundaries. A DNS zone apex marks the beginning of a zone, and delegations mark where the responsibility for DNS data passes to another zone. But that boundary doesn’t reliably tell applications which sites should trust each other.

One good way to illustrate this is with universities, where dividing up zones was purely an operational decision for the administrators. One university might want a single zone for all its departments, and another might want to divide its departments into separate zones. Multiple ways to break up zones, all about who administers the DNS data.

Twenty years later, Free Telecom and LiveJournal started giving away subdomains on names like free.fr and livejournal.com.

That revived questions among internet and browser builders over where information about boundaries between tenants should live, because DNS had no standard way to tell browsers where one tenant’s site ends and another’s begins.

Well then. Let’s just fix DNS!

The DBOUND debacle

In January 2015, Andrew Sullivan, Jeff Hodges, John Levine, and Casey Deccio posted the first draft of their DBOUND problem statement: Let’s replace the PSL without changing the DNS protocol. New record types were fair game. Sounds easy, right?

By July 2015, working group co-chair Pete Resnick had identified the problem at hand.

It looks like we have a suite of questions needing a suite of solutions.
— Pete Resnick, working group co-chair

Does this sound painfully familiar to anyone else? Just me?

After just under two more years of debate (dare I say bickering?), the effort collapsed in April 2017.

Revival efforts continued as recently as September 2025. A decade of efforts from smart and well-intentioned people who wanted to fix DNS to account for public suffixes, and still no general replacement.

Forgive me for not having been in all of these rooms, but here’s my take on why:

  1. DBOUND started from the idea that cookies, certificates, DMARC, and browser URL bars each need a different kind of boundary. That idea split one problem into a suite of them. It might not even be true: Simon told me he tried several times to find real differences between these uses and couldn’t.
  2. A replacement had to beat something that already worked. In 2014, Mozilla said the PSL worked well for them, and extra DNS queries were a concern. Browsers can check a bundled list locally, but a DNS-based alternative would introduce additional lookups that could delay requests when the information isn’t cached. “Better” had to justify both the performance hit and the work of switching.

So, replacing the list for browsers has proven… difficult, but email is the exception. In May 2026, the IETF published DMARCbis as RFC 9989, which drops the PSL for a “DNS tree walk”: a mail receiver checks for _dmarc records at each parent name and tries up to 8 lookups to find the domain’s policy. Browsers are another story. Simon told me that even today, Mozilla has no plans to move Firefox off a bundled PSL. He’s exploring options, but “it’s a tough space with lots of constraints.”

Meanwhile, the private section of the list keeps growing.

How a list for browsers became shared infrastructure

When the private section of the Public Suffix List was added in 2012, it contained 318 rules, some of which you might recognize, like appspot.com, dyndns.org, and blogspot.com.

Since then, the number of rules has grown 10.8x, from 318 rules at creation to 3,449 as of October 19, 2026. What was once a section containing 7.4% of the list’s rules has grown to 33%.

PRIVATE: 318 rules on March 6, 2012; 3,449 on October 19, 2026. ICANN: 3,996 to 6,949 rules over the same period. Areas stack from zero, with PRIVATE below ICANN. Monthly snapshots, held until the next sample. Circles mark twenty selected platform listings. Listings in the same calendar month share a circle. Hover or activate a circle for its domain, listing date, and review link. Dates identify listings, not service launches.

Monthly Public Suffix List rule counts by section
DatePRIVATEICANN
2012-03-063183996
2012-03-313183999
2012-04-303183999
2012-05-313183999
2012-06-303184019
2012-07-313185642
2012-08-313185642
2012-09-303185673
2012-10-313655696
2012-11-303655694
2012-12-313655693
2013-01-313655698
2013-02-283655700
2013-03-313875706
2013-04-303895706
2013-05-313915706
2013-06-304045706
2013-07-314095707
2013-08-314125707
2013-09-304125724
2013-10-314135783
2013-11-304135844
2013-12-314135839
2014-01-314175968
2014-02-284185968
2014-03-314256143
2014-04-304246143
2014-05-314266173
2014-06-304306340
2014-07-314306340
2014-08-314326359
2014-09-304336385
2014-10-314476445
2014-11-304476445
2014-12-314476445
2015-01-314476445
2015-02-284476445
2015-03-314476445
2015-04-304476445
2015-05-314476445
2015-06-304476445
2015-07-315537096
2015-08-315537200
2015-09-305567226
2015-10-315567233
2015-11-305577247
2015-12-315757247
2016-01-315787260
2016-02-295897264
2016-03-315987268
2016-04-306157280
2016-05-317137283
2016-06-307357278
2016-07-317487278
2016-08-317637278
2016-09-307637285
2016-10-318197286
2016-11-308767284
2016-12-319007161
2017-01-319047162
2017-02-289807126
2017-03-319827126
2017-04-3010147138
2017-05-3110147138
2017-06-3010647173
2017-07-3111297181
2017-08-3111517189
2017-09-3011517206
2017-10-3111517219
2017-11-3011517219
2017-12-3111687251
2018-01-3111677272
2018-02-2811747272
2018-03-3111837273
2018-04-3012017277
2018-05-3112827329
2018-06-3012827329
2018-07-3112817332
2018-08-3112827339
2018-09-3012827339
2018-10-3112977334
2018-11-3012997340
2018-12-3113097340
2019-01-3113097339
2019-02-2813377334
2019-03-3113457337
2019-04-3013507337
2019-05-3114317336
2019-06-3014317338
2019-07-3114507343
2019-08-3114507337
2019-09-3014527344
2019-10-3114527347
2019-11-3014507337
2019-12-3114807330
2020-01-3114897329
2020-02-2914897340
2020-03-3114947338
2020-04-3015167337
2020-05-3115777335
2020-06-3015817330
2020-07-3116027340
2020-08-3116467346
2020-09-3016537347
2020-10-3117337345
2020-11-3017417343
2020-12-3117647341
2021-01-3117797349
2021-02-2817897348
2021-03-3118147347
2021-04-3018217344
2021-05-3118277345
2021-06-3018367344
2021-07-3118797344
2021-08-3118367348
2021-09-3018477344
2021-10-3118507346
2021-11-3018497346
2021-12-3118647339
2022-01-3118677338
2022-02-2819897335
2022-03-3119997335
2022-04-3020257335
2022-05-3120337335
2022-06-3020397335
2022-07-3120397335
2022-08-3120477369
2022-09-3020907369
2022-10-3120977367
2022-11-3021017366
2022-12-3121017365
2023-01-3121017380
2023-02-2821877380
2023-03-3121877378
2023-04-3021886833
2023-05-3121886841
2023-06-3022146898
2023-07-3122126894
2023-08-3122126892
2023-09-3022246880
2023-10-3126906878
2023-11-3026916875
2023-12-3126916874
2024-01-3126966872
2024-02-2927406870
2024-03-3128046868
2024-04-3028266868
2024-05-3128866868
2024-06-3029176867
2024-07-3129126868
2024-08-3129186870
2024-09-3029076874
2024-10-3129106870
2024-11-3029166860
2024-12-3128366857
2025-01-3128576868
2025-02-2828676867
2025-03-3128806871
2025-04-3028966871
2025-05-3129056911
2025-06-3029386912
2025-07-3130036912
2025-08-3130186915
2025-09-3030296914
2025-10-3130416928
2025-11-3031296930
2025-12-3131646934
2026-01-3131896930
2026-02-2832176934
2026-03-3132226934
2026-04-3032726934
2026-05-3132776933
2026-06-3032966933
2026-07-3132906949
2026-08-3132996949
2026-09-0833756950
2026-09-3033846950
2026-10-1934496949

Behind those rules are generations of multi-tenant platforms that depend on the time, attention, and care of the list’s maintainers. While the PSL is a Mozilla initiative, it’s maintained as a community resource by volunteers.

Well, if adding a new domain to the Public Suffix List is just one pull request away, what’s the big deal? To add any new rules to the PRIVATE section of the list, a maintainer must validate, investigate, and establish, with confidence, the following:

  • Do the proposed new rules describe the boundary correctly? Would they affect any other service? Are they sorted correctly and put in the right place?
  • Does the service actually give domains to independent users who shouldn’t share cookies? Or does the submitter only want to get around a third-party limit, like Let’s Encrypt’s? The template asks them to attest that they don’t.
  • Is the project sizable enough to warrant inclusion? Changes can reach hundreds of millions of devices, and additions increase the file size for everyone who incorporates them. On March 26, 2026, maintainers codified the 2,000–3,000 distinct user requirement in the PR template and asked submitters to come with proof of the relative extensiveness of their project.
  • Has an authorized domain administrator confirmed this request? A _psl TXT record linking to the pull request demonstrates DNS control and connects that control to the ask.
  • Does the domain have at least two years left on its registration when the request is submitted? Propagation of the list takes time, and domains that expire not long after they’ve landed in the list are a waste on all fronts.

Sometimes those questions aren’t enough. Then a maintainer might tag the domain owner on GitHub (as they did with ngrok and @inconshreveable), email the company directly, or check services like VirusTotal for abuse on its subdomains.

All that validation takes meaningful, valuable, hard-to-find time. Automation can run dig TXT _psl.addmetothepslplease.com and validate that it returns the URL of the PR in question, but people still make every single decision based on their judgment, best effort, and expertise.

Even after a rule gets accepted and added, it doesn’t immediately propagate to every browser and password manager and internal implementation. Changes may arrive through library releases, app updates, or even OS updates. The PSL’s maintainers don’t control whether or when those downstream systems and software adopt any change.

A proposal emerges: make the list harder to join

As I was writing this section, I started chatting with Jothan Frakes, also known as @dnsguru. As a longtime PSL volunteer, he’s personally felt the actual tax that all this work and the growth of the PSL itself place on maintainers. During our conversation, he shared a proposal he’d already been working on to raise the floor of verifiable users from 2,000–3,000 to 15,000.

That’s a substantial change. But his rationale returns to what we’ve learned so far about how cookie boundaries work, why browsers both need this information and need to tightly control it, and why efforts like DBOUND failed:

A DNS-based solution to the cookie isolation dilemma that would allow a domain administrator to self-define their preferences does not currently exist. If it did, there would still be the hurdle of convincing browsers to invest development cycles and slow down their page loads to support it.

The best method that exists for proper cookie isolation for your project is to register and use individual domain names.

— @dnsguru

Since 2015, when the Public Suffix List moved to GitHub, the volume of PRs has grown significantly. As of October 19, there have been 684 pull requests in 2026: 148 merged, 465 closed without merging, and 71 still open. That’s the largest number of pull requests in any year so far and, by quite a large margin, the largest number closed without merging.

Pull requests to the Public Suffix List, by year opened

* Status as of October 19, 2026, grouped by the year each pull request opened. Each bar includes merged, closed without merging, and still-open requests. The 2026 bar covers part of the year.
Source: publicsuffix/list on GitHub.

If you ask me, that’s a pretty clear throughline. What does Jothan think?

He speaks from his experience as a volunteer, not on behalf of the whole project or for Mozilla, but in his account, platforms’ preference for putting users on shared subdomains creates demand for PSL entries. Higher demand equals more pull requests, longer review times, and more tax on the volunteers.

I’ll admit: I had assumed AI was to blame. When I first pulled data on pull request volume, the ramp-up from 2024 to today looked to me like it was tied to growth of AI tooling and coding agents. Yet another open source project drowned in slop! What a story! But Jothan’s proposal doesn’t even mention AI.

As our conversation progressed, he did identify AI-generated requests, particularly from small multi-tenant projects, as one source of pressure. Beyond the very real burden on volunteer reviewers, he worries that continued growth of the PSL could force browsers to bail. As Jothan says, “We all lose if the one-stop solution gets broken up.”

Jothan’s proposal isn’t without pushback.

Simon argues that verifying 15,000 users is no easier to automate than 3,000, and others agree that neither is a magic number that proves a project’s legitimacy. Over email, he mentioned maintainers might even relax the requirements to join the list because he doesn’t share Jothan’s worry about growth. A bigger list is only a concern if it “would become a large percentage of a browser download,” but even if maintainers accepted every PR from the last year, the list would only be about 8% bigger. And that, to him, is “pretty modest growth.”

Elsewhere in the thread, a participant from Amazon argues that supporting custom domains doesn’t remove the need to isolate the default subdomains that customers use before configuring their own—and requiring custom domains majorly hurts the usability of any platform.

Whatever happens to the threshold, volunteers still have to decide whether each proposed entry belongs. An AI agent can conjure up a well-written submission that follows all the rules, but it can’t establish whether the service belongs at all. And, sometimes, the agent takes a little bit too much agency into its own “hands”:

Oh my goodness, so sorry to waste your time - (this is really embarrassing, but I asked an agent to draft a pull request so I could review and I guess it took that as permission to use my github account).
— @OliverMoreland

That’s one accidental submission. In two other cases, submitters apologized after their agents opened requests. Volunteers have also flagged submissions as AI-generated. Maintainers have responded with warnings about copying the submission template into AI, and have even offered instructions for agents to preserve the submission template, but none of it is the AI-drawn smoking gun I assumed I’d find.

Why have so many requests to join the list this year been closed? Simon admits he has no data, but offers a different way that AI matters: “AI made it easier to start projects, so we get a lot of new projects which don’t meet the 3k user requirement yet.” He also sees many people building AI site builders that dole out independent subdomains to each user and their deployments.

So the problem is still that volunteers must spend their time deciding whether each proposed entry really belongs. And that is, in turn, the consequence of a chain reaction of decisions and debates that began long ago with DNS, browsers, cookies, and multi-tenant platforms.

The file that feels irreplaceable

I had barreled through this article thinking I would end by helping developers create better submissions to the Public Suffix List. Better submissions equal less time in triage and debate, right?

Then Jothan asked a harder question: Why on earth are we still building services that require another entry to function properly?

Simon’s answer starts with today’s status quo itself: “My main gripe with the PSL is that the general system is ‘fail-open’, in other words, if you don’t have a PSL entry your subdomains share cookies. That is an insecure default.” He would rather have an opt-in system for those who do want to share cookies across domain boundaries.

But, with the way browsers work today, getting on the PSL is the only way for a platform to opt in to isolation. It is, as Simon says, “a poor solution to a real problem, which is surprisingly hard to do better and doesn’t receive much attention, and so it has persisted.” That’s a maintainer talking about the system the list is stuck in, not the work that keeps it running.

Where we go next on sustaining the PSL’s current work, or discovering a different solution, has no tidy answer.

We’re left with a few volunteer maintainers holding up a security boundary for the whole web. They can’t control demand for new entries, they can’t control how fast their decisions reach your browser, and they can’t stop anyone from using the PSL’s entries for any other use case. And when the flaws of this inherited system show, they’re the ones who catch the grief.

I do think companies that benefit from this file, like ngrok, owe maintainers more than carefully formatted pull requests. We have hard discussions ahead about making custom domains easier for our users, because the product decisions we make today create more work. What seems like a simple ask to add one more line to a text file is another request to investigate and another decision that software across the internet will rely on.

Before we ask them to add that line, we should be able to explain why we need it.