PDF.js's signature dialog saved every signature in localStorage under
pdfjs.signature, "save" ticked on every open, for this origin rather
than for a bau-pm user. Measured on v0.1.0: a typed and an uploaded
signature were offered to a fresh page on the same browser, the way the
next person on a shared tablet would get it, a Redmine logout included.
Another browser profile saw nothing; the server never had anything.
The glue's fifth duty, in every window before PDF.js's modules: delete
the store (a device that saved signatures loses them on its first
visit), refuse writes to that key, hold the save box unticked through a
property on the element and hide it, and hide the dialog's Bild tab and
its file picker, so a scanned signature never enters the dialog.
test/signatures.mjs is the second gate, in CI and the release workflow:
a browser seeded with a real saved entry (captured from v0.1.0's own
store) is offered none, the dialog shows neither the box nor the tab, a
typed signature is placed and not stored, a fresh page is offered
nothing. Fed v0.1.0: 9 findings, exit 1. Against this image: 0, and the
zero-host gate drove 117 tool pages with nothing leaving the origin. A
signed PDF still exports with the signature on the page.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
BentoPDF v2.8.8 built from source at its pinned commit with BentoPDF's own
air-gapped build options, every module it would load from a CDN vendored and
checked against vendor.lock, a Content-Security-Policy without a single host,
digital-sign-pdf and timestamp-pdf disabled because both need a third party,
and the hand-off glue on every page: the AGPL source link, the hand-in of a
file from bau-pm through a one-minute cookie into sessionStorage, confirmed by
the tool's reaction, the hand-back of a result from every window, and the
signing tool's flatten switch locked on.
The zero-host gate drives all 117 enabled tool pages in Chromium and fails on
any request to another origin, any CSP violation, a CSP that names a host, and
a disabled id that names no page. Green on this image (3 min 52 s on a private
network), red on the stock upstream image (115 findings) and on a misspelled
id. CI runs it on every push, the release workflow before it pushes.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>