53 Commits

Author SHA1 Message Date
9dfd1829e9 fix: audit MEDIUM fixes — D-Bus race, TOCTOU, FP reset, entry clear (v0.6.11)
- fingerprint: split cleanup_dbus into a sync take_cleanup_proxy() + async
  perform_dbus_cleanup(). resume_async now awaits VerifyStop+Release before
  re-claiming, so fprintd cannot reject the Claim on a slow bus. stop()
  still spawns the cleanup fire-and-forget.
- fingerprint: remove failed_attempts = 0 from resume_async. An attacker
  with sensor control could otherwise cycle verify-match → account-fail →
  resume and never trip the 10-attempt cap.
- lockscreen: open the wallpaper with O_NOFOLLOW and build the texture
  from bytes, closing the TOCTOU between the symlink check and Texture::
  from_file.
- lockscreen: clear password_entry immediately after extracting the
  Zeroizing<String>, shortening the window the GLib GString copy stays in
  libc-malloc'd memory.
v0.6.11
2026-04-24 13:21:19 +02:00
39d9cbb624 fix: audit fixes — RefCell across await, async avatar decode (v0.6.10)
- init_fingerprint_async: hoist username before the await so a concurrent
  connect_monitor signal (hotplug / suspend-resume) cannot cause a RefCell
  panic. Re-borrow after the await for signal wiring.
- set_avatar_from_file: decode via gio::File::read_future +
  Pixbuf::from_stream_at_scale_future so the GTK main thread stays
  responsive during monitor hotplug. Default icon shown while loading.
v0.6.10
2026-04-24 12:34:00 +02:00
3adc5e980d docs: drop Nyx persona, unify attribution on ClaudeCode
Remove the Nyx persona block from CLAUDE.md and rewrite prior
DECISIONS entries from Nyx and leftover Ragnar to ClaudeCode for
consistency with the rest of the ecosystem.
2026-04-21 09:03:23 +02:00
3f4448c641 style: replace hardcoded colors with GTK theme variables
All checks were successful
Update PKGBUILD version / update-pkgver (push) Successful in 3s
Use @theme_bg_color, @theme_fg_color, @error_color and @success_color
instead of hardcoded hex values and 'white'. Makes moonlock respect the
active GTK theme instead of assuming Catppuccin Mocha colors.

Note: moongreet and moonset still use hardcoded colors and should be
updated to match.
2026-04-09 14:51:29 +02:00
b621b4e9fe fix: handle monitor hotplug to survive suspend/resume (v0.6.9)
moonlock crashed with segfault in libgtk-4.so after suspend/resume when
HDMI monitors disconnected and reconnected, invalidating GDK monitor
objects that statically created windows still referenced.

Replace manual monitor iteration with connect_monitor signal (v1_2) that
fires both at lock time and on hotplug. Windows are now created on demand
per monitor event and auto-unmap when their monitor disappears.
v0.6.9
2026-04-09 14:48:06 +02:00
b89435b810 Remove unnecessary pacman git install from CI workflow
All checks were successful
Update PKGBUILD version / update-pkgver (push) Successful in 2s
Git is already available in the runner image.
2026-04-02 08:28:08 +02:00
06dadc5cbf Revert CI workaround: remove pacman install step
Some checks failed
Update PKGBUILD version / update-pkgver (push) Failing after 0s
The act_runner now uses a custom Arch-based image with git
pre-installed, so per-workflow installs are no longer needed.
2026-04-01 16:17:45 +02:00
2a9cc52223 fix: audit fixes — peek icon, blur limit, GResource compression, sync markers (v0.6.8)
All checks were successful
Update PKGBUILD version / update-pkgver (push) Successful in 2s
- Enable peek icon on password entry (consistent with moongreet)
- Raise blur limit from 100 to 200 (consistent with moongreet/moonset)
- Add compressed="true" to GResource CSS/SVG entries
- Add SYNC comments to duplicated blur/background functions
v0.6.8
2026-03-31 11:08:36 +02:00
102520d15f docs: update README features and fix build.rs comment
README was missing features added since v0.6.1 (GPU blur, journal
logging, lock-first architecture, PAM timeout, fprintd sender
validation, progressive faillock). build.rs comment still referenced
removed wallpaper.jpg.
2026-03-31 09:34:06 +02:00
59c509dcbb fix: audit fixes — fprintd path validation, progressive faillock warning (v0.6.7)
All checks were successful
Update PKGBUILD version / update-pkgver (push) Successful in 1s
- Validate fprintd device path prefix (/net/reactivated/Fprint/Device/) before
  creating D-Bus proxy (prevents use of unexpected object paths)
- faillock_warning now warns at remaining <= 2 attempts (not just == 1), improving
  UX for higher max_attempts configurations
v0.6.7
2026-03-30 16:08:59 +02:00
af5b7c8912 ci: also update .SRCINFO in pkgver workflow
All checks were successful
Update PKGBUILD version / update-pkgver (push) Successful in 1s
paru reads .SRCINFO (not PKGBUILD) for version comparison during
sysupgrade. Without updating .SRCINFO, paru never detects upgrades
for PKGBUILD repository packages.
2026-03-30 13:49:03 +02:00
1d8921abee fix: audit fixes — blur offset, lock-before-IO, FP signal lifecycle, TOCTOU (v0.6.6)
All checks were successful
Update PKGBUILD version / update-pkgver (push) Successful in 2s
Third triple audit (quality, performance, security). Key fixes:
- Blur padding offset: texture at (-pad,-pad) prevents edge darkening on all sides
- Wallpaper loads after lock.lock() — disk I/O no longer delays lock acquisition
- begin_verification disconnects old signal handler before registering new one
- resume_async resets failed_attempts to prevent premature exhaustion
- Unknown VerifyStatus with done=true triggers restart instead of hanging
- symlink_metadata() replaces separate is_file()+is_symlink() (TOCTOU)
- faillock_warning dead code removed, blur sigma clamped to [0,100]
- Redundant Zeroizing<Vec<u8>> removed, on_verify_status restricted to pub(crate)
- Warn logging for non-UTF-8 GECOS and avatar path errors
- Default impl for FingerprintListener, 3 new tests (47 total)
2026-03-30 13:09:02 +02:00
65ea523b36 fix: audit fixes — CString zeroize, FP account check, PAM timeout, blur downscale (v0.6.5)
All checks were successful
Update PKGBUILD version / update-pkgver (push) Successful in 1s
Address findings from second triple audit (quality, performance, security):

- Wrap PAM CString password in Zeroizing<CString> to wipe on drop (S-H1)
- Add check_account() for pam_acct_mgmt after fingerprint unlock,
  with resume_async() to restart FP on transient failure (S-M1)
- 30s PAM timeout with generation counter to prevent stale result
  interference from parallel auth attempts (S-M3)
- Downscale wallpaper to max 1920px before GPU blur, reducing work
  by ~4x on 4K wallpapers (P-M1)
- exit(1) instead of return on no-monitor after lock.lock() (Q-2.1)
2026-03-30 00:24:43 +02:00
465a19811a ci: add workflow to auto-update pkgver in moonarch-pkgbuilds
All checks were successful
Update PKGBUILD version / update-pkgver (push) Successful in 1s
2026-03-29 23:05:09 +02:00
484e990c68 fix: elevate CSS priority to override GTK4 user theme (v0.6.4)
Colloid-Catppuccin theme loaded via ~/.config/gtk-4.0/gtk.css at
PRIORITY_USER (800) was overriding moonlock's PRIORITY_APPLICATION (600),
causing avatar to lose its circular border-radius.

- Use STYLE_PROVIDER_PRIORITY_USER for app CSS provider
- Replace border-radius: 50% with 9999px (GTK4 CSS percentage quirk)
v0.6.4
2026-03-29 14:24:26 +02:00
77d6994b8f fix: prevent edge darkening on GPU-blurred wallpaper (v0.6.3)
GskBlurNode samples pixels outside texture bounds as transparent,
causing visible darkening at wallpaper edges. Fix renders the texture
with 3x-sigma padding before blur, then clips back to original size.
Symmetric fix with moonset v0.7.1.
2026-03-28 23:28:40 +01:00
fff18bfb9d refactor: remove embedded wallpaper from binary (v0.6.2)
Wallpaper is installed by moonarch to /usr/share/moonarch/wallpaper.jpg.
Embedding a 374K JPEG in the binary was redundant. Without a wallpaper
file, GTK background color (Catppuccin Mocha base) shows through.
2026-03-28 23:23:02 +01:00
ca934b8c36 feat: add MOONLOCK_DEBUG env var for debug-level logging (v0.6.1)
Align with moongreet/moonset logging pattern — set MOONLOCK_DEBUG to
enable debug-level journal output for troubleshooting.
v0.6.1
2026-03-28 22:57:02 +01:00
d11b6e634e fix: audit fixes — D-Bus sender validation, fp lifecycle, multi-monitor caching (v0.6.0)
Close the only exploitable auth bypass: validate VerifyStatus signal sender
against fprintd's unique bus name. Fix fingerprint D-Bus lifecycle so devices
are properly released on verify-match and async restarts check the running
flag between awaits.

