Public Suffix List
Ask the Public Suffix List (PSL) to treat every tunnel as its own site, so that browsers keep one user's apps apart from another's. This page has what the maintainers require, the entry, and the body of the pull request.
Browsers treat everything under one "registrable domain" as the same
site. Today that is local.link, so every user's tunnel
(app.alice.local.link, app.bob.local.link) is the same site as every
other. The relay already strips cookie Domain attributes that would
cross tunnels (Keeping tunnels
apart). A PSL
entry fixes the root cause in browsers. Each tunnel becomes its own site,
so SameSite cookies, storage partitioning and site isolation separate
users' apps the way they separate unrelated websites.
Similar services already have entries: ngrok.io and ngrok-free.app
(ngrok), trycloudflare.com (Cloudflare Tunnel), github.io (GitHub Pages).
Prerequisites
The PSL maintainers (CONTRIBUTING, Guidelines) decline or delay requests that miss any of these. Submit only once all of them hold:
- Enough users. They decline "smaller, private projects with <2000 stakeholders". An invite-only relay for friends doesn't qualify.
- A role-based email address on the domain, e.g.
security@local.linkorpsl@local.link, monitored with replies within 30 days. A personal address is not accepted. - A public abuse contact. dev@local.link, on the terms page
(
www.local.link/terms). Link it from the home page too before submitting. - At least 2 years left on the
local.linkregistration, and a commitment to keep more than 1 year left. Renew for several years first. - Terms of use covering abuse (
www.local.link/terms) are strongly advisable, since the site is open to other people's content.
An entry takes months to reach browsers, and removing it later is just as slow. So it's worth doing once, when the service is clearly multi-tenant and public.
The entry
*.local.link makes every <user>.local.link a public suffix, so each
<app>.<user>.local.link is its own site. Separating users is the point,
and the wildcard also separates one user's apps from each other. Share
links are served on <user>.local.link itself, which the entry makes a
public suffix. local.link itself stays a normal registrable domain for
the relay and website.
To file it:
- Fork
publicsuffix/listand editpublic_suffix_list.dat. Add the block below in the PRIVATE DOMAINS section, sorted alphabetically by organization name among the existing entries. Don't append it at the end.// Local Link : https://local.link // Submitted by <Your Name> <security@local.link> *.local.link - Run the repo's checks (
make test, see its README). - Open the PR with the body below. Then add the DNS record it asks for, and
keep it forever:
Check it with_psl.local.link. TXT "https://github.com/publicsuffix/list/pull/<number>"dig +short TXT _psl.local.link.
PR body
Fill in the <…> parts. The checklist items come from the PSL's own PR
template, .github/pull_request_template.md in their repo. Copy the
current template and put these answers into it, because they change it
now and then.
Description of Organization
Local Link (https://local.link) is a tunneling service run by <your name / organization>. Users run the open
lnkclient on their own computer, and it gives a local web server a public HTTPS URL:lnk tunnel open 3000serves the app athttps://<app>.<user>.local.link. Each user owns the namespace<user>.local.link, tied to their GitHub account, and every app they expose gets its own host under it. The relay routes each host only to its owner's machine. users currently run tunnels.Reason for PSL Inclusion
Every tunnel serves content written by a different, mutually untrusting person, often a development build of their own web app. Without a PSL entry, browsers treat all of
*.local.linkas one site. That has three effects:
- A cookie set with
Domain=local.linkby one user's app is sent to every other user's app. That allows session fixation and overwriting other apps' CSRF cookies.SameSitecookie protection doesn't apply between users, becausea.alice.local.linkandb.bob.local.linkcount as same-site.- Storage partitioning and site isolation don't separate them.
The relay already strips
Domainattributes that aren't the exact tunnel host fromSet-Cookie. But that can't cover cookies set from JavaScript, or the same-site checks. A*.local.linkentry makes each<app>.<user>.local.linkits own site, as intended: users are separated from each other, and one user's apps from each other.local.linkitself stays a normal registrable domain for the service's website and API.Example outcomes after inclusion:
demo.alice.local.link: registrable domaindemo.alice.local.link.demo.bob.local.link: a different site from the above.local.link: unchanged; the service's own site.The domain has at least two years remaining on its registration (expires ), and we will keep more than one year remaining for as long as the entry exists.
Third-party limits: none sought. This request is not intended to work around Let's Encrypt or any other third-party limit. Certificates are issued only for a host the relay serves right now: a connected tunnel's host, or a user's own host while they have live share links, and at most 7 new hosts per user a day.
DNS verification
$ dig +short TXT _psl.local.link "https://github.com/publicsuffix/list/pull/<number>"Abuse contact:
