OpenRiot v4.1 Release Notes
Games — Release Notes
New: Optional Games Installation
Games are no longer forced. On first run of openriot –install , an interactive prompt asks:
Do you want to install Games (~1.75G)? [Y/n]
• Answering Y (or pressing Enter) installs all nine games and remembers the choice. • Answering n skips games, removes the Games submenu from rofi, and remembers the choice. • To change later, delete ~/.config/openriot/games.cfg and re-run openriot –install .
Disk size shown upfront
The prompt displays the total installed size (~1.75 GB) so users know the cost before committing.
Files added
• source/installer/games.go — GamesPreference() and StripGamesFromRofi()
Files modified
• source/main.go — checks preference before deploying desktop configs • source/installer/cmd.go — checks preference before installing packages • source/installer/games.go — prompt includes size hint
Release Notes — settings.go Pure-Go Refactor
What Was Done
File: source/settings/settings.go + source/polybar/polybar.go
Replaced shell subprocess self-reinvocations in the Settings menu with direct Go function calls, eliminating 4 sh -c shell-outs.
Setting │ Before │ After │ Status ───────────────┼──────────────────────────────────────────┼──────────────────────────┼──────────── WireGuard VPN │ exec.Command(“sh”, “-c”, │ wireguard.Toggle() │ ✅ Working │ “$HOME/.local/share/openriot/install/ope │ │ │ nriot –wireguard”).Start() │ │ Night Light │ exec.Command(“sh”, “-c”, │ nightlight.Toggle() │ ✅ Working │ “$HOME/.local/share/openriot/install/ope │ │ │ nriot –night-light”).Start() │ │ Stealth Mode │ exec.Command(“sh”, “-c”, │ macspoof.StealthToggle()│ ✅ Working │ “$HOME/.local/share/openriot/install/ope │ + notifications │ │ nriot –stealth”).Start() │ │ Proton Sync │ exec.Command(“sh”, “-c”, │ polybar.TriggerSync() │ ✅ Working │ “$HOME/.local/share/openriot/install/ope │ │ │ nriot –proton-drive-sync”).Start() │ │
UX Fixes
• Stealth Mode notifications: Added proper notifications (restarting → enabled/disabled) to match –stealth CLI behavior. • Proton Sync label: Changed label from “Turn on/Turn off” to “(Sync)” since it’s an action, not a toggle. Implemented via new label field on entry struct. • Proton Sync not-configured: Added “Not configured” notification when Proton Drive is not set up.
New Function
source/polybar/polybar.go — TriggerSync()
Exported function that encapsulates the full sync flow:
- Check if configured → send “Not configured” notification if not
- Check sync state → send “Synchronized” notification if already synced
- Send “Syncing…” notification and launch alacritty with sync menu
Security Fixes
CVE-level: MAC Spoofing Shell Injection & TOCTOU Race ( source/macspoof/macspoof.go:104 )
The EnableRandomMAC function previously constructed a root-privileged shell command via fmt.Sprintf with unvalidated user input:
// BEFORE (v4.0) — vulnerable
cmd := exec.Command("doas", "sh", "-c",
fmt.Sprintf(`... > /tmp/hostname.tmp && mv /tmp/hostname.tmp %s`, ...))
Two critical vulnerabilities existed:
• Shell injection: Interface names were concatenated into hostnameFile ( “/etc/hostname.” + iface ) without validation. Any shell metacharacter in iface would execute arbitrary commands as root via doas . • TOCTOU race: Writing to predictable /tmp/hostname.tmp allowed symlink attacks. An attacker could create /tmp/hostname.tmp → /etc/passwd and the doas mv would overwrite arbitrary system files as root.
Fix: Complete rewrite using doas ed with no shell subprocess, no temp files, and strict regex validation ( ^[a-z]+[0-9]+$ ):
// AFTER (v4.1) — safe
cmd := exec.Command("doas", "ed", "-s", hostnameFile)
cmd.Stdin = strings.NewReader("0a\nlladdr random\n.\nw\nq\n")
DisableRandomMAC already used safe doas sed (no shell, no temp file) and remains unchanged.
Core Dumps Persisting for GUI Applications ( config/xsession/openriot-xsession , config/fish/config.fish )
Despite login.conf coredump=0 being set during install, Firefox and other X11 applications continued generating firefox.core files in ~/ because:
• login.conf only affects processes that go through login(1) • GUI apps launched via xenodm → ~/.xsession → i3 do not inherit login.conf resource limits
Fix: Added ulimit -c 0 to:
• config/xsession/openriot-xsession:6 — the parent of all X11 processes. This propagates to Firefox, GTK apps, and everything launched from the desktop. • config/fish/config.fish:9 — backup for shell-launched processes.
This is a breaking behavioral change for users who rely on core dumps. The .xsession file always overwrites on install ( docs/architecture.md states “ALWAYS overwrite”), so this will take effect on next openriot –install .
Lock Screen System Complete Rewrite
Directory-Based Organization Replaces Flat Prefix Files
v4.0 used a flat directory with filename prefixes:
~/.local/share/openriot/Locked/ ├── locked_01.jpg ├── locked_02.jpg ├── … ├── stealth_01.jpg └── stealth_02.jpg
v4.1 uses semantic subdirectories:
~/.local/share/openriot/Locked/ ├── default/ # shown in default mode, AND in stealth mode ├── stealth/ # shown only in stealth mode ├── holiday/ # shown in BOTH modes (seasonal, optional) └── retro/ # shown in BOTH modes (classic wallpapers, optional)
Files changed: source/lock/lock.go
Behavior matrix:
Mode │ Pools included ────────────────────────────┼───────────────────────────────────────────────────────────────────── Default (stealth OFF) │ default/.jpg + holiday/.jpg + retro/.jpg Stealth (stealth ON) │ default/.jpg + stealth/.jpg + holiday/.jpg + retro/*.jpg
Bug fixed: In v4.0, stealth mode exclusively showed stealth_.jpg and completely hid locked_.jpg . Users in stealth mode lost access to their entire default wallpaper collection. v4.1 pools both directories.
Migration required: Existing locked_.jpg files must be moved to default/.jpg and stealth_.jpg to stealth/.jpg . The holiday/ and retro/ directories are optional — create them to add images, delete them to revert.
Bug Fixes
Workspace Notifications Restored ( source/workspace/workspace.go:52 )
v3.x showed “On workspace 2” when pressing SUPER+2 while already on workspace 2. v4.0 broke this by silently returning with no notification:
// v4.0 (broken)
current := GetCurrent()
if current == target {
return // Already on this workspace — NO notification
}
Fix: Notify even when already on the target workspace:
// v4.1
if current == target {
notify.SendNotify(iconName, "Workspace", fmt.Sprintf("On workspace %d", target), "normal",
1500, 0)
return
}
Transmission-GTK Ignored Daemon Config ( install/packages.yaml:215 )
transmission-gtk stores settings in ~/.config/transmission/settings.json , while the standalone daemon uses ~/.config/transmission-daemon/settings.json . v4.0 only deployed to the daemon directory, so transmission-gtk (launched via polybar/rofi) ignored all defaults including blocklist, speed limits, and RPC settings.
Fix: Added second config deployment entry:
- pattern: “transmission-daemon/settings.json” target: “~/.config/transmission” preserve_if_exists: [settings.json]
Cleanup
Removed Duplicate –notify-dunst Command ( source/main.go:742 , docs/architecture.md:145 )
–notify-dunst and –notify-status were byte-identical handlers calling notify.Status() .
Removed –notify-dunst entirely. –notify-status is the canonical command for polybar integration.
Installer Changes
Stealth Mode No Longer Enabled by Default ( install/packages.yaml:298 )
Removed the mac-spoof source build step from the install pipeline. MAC randomization is no longer automatically enabled during openriot –install . Users must explicitly toggle it via the settings menu or openriot –stealth .
Files Changed
File │ Change ─────────────────────────────────────┼──────────────────────────────────────────────────────────── source/macspoof/macspoof.go │ Security rewrite of EnableRandomMAC source/lock/lock.go │ Directory-based lock screen pooling + holiday/retro │ support source/workspace/workspace.go │ Restored “On workspace N” notification source/main.go │ Removed –notify-dunst duplicate config/xsession/openriot-xsession │ Added ulimit -c 0 config/fish/config.fish │ Added ulimit -c 0 install/packages.yaml │ Removed auto-enable stealth; added transmission-gtk config │ path docs/architecture.md │ Removed –notify-dunst documentation