Security: num_msg guard in PAM callback, symlink rejection for background_path,
peek icon disabled, TOML parse errors logged, panic hook before logging.

Performance: blur and avatar textures cached across monitors, release profile
with LTO/strip.
2026-03-28 22:47:09 +01:00
4026f6dafa fix: audit fixes — double-unlock guard, PAM OOM code, GPU blur, async fp stop (v0.5.1)
Security: prevent double unlock() when PAM and fingerprint succeed
simultaneously (ext-session-lock protocol error). Fix PAM callback
returning PAM_AUTH_ERR instead of PAM_BUF_ERR on calloc OOM.

Performance: replace CPU-side Gaussian blur (image crate) with GPU blur
via GskBlurNode + GskRenderer::render_texture(). Eliminates 500ms-2s
main-thread blocking on cold cache for 4K wallpapers. Remove image and
dirs dependencies (~15 transitive crates). Make fingerprint stop()
fire-and-forget async to avoid 6s UI block after successful auth.
2026-03-28 22:06:38 +01:00
48706e5a29 perf: cache blurred wallpaper to disk to avoid re-blur on startup
First launch with blur blurs and saves to ~/.cache/moonlock/.
Subsequent starts load the cached PNG directly. Cache invalidates
when wallpaper path, size, mtime, or sigma changes.
Adds dirs crate for cache directory resolution.
2026-03-28 21:23:43 +01:00
de9a3e9e6a feat: add optional background blur, align to shared texture pattern
Gaussian blur applied at texture load time when `background_blur` is
set in moonlock.toml. Refactored wallpaper loading from per-window
Picture::for_filename() to shared gdk::Texture pattern (matching
moonset/moongreet), avoiding redundant JPEG decoding on multi-monitor.
v0.5.0
2026-03-28 14:53:27 +01:00
09e0d47a38 fix: audit fixes — async restart_verify, locale caching, panic safety (v0.5.0)
- restart_verify() now async via spawn_future_local (was blocking main thread)
- stop() uses 3s timeout instead of unbounded
- load_strings() caches locale detection in OnceLock (was reading /etc/locale.conf on every call)
- child_get() replaced with child_value().get() for graceful D-Bus type mismatch handling
- Eliminate redundant password clone in auth path (direct move into spawn_blocking)
- Add on_exhausted callback: hides fp_label after MAX_FP_ATTEMPTS
- Set running=false before on_success callback (prevent double-unlock)
- Add 4 unit tests for on_verify_status state machine
- Document GLib-GString/CString zeroize limitation in CLAUDE.md
2026-03-28 10:16:06 +01:00
13b329cd98 perf: async fprintd initialization for instant window display
Move all fprintd D-Bus calls (init, availability check, claim, verify)
from synchronous to async using gio futures. Windows now appear
immediately without waiting for D-Bus — fingerprint label fades in
once fprintd is ready. Single shared FingerprintListener across all
monitors instead of one per monitor.
2026-03-28 09:57:56 +01:00
58c076198f feat: switch logging to systemd journal (v0.4.2)
Replace env_logger + /var/cache/moonlock file logging with
systemd-journal-logger. Logs are now reliably accessible via
journalctl --user -u moonlock, fixing invisible errors in the
systemd user service context.

- Cargo.toml: env_logger → systemd-journal-logger 2.2
- main.rs: setup_logging() uses JournalLog
- PKGBUILD: add systemd-libs dependency
- power.rs: include unstaged systemctl fixes (ABOUTME, --no-ask-password, output())
2026-03-28 01:11:48 +01:00
78bcf90492 fix: use systemctl instead of loginctl for reboot/poweroff
loginctl has no reboot/poweroff subcommands — these are systemctl
commands. The error was silently swallowed because stderr wasn't
captured and logs went to a non-existent directory.
2026-03-28 00:53:14 +01:00
17f8930ff7 fix: security and correctness audit fixes (v0.4.1)
PAM conv callback: check msg_style (password only for ECHO_OFF),
handle strdup OOM with proper cleanup, null-check PAM handle.

