From b7e4fbfa321d6d01ce99ad4805389a6f25edc929 Mon Sep 17 00:00:00 2001 From: DuskyElf Date: Sun, 2 Aug 2026 09:10:25 +0530 Subject: [PATCH] fix(security): pin power.sh into store, sudo targets /usr/local/sbin --- AGENTS.md | 4 ++-- gui/niri.nix | 12 ++++++------ system.nix | 23 ++++++++++++++++++++++- 3 files changed, 30 insertions(+), 9 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index d759372..45ed990 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -99,7 +99,7 @@ Each individual setting is discoverable; the pattern is not. Respect these when - The agent shell runs in a jailed sandbox (hostname "jail"), NOT the real machine: no niri, no /sys, no DRM, no sudo, no systemctl, no bash network (curl fails with bwrap errors). Anything needing system access must be given to the user as a command block, then their pasted output interpreted: rebuilds, DRM/backlight inspection, journalctl, niri msg, udevadm, systemctl. The user is the only bridge to system state; code edits happen in the jail, system verification happens on the machine. - Network in the jail: web_search works but ONE call per turn with 2-4 queries; fetch_content works for raw.githubusercontent.com at any rev and the GitHub API. -- sudo NOPASSWD is scoped to `/home/duskyelf/.config/scripts/power.sh` ONLY (root system.nix). Any root action from a keybind must route through power.sh, or sudo will prompt and hang the keybind. -- scripts/ is symlinked into ~/.config via mkOutOfStoreSymlink: edits to scripts/ are live immediately, no rebuild needed. +- sudo NOPASSWD is scoped to `/usr/local/sbin/power.sh` ONLY (root system.nix). power.sh is store-pinned: content is read from scripts/power.sh at eval time and the activation script symlinks the immutable store copy into /usr/local/sbin. Repo edits to power.sh take effect only on the next nixos-rebuild. Any root action from a keybind must route through power.sh, or sudo will prompt and hang the keybind. +- scripts/ is symlinked into ~/.config via mkOutOfStoreSymlink: edits to scripts/ are live immediately, no rebuild needed. Exception: power.sh is NOT live (store-pinned, see the sudo bullet above), so edit it and run a nixos-rebuild for it to take effect. - piBTW and opencodeBTW are agent submodules; their dirty states are noise, never commit them. - niri 26.04 source is unpacked at /nix/store/k2nfl71r8lfxzgzj2yhfxycjkbqxx3im-source if internals are needed. diff --git a/gui/niri.nix b/gui/niri.nix index 9714225..41275c7 100644 --- a/gui/niri.nix +++ b/gui/niri.nix @@ -183,9 +183,9 @@ in "Mod+T".action = spawn "kitty"; "Mod+O".action = spawn "fuzzel"; - "Mod+8".action = spawn "bash" "-c" ("sudo ~/.config/scripts/power.sh powersave"); - "Mod+9".action = spawn "bash" "-c" ("sudo ~/.config/scripts/power.sh performance"); - "Mod+0".action = spawn "bash" "-c" ("sudo ~/.config/scripts/power.sh ultra-powersave"); + "Mod+8".action = spawn "bash" "-c" ("sudo /usr/local/sbin/power.sh powersave"); + "Mod+9".action = spawn "bash" "-c" ("sudo /usr/local/sbin/power.sh performance"); + "Mod+0".action = spawn "bash" "-c" ("sudo /usr/local/sbin/power.sh ultra-powersave"); "XF86AudioMute" = { allow-when-locked = true; @@ -293,10 +293,10 @@ in # retries. Press again if the attach does not stick. if [ "$(cat /sys/class/backlight/asus_screenpad/bl_power 2>/dev/null)" = "4" ]; then niri msg output DP-2 off || true - sudo ~/.config/scripts/power.sh screenpad off || true + sudo /usr/local/sbin/power.sh screenpad off || true notify-send "Secondary Display" "Turned OFF" -t 1000 else - sudo ~/.config/scripts/power.sh screenpad on || true + sudo /usr/local/sbin/power.sh screenpad on || true niri msg output DP-2 on || true notify-send "Secondary Display" "Turned ON" -t 1000 fi @@ -362,7 +362,7 @@ in { argv = [ "sudo" - "~/.config/scripts/power.sh" + "/usr/local/sbin/power.sh" "screenpad" "off" ]; diff --git a/system.nix b/system.nix index ee5ddd3..c4900e4 100644 --- a/system.nix +++ b/system.nix @@ -1,8 +1,24 @@ { config, lib, + pkgs, ... }: +let + # power.sh runs as root via NOPASSWD sudo, so it must never be writable by + # the user. Content is read from scripts/power.sh at eval time and the + # activation script symlinks the immutable store copy into /usr/local/sbin. + # Repo edits only take effect on the next nixos-rebuild, and tampering with + # the writable ~/.config/scripts copy is useless because sudo only matches + # the path below. + powerScript = pkgs.writeTextFile { + name = "power.sh"; + executable = true; + text = + "#!${pkgs.bash}/bin/bash\n" + + lib.removePrefix "#!/usr/bin/env bash\n" (builtins.readFile ./scripts/power.sh); + }; +in { options.hostOptions = { hostName = lib.mkOption { @@ -92,12 +108,17 @@ LC_TIME = "en_IN"; }; + system.activationScripts.powerScript = '' + mkdir -p /usr/local/sbin + ln -sfn ${powerScript} /usr/local/sbin/power.sh + ''; + security.sudo.extraRules = [ { users = [ "duskyelf" ]; commands = [ { - command = "/home/duskyelf/.config/scripts/power.sh"; + command = "/usr/local/sbin/power.sh"; options = [ "NOPASSWD" ]; } ]; -- 2.51.2