mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-08-02 03:28:28 -04:00
ca89e12963
* core: fix security and concurrency issues found in backend audit Security: - privesc: pipe the sudo password via stdin (sudo -S) instead of embedding it in the command string, so it no longer appears in argv (readable by any local user via /proc/<pid>/cmdline or ps) - greeter: tokenize a session .desktop Exec= line into argv and execve directly instead of running it through /bin/sh -c, closing a command- injection path via user-writable ~/.local/share/wayland-sessions - plugins: reject path-separator/.. in plugin id/name before joining into a filesystem path, closing an arbitrary-directory-delete in the uninstall/update fallback - keybinds/hyprland: always quote unrecognized bind actions/keys when writing generated Lua; only re-emit genuine round-tripped custom Lua verbatim (tracked via an explicit flag), closing a Lua-injection path - desktop/mimeapps: reject newline/bracket in mime/desktop-id fields so they can't inject fake sections into the shared mimeapps.list Robustness / concurrency: - server: recover panics in the request-dispatch path so one bad handler can't crash the daemon and drop every client - go-wayland: recover panics in the shared dispatch choke point so a malformed compositor event can't crash CLI tools / the daemon - server: per-connection D-Bus client ID instead of a shared constant, fixing cross-client signal delivery and subscription teardown - network: guard the NetworkManager device maps with a mutex (a concurrent map read/write here is an unrecoverable fatal error) - cups: close the event channel on Stop() so Unsubscribe() of the last subscriber no longer deadlocks; allocate the fresh channel in Start() - freedesktop: reuse the shared session conn for the settings watcher and tear it down in Close(), fixing a per-Manager conn+goroutine leak - clipboard: mutex-guard lazy dbusConn creation - geolocation: use WithMatchMember for the GeoClue2 LocationUpdated signal (was WithMatchSender with an interface.member string, so the match never fired and live location updates never arrived) - screenshot: set failed=true on buffer/pool creation errors so the dispatch loop doesn't wait forever for a ready/failed that never comes * apply code review comments --------- Co-authored-by: bbedward <bbedward@gmail.com>
58 lines
1.6 KiB
Go
58 lines
1.6 KiB
Go
package greeter
|
|
|
|
import (
|
|
"path/filepath"
|
|
"reflect"
|
|
"testing"
|
|
)
|
|
|
|
func TestParseExecString(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
tests := []struct {
|
|
name string
|
|
exec string
|
|
want []string
|
|
}{
|
|
{"plain", "niri --session", []string{"niri", "--session"}},
|
|
{"extra spaces", "niri --session", []string{"niri", "--session"}},
|
|
{"double quoted arg", `env "with space" run`, []string{"env", "with space", "run"}},
|
|
{"single quoted arg", `env 'with space' run`, []string{"env", "with space", "run"}},
|
|
{"escaped quote in quotes", `sh "say \\"hi\\""`, []string{"sh", `say "hi"`}},
|
|
{"field code dropped", "gnome-session %U", []string{"gnome-session"}},
|
|
{"field code mid-arg", "app --url=%u --run", []string{"app", "--url=", "--run"}},
|
|
{"literal percent", "app 100%% done", []string{"app", "100%", "done"}},
|
|
{"shell metachars stay literal", "sh -c $(reboot); echo", []string{"sh", "-c", "$(reboot);", "echo"}},
|
|
{"empty", "", nil},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
if got := parseExecString(tt.exec); !reflect.DeepEqual(got, tt.want) {
|
|
t.Fatalf("parseExecString(%q) = %#v, want %#v", tt.exec, got, tt.want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestExecFromDesktopFileOnlyReadsDesktopEntryGroup(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
path := filepath.Join(t.TempDir(), "example.desktop")
|
|
writeTestFile(t, path, `[Desktop Action other]
|
|
Exec=/wrong/binary
|
|
|
|
[Desktop Entry]
|
|
Name=Example
|
|
Exec = /right/binary --flag
|
|
`)
|
|
|
|
got, err := execFromDesktopFile(path)
|
|
if err != nil {
|
|
t.Fatalf("execFromDesktopFile returned error: %v", err)
|
|
}
|
|
if got != "/right/binary --flag" {
|
|
t.Fatalf("execFromDesktopFile = %q, want %q", got, "/right/binary --flag")
|
|
}
|
|
}
|