Fingerprint: self-wire D-Bus g-signal in start() via Rc<RefCell<>>
and connect_local — VerifyStatus signals are now actually dispatched.
VerifyStop before VerifyStart in restart_verify.

Lockscreen: password entry stays active after faillock threshold
(PAM decides lockout, not UI), use Zeroizing<String> from GTK entry.

Release builds exit(1) without ext-session-lock-v1 support.

Config: fingerprint_enabled as Option<bool> so empty user config
does not override system config.

Dead code: remove unused i18n strings and fingerprint accessors,
parameterize faillock_warning max_attempts.
v0.4.1
2026-03-28 00:06:27 +01:00
64f032cd9a fix: PKGBUILD depends on gtk-session-lock (not gtk4-session-lock) 2026-03-27 23:28:11 +01:00
4968b7ee2d Merge rust-rewrite: moonlock v0.4.0 Rust rewrite 2026-03-27 23:18:03 +01:00
60e63a6857 Fix Rust 2024 unsafe block warnings in PAM callback
Wrap raw pointer operations in explicit unsafe blocks inside
the unsafe extern "C" conv callback, as required by Rust 2024
edition. Remove unused mut binding.
2026-03-27 23:13:23 +01:00
817a9547ad Rewrite moonlock from Python to Rust (v0.4.0)
Complete rewrite of the Wayland lockscreen from Python/PyGObject to
Rust/gtk4-rs for memory safety in security-critical PAM code and
consistency with the moonset/moongreet Rust ecosystem.

Modules: main, lockscreen, auth (PAM FFI), fingerprint (fprintd D-Bus),
config, i18n, users, power. 37 unit tests.

Security: PAM conversation callback with Zeroizing password, panic hook
that never unlocks, root check, ext-session-lock-v1 compositor policy,
absolute loginctl path, avatar symlink rejection.
2026-03-27 23:09:54 +01:00
7de3737a61 Revert "feat: fade-in animation for panel and wallpaper windows"
This reverts commit 4a2bbb3e98adfeded7fa88332e60e1ab3e3b14b0.
2026-03-27 15:12:26 +01:00
4a2bbb3e98 feat: fade-in animation for panel and wallpaper windows
CSS opacity transition (350ms ease-in) triggered via adding
a 'visible' class after the window is mapped.
2026-03-27 14:45:10 +01:00
fe6421c582 Move power confirmation below fingerprint label with own text
Confirmation prompt is now a self-contained box (label + buttons)
appended at the bottom of the login box instead of reusing the
error label above the fingerprint text.
2026-03-26 22:18:58 +01:00
fb11c551bd Security hardening based on triple audit (security, quality, performance)
- Remove SIGUSR1 unlock handler (unauthenticated unlock vector)
- Sanitize LD_PRELOAD (discard inherited environment)
- Refuse to run as root
- Validate D-Bus signal sender against fprintd proxy owner
- Pass bytearray (not str) to PAM conversation callback for wipeable password
- Resolve libc before returning CFUNCTYPE callback
- Bundle fingerprint success idle_add into single atomic callback
- Add running/device_proxy guards to VerifyStart retries with error handling
- Add fingerprint attempt counter (max 10 before disabling)
- Add power button confirmation dialog (inline yes/cancel)
- Move fingerprint D-Bus init before session lock to avoid mainloop blocking
- Resolve wallpaper path once, share across all monitor windows
- Document faillock as UI-only (pam_faillock handles real brute-force protection)
- Fix type hints (Callable), remove dead import (c_char), fix import order
v0.3.0
2026-03-26 22:11:00 +01:00
5fda0dce0c Replace crash guard with SIGUSR1 unlock and crash logging
Remove sys.excepthook that unlocked on crash — this violated
ext-session-lock-v1 security model where the compositor must keep
the screen locked if the client dies (per protocol spec and hyprlock
reference). Now: crashes are logged but session stays locked.
SIGUSR1 handler added for external recovery (e.g. wrapper script).
v0.2.2
2026-03-26 21:11:42 +01:00
3f31387305 Add crash guard, logging, and defensive error handling to prevent lockout
Global sys.excepthook unlocks the session on unhandled exceptions.
Structured logging to stderr and optional file at /var/cache/moonlock/.
Window creation, CSS loading, and fingerprint start wrapped in
try/except with automatic session unlock when all windows fail.
v0.2.1
2026-03-26 17:56:45 +01:00
7cee4f4f8d Bump version to 0.2.0 v0.2.0 2026-03-26 16:31:20 +01:00
1ed42d51d1 Make login box background transparent v0.1.1 2026-03-26 16:31:01 +01:00
a05c2030e8 Clean dist/ before wheel build to prevent stale artifacts
Version bumps leave old wheels in dist/, causing the glob to
expand to multiple files and python-installer to fail.
2026-03-26 15:49:37 +01:00
22f725e4ac Bump version to 0.1.1 2026-03-26 15:44:37 +01:00
b8e060b850 Fix fprintd AlreadyInUse error by respecting done flag
VerifyStart was called unconditionally on retry/no-match statuses,
ignoring the done parameter from fprintd's VerifyStatus signal.
When done=False the verify session is still active, causing
AlreadyInUse errors. Now only restarts verification when done=True.
2026-03-26 15:43:27 +01:00
c759919367 Simplify pkgver() to require tags v0.1.0 2026-03-26 14:02:06 +01:00
9539d83c85 Fix pkgver() stdout leak in PKGBUILD 2026-03-26 14:00:16 +01:00
b365572033 Show login UI on all monitors for compositor-agnostic focus
Wayland does not expose absolute pointer coordinates to clients,
so we cannot reliably detect which monitor has focus. Instead,
show the full lockscreen UI on every monitor — the compositor
assigns keyboard focus to the surface under the pointer via
ext-session-lock-v1.

