Skip to content

v3.1.0

Choose a tag to compare

@github-actions github-actions released this 25 Aug 20:22
· 35 commits to main since this release

Visilant 3.1.0 closes the gap the extension had: a login form served inside an iframe never reached a single one of its warnings. It also stops the toolbar promising a guard that was stood down, and brings the display controls to the page where an unknown address is actually read.

Warnings now reach inside frames and shadow roots

Events do not cross a frame boundary. The content script ran in the top document only, so typing into an iframe, pasting into a form in one, or copying out of one raised nothing at all – and a great many login forms are served exactly that way.

A separate frame guard now runs in every frame. It is 12 kB against the 220 kB of the main script: no Vue, no stylesheet, no domain lists, and it asks the background for nothing until a pointerdown or a focusin says somebody is using the frame. It draws no interface of its own, because a dialog inside a 200 pixel advert would be clipped to nothing. What it catches is handed to the top document instead.

A frame the page wrote rather than fetched – about:blank, srcdoc, a blob – is judged as the page that made it, and is still guarded. Links and events inside open shadow roots and custom elements are covered by the same change.

A silenced site keeps its verdict, said in grey

Red on the toolbar is a promise that something is on duty. On a site whose warnings you turned off there is nothing on duty, so the icon and the badge now draw the same verdict in grey. Familiar stays green either way, because silencing warnings does not make a site less known. The tamper alarm keeps its own red: not being warned about a site is not consent to the page tearing the extension out of it.

The controls for an address sit where the address is

Case, highlighting and the spelling of an international name used to be three buttons inside the subdomain list, which is not on screen until a site has visits – so the check page, where somebody reads an address they do not know, could not reach any of them. They now live in the header.

The account name of an email address has a control of its own, in its own row beside the name, with three positions rather than two: a domain reads the same in either case, while the capitals somebody chose are part of how a name was written down, so it is left as typed until you ask otherwise.

Fixed

  • A paste into a field inside a closed shadow root is held like any other. The field is invisible to composedPath(), so the guard used to see the host element, find nothing editable, and let it through.
  • A paste the page raised itself is no longer taken for one you made.
  • A background that could not answer is reported as a check that failed rather than as a site that is safe. A storage error used to read as "this site is fine" and took the warnings and the paste guard down with it.
  • A frame is judged by what the browser says it is rather than by the address it sends about itself, and a stale yes is no longer trusted.
  • Every recipient of a mailto: is checked, not only the first, and every address a link wears is read rather than the first one found.
  • The site boundary is drawn where the ownership changes, so two tenants of one hosting platform are two different sites and a tenant keeps its own subdomains.
  • A visit count is coloured by the check it belongs to rather than by the whole verdict, and by the address it belongs to.
  • One tab that cannot be drawn no longer ends the sweep, so a closed tab stops leaving every tab after it on a stale verdict.
  • Dialog close buttons are named, and focus goes back where it came from. Both intercept dialogs can be answered from the keyboard alone.
  • One writer for the settings and one for the visit records. A window left open used to write back the copy it had read, quietly undoing whatever had been changed elsewhere since.
  • Answers that were replaced while in flight are dropped instead of overwriting the current one, and the link cache is bounded.

Under the hood

  • Every dependency advisory in the development tree is closed except two in image-size, which has no fixed release. Nothing from node_modules reaches the packaged extension, so no shipped build was ever affected.
  • Node, pnpm, Vite and the rest are pinned through flake.lock and pnpm-lock.yaml, and both targets still rebuild byte for byte.

Verify this build

nix build github:ikskoder/visilant/v3.1.0#firefox
sha256sum result/*.xpi          # compare with SHA256SUMS below

scripts/verify.sh <downloaded.xpi> compares the copy your browser installed against a fresh build, file by file. Full instructions are in REPRODUCE.md.

Full Changelog: v3.0.0...v3.1.0