Skip to content

v1.2.1

Choose a tag to compare

@github-actions github-actions released this 21 Sep 14:52
· 52 commits to master since this release
137c6c9

Ubuntu Hello v1.2.1 - Clean-Install Fix, Settings Env Hardening, Booted-OS + Footage Test Tiers

This release fixes the 1.2.0 package failing to configure on a clean Ubuntu 26.04, closes a local root-execution path through the polkit-elevated Settings process, stops the PAM module from hijacking the host process's syslog identity, makes the confirmations config migration run for package installs, corrects the mode of config.ini, and adds the two test tiers that found all of it: a booted-OS tier (a clean Ubuntu, Fedora or Arch under QEMU/KVM with an emulated TPM) and a recorded-footage tier (the real recognition loop on real camera frames, no face pixels kept). Plural-form translations are now linted and declared in every catalog.


πŸ”§ What's in this release

  • πŸ“¦ Fix: fresh install failed on a clean Ubuntu 26.04. The package builds dlib from source (the archive has no python3-dlib) and the toolchain it needs was only Recommended. apt never upgrades an already-installed package to satisfy a Recommends, so on an image whose python3 lagged the archive python3-dev was silently skipped, the build died on Python.h: No such file or directory, dpkg stayed half-configured and every login fell through to the password. Developer machines that already had the headers never saw it. The toolchain is now a hard dependency unless the distro's dlib is installed (python3-dlib | python3-dev, | python3-pip, | cmake, | g++); Fedora/openSUSE gain python3-devel / gcc-c++ / Pillow, Arch gcc / python-pillow. Reproduced and verified on a clean cloud image.
  • πŸ›‘οΈ Security fix: the elevated Settings process accepted arbitrary environment variables from argv. ubuntu-hello-gtk forwards the desktop's display and locale variables across pkexec as --env-KEY=value arguments and restored every such argument into its environment as root. polkit pins only the interpreter and the script path, so a local user who can pass the auth_admin prompt could append --env-PATH=/tmp/evil:… or --env-LD_PRELOAD=… and have the root process β€” which spawns ubuntu-hello, sudo, gsettings and loginctl by bare name β€” execute their binary as root. The restore now accepts only the fixed display/locale allowlist that elevate() sends (one shared constant for sender and receiver), drops everything else with a stderr notice, and as root pins PATH to a fixed system value before any helper is spawned. Reported by an automated security review; unit tests cover the injected PATH/LD_*/PYTHON*/HOME cases.
  • πŸͺ΅ Fix: the PAM module hijacked the host's syslog identity. openlog("pam_ubuntu_hello") without closelog() tagged every later line of sudo or the display manager as pam_ubuntu_hello. The identity is now scoped to the module's own logging (SyslogIdentityScope).
  • βš™οΈ Fix: the confirmations migration never ran for package installs. It lived in the source installer only; .deb/RPM/Arch upgrades left the key out and fell back to a single frame. It now lives in config_ensure.py and package-configure.sh runs it on every install and upgrade β€” hand edits, comments and a hand-tightened threshold are kept, verified on a real 1.1.6 β†’ 1.2.1 apt upgrade.
  • πŸ” Fix: config.ini was installed executable (0755 β†’ 0644); docs/SECURITY.md now describes the real /etc/ubuntu-hello/ layout (0755 directory, secrets in 0700 subdirectories).
  • πŸ” Fix: on Fedora/Arch the module could break password authentication. The authselect/Arch PAM line used [success=end default=ignore]; end is a Debian pam-auth-update macro, not raw PAM syntax, so Linux-PAM let the module's skip return (AUTHINFO_UNAVAIL for SSH / no camera / disabled) surface β€” an SSH or camera-less login failed instead of falling through to the password. Now [success=done default=ignore]. Found with a live before/after on a booted Fedora guest.
  • πŸ‘» Fix: face auth spawned a GTK overlay that crashed on a headless box. compare.py started the on-screen auth overlay unconditionally, but under PAM there is no display, so on a server or SSH sudo it crashed on open and left an apport report every time (auth still fell back to the password). The overlay is now spawned only when a display is reachable.
  • πŸͺŸ Fix: the post-install wizard crashed on a headless machine. It assumed DISPLAY=:0; installing over SSH started GTK with no display and left an apport crash report. It now launches only when a display actually exists.
  • 🧩 Fix: the Arch PAM module failed to load, breaking face auth entirely on Arch. It links libINIReader.so.0 (libinih) and libevdev, but those were build-only deps, so pacman never installed them and PAM could not dlopen the module. Both are now runtime dependencies.
  • πŸ—οΈ Fix: the Arch package could not build dlib and then skipped the security setup. Its deps listed gcc/cmake but not make, so cmake could not build dlib, and that failure aborted the post-install before PAM and the polkit drop-in were written. make is now a dependency and the dlib build runs last and non-fatally on every format, so the security config is always applied.
  • 🧹 Fix: dnf remove left /usr/lib64/ubuntu-hello behind (untracked __pycache__); the shared pre-remove step now sweeps every lib dir and drops the emptied directory.
  • πŸ–₯️ New: booted-OS test tier (scripts/vm/, tests/vm/). A clean Ubuntu 26.04, Fedora 44 or Arch cloud image boots under QEMU/KVM with a swtpm TPM 2.0 and scenario scripts run inside over SSH: install (PAM line, drop-in, tmpfiles, catalogs, dlib, file modes), config migration, sudo through PAM with a synthetic model (fails closed without a camera, wrong password refused, caller environment never inherited, syslog identity kept), the greeter HARD RULE (pam_probe.py runs the real PAM stack for gdm-password and counts prompts: with workaround = off the module never asks itself), the polkit helper sandbox with a real TPM seal/unseal, a real reboot, purge (nothing left, no crash reports), and an upgrade from the previous GitHub release. One lib.sh holds what differs per distro. UH_VM_PKG_DIR tests packages built from the tree; CI runs a matrix job per distro on release branches. Every fix above was found by it.
  • 🎞️ New: recorded-footage test tier (tests/footage/). Replays real-camera clips through compare.py's actual scan loop, the real dlib detector/predictor/encoder and the real nod rubber stamp: enrollment on real frames, the same face at Secure from another clip, no face never passing, the agreeing-frames gate, a real nod passing and holding still failing fail-closed, Secure margin. Privacy: only de-identified per-frame signals exist (dark flag, face rect, five landmarks, descriptor), the pixels were shredded, the signals stay off the repository, and CI uses a synthetic set with the measured shape.
  • 🌍 i18n: plural forms. ngettext() entries were invisible to the lint and an untranslated plural shipped everywhere with the lint green; plural entries are now linted and every catalog header carries the language's Plural-Forms rule so Python's gettext picks the right form. Catalogs are refreshed for 1.2.1 (template version, source references).