Share a single FingerprintListener across all windows to avoid
multiple device claims. Also add makepkg build artifacts to
gitignore.
2026-03-26 13:58:45 +01:00
0eefe76a3a Add PKGBUILD and remove stale moongreet icon
Add Arch Linux PKGBUILD for makepkg installation. Installs the
Python package, PAM config, and example config file. Fix pkgver()
to handle repos without tags (sed always exits 0 on empty input).

Remove leftover moongreet icon that was accidentally included in
the data directory.
2026-03-26 13:48:07 +01:00
e7ab4c2e73 Harden auth, user detection, faillock, and LD_PRELOAD handling
- Replace os.getlogin() with pwd.getpwuid(os.getuid()) to prevent
  crashes in systemd/display-manager sessions without a controlling tty
- Cache libpam and libc at module level instead of calling find_library()
  on every auth attempt (spawned ldconfig subprocess each time)
- Disable password entry permanently after FAILLOCK_MAX_ATTEMPTS instead
  of just showing a warning while allowing unlimited retries
- Fix LD_PRELOAD logic to append gtk4-layer-shell instead of skipping
  when LD_PRELOAD is already set (caused silent session lock fallback)
- Ensure password entry keeps focus after errors and escape
2026-03-26 13:35:26 +01:00
dd9937b020 Add wallpaper and default avatar support
Wallpaper with fallback hierarchy: config path > Moonarch system
default (/usr/share/moonarch/wallpaper.jpg) > package fallback.
Applied to both primary and secondary monitors.

Default avatar from Moongreet ecosystem with theme-colored SVG
rendering via PixbufLoader and proper clipping frame (Gtk.Box
with overflow hidden), matching the Moongreet avatar pattern.
2026-03-26 13:01:25 +01:00
d0d390d0cb Fix PAM conversation segfault causing unrecoverable red lockscreen
ctypes auto-converts c_char_p return values to Python bytes, losing
the original malloc'd pointer from strdup(). When PAM called free()
on the response, it hit a ctypes-internal buffer instead — segfault.
Use c_void_p for PamResponse.resp and strdup restype to preserve raw
pointers. Also use calloc/strdup for proper malloc'd memory that PAM
can safely free().

Add try/except in auth thread so UI stays interactive on PAM errors.
2026-03-26 12:43:53 +01:00
db05df36d4 Add security hardening, config system, and integration tests
- Password wiping after PAM auth (bytearray zeroed)
- TOML config loading (/etc/moonlock/ and ~/.config/moonlock/)
- Config controls fingerprint_enabled and background_path
- Integration tests for password/fingerprint auth flows
- Security tests for bypass prevention and data cleanup
- 51 tests passing
2026-03-26 12:36:58 +01:00