Re: A less-circumventable age verification protocol: good ol' files
"Jeremy Soller" <[email protected]> Tue, 10 Mar 2026 21:03:38 -0600
| Newsgroups | gmane.linux.xdg.devel |
|---|---|
| Message-ID | <[email protected]> |
Hello Daniel, I do not agree that having the API be technically possible to circumvent is a legal issue (the word "reasonably" carries a lot of weight), or that your implementation can resolve it. I could still virtualize or emulate an operating system where I have root, even if I do not have root on the host OS. The New York bill also seems to require age estimation, done either with biometrics or using other collected user data. I have not seen a proposal that takes this into account yet, and I hope it will be unconstitutional for the same reason the Texas bill was. -- Jeremy Soller System76 Principal Engineer [email protected] On Tue, Mar 10, 2026, at 8:41 PM, Daniel Tang wrote: > I would like to propose a better way to implement age verification. The > existing proposals fall short of the anti-circumvention requirements. > > The New York bill at > https://www.nysenate.gov/legislation/bills/2025/S8102/amendment/A says: > >> 1. "age assurance" shall mean any method to reasonably determine the >> age category of a user, using methods that reasonably prevent against >> circumvention. such method may include a method that meets the require- >> ments of article forty-five of this chapter, or may be a method that is >> identified pursuant to new regulations promulgated by the attorney >> general consistent with section fifteen hundred forty-five of this arti- >> cle. > > Their first proposal was > https://gitlab.freedesktop.org/xdg/xdg-specs/-/merge_requests/113 . > That was rapidly circumvented by > https://github.com/HaplessIdiot/ageverificationbypass/blob/main/bypassageverification.py > . > Someone else's proposal was > https://github.com/flatpak/xdg-desktop-portal/pull/1922 . > > Both use D-BUS. I assert that the age verification must not use D-BUS. > While the first circumvention might require root, a child could wrap it > to not require root. They could just set the DBUS_SYSTEM_BUS_ADDRESS > environment variable. Then a Python server could start listening on > that file to falsely respond to requests. > > The second proposal is 535 lines of code of D-BUS verboseness. That > feels wrong. Let's go back the Unix philosophy of "everything is a file". > > What I propose is a root-owned world-unwritable directory at either: > * /etc/age-verification/$UID/ , or > * ${XDG_RUNTIME_DIR:-/run/user/$UID}/ageverification/ , or > * /var/lib/ageverification/$UID/ > > /etc is trusted by sudo's authentication, and by ImageMagick's security > blocking PDFs.XDG_RUNTIME_DIR can be better if /etc is out of scope > for the XDG mailing list and we want dynamic updates coexisting with > ReadonlyRoot. To prevent tampering, no directory there should be empty. > > Originally I considered a /etc/age/$UID or /etc/birthday/$UID file, but > that offers less privacy. For additional privacy, each directory should > have 0711 permissions, so accesses can be granular. Then there should > be exactly one of the following empty regular files: > * "under-13" > * "13-to-15" > * "16-to-17" > * "18-plus" > > Only when a different jurisdiction enacts conflicting age intervals, we > can discuss whether to include both. > > An absent directory indicates a system service or test environment. > Each desktop environment shall be responsible for prompting existing > users and talking to a service or setuid helper binary unless the > CI=true environment variable is set or the UID is below 1000. > libpam_systemd can be used to delay login until any dynamic directory > is created. > > The helper should have PAM-like interactions to dynamically drive a UI > like KDE or GNOME's current lockscreens. I originally considered > introducing a new PAM type, but too many setups might already assume > exactly the 4 traditional account/auth/password/session set, and I > don't know whether PAM is convenient with Flatpak. Anyway, Flatpak > shall be responsible that the directory is accessible and not > overmounted inside its sandbox. The "real-time application programming > interface" in the law can be `access(2)` on the appropriate file. > > Each Linux distribution shall choose what helper to run, depending > on the local laws of its target market. It can also omit the helper, and > lock in the age bracket set at install-time. If the helper stores the > birthdate, it can add-then-remove files as time goes by. The > simplicity of this file-based approach establishes clear > responsibilities between operation system code and application code. > A simple protocol will be implemented faster, and this speed is > important, as mentioned in a comment in the second proposal, for LTS > distributions. > > California Assembly Bill No. 1043 prohibits sharing "the digital > signal information with a third party for a purpose not required by > [the] title". Accordingly, https://github.com/systemd/systemd/pull/40954 > may violate it by storing the birthdate. I am not a lawyer, and this is > not legal advice. But decopuling the birthdate from the files and > into the helper allows different distributions to follow the differing > opinions of their different legal counsel. > > The anti-circumvention should center on requiring root access. > Reinstallation is no more of a concern than factory-resetting other > OSes. Parents are responsible for not adding their children to the > sudo group and adding a GRUB password. To make the anti-circumvention > complete, other distributions could need to, like Ubuntu, restrict > unprivileged user namespaces. The security of my whole proposal rests > on the fact that without userns, getuid(2) cannot be remapped, and > /etc cannot be overmounted. sudo and ImageMagick rely on this. These > two steps provide secure attestation of the user's age range. > > The other proposals rest on one weak link, namely > DBUS_SYSTEM_BUS_ADDRESS. With so many programming languages, at least > one will have an age verification library that is vulnerable to an > attack where it fails to unsetenv(3) or reject this envvar. LD_PRELOAD > attacks are different and don't matter, because it's code not data, and > injected code can turn any application into any new application, so the > some may consider the person injecting the code to be the new legal > developer. > > ~ daniel . z . tg