No new config keys or strings. Runtime dependencies: the dlib build toolchain is now a proper dependency where the distro ships no dlib. Desktop / greeter / wallet compatibility is unchanged.


πŸ“₯ Installation (from Release assets)

Verify downloads against SHA256SUMS on the Release page before installing. Download this release's assets into an empty/clean directory before running these commands β€” the wildcards below match by filename pattern, and leftover assets from another version in the same directory can make a package manager see multiple matches (or, for the AppImage command, pass a second matched file as a stray argument).

Format Command
Debian (amd64 + arm64) sudo apt install ./ubuntu-hello_*_$(dpkg --print-architecture).deb ./ubuntu-hello-gtk_*_$(dpkg --print-architecture).deb
Fedora (amd64 + arm64) sudo dnf install ./ubuntu-hello-[0-9]*fc44*.$(uname -m).rpm ./ubuntu-hello-gtk-*fc44*.$(uname -m).rpm
openSUSE (amd64 + arm64) sudo zypper install ./ubuntu-hello-[0-9]*lp160*.$(uname -m).rpm ./ubuntu-hello-gtk-*lp160*.$(uname -m).rpm
AppImage (amd64 + arm64) chmod +x Ubuntu-Hello-*-$(uname -m).AppImage && ./Ubuntu-Hello-*-$(uname -m).AppImage --install
Arch (amd64 only) sudo pacman -U ./ubuntu-hello-[0-9]*.pkg.tar.zst ./ubuntu-hello-gtk-*.pkg.tar.zst
Snap (amd64 only) sudo snap install --dangerous --classic ubuntu-hello_*_amd64.snap && sudo snap run ubuntu-hello.host-install
Flatpak (amd64 only) flatpak install --user ./com.github.ventura8.UbuntuHello-*.flatpak && flatpak run --command=ubuntu-hello-host-install com.github.ventura8.UbuntuHello

PPA remains available:

sudo add-apt-repository ppa:ventura8/ubuntu-hello && sudo apt update && sudo apt install ubuntu-hello

Optional source install: download install.sh from the v1.2.1 tag, review it, then run locally β€” do not pipe a moving branch URL directly to bash.

Full Changelog: v1.2.0...v1.2.1