Skip to content

Code audit: security fixes, multi-client backend, and bug fixes#14

Closed
Batuhan4 wants to merge 4 commits intomainfrom
cursor/project-code-audit-827e
Closed

Code audit: security fixes, multi-client backend, and bug fixes#14
Batuhan4 wants to merge 4 commits intomainfrom
cursor/project-code-audit-827e

Conversation

@Batuhan4
Copy link
Copy Markdown
Owner

Code Audit Summary

Full security and code quality audit of the victus-control codebase, plus review of PR #10 (GNOME Shell extension).


Security Fixes

Critical: Command injection via system()/popen() (backend)

The backend passed user-supplied arguments (fan number, speed, mode, hex color) directly to system() and popen(), which allowed shell metacharacter injection by any socket client. A malicious client connecting to the Unix socket could execute arbitrary commands as root via sudo.

Fix: Replaced all system()/popen() invocations with fork()+execvp() via a new run_helper() function that never invokes a shell. Added is_safe_shell_arg() and is_valid_hex_color() input validation as defense-in-depth.

Files: backend/src/fan.cpp, backend/src/keyboard.cpp


Architecture Improvements

Multi-client backend support

The backend previously handled only one client at a time in a blocking read loop. If the GNOME Shell extension (PR #10) held a persistent connection, the GTK frontend could not connect, and vice versa.

Fix: Each accepted client now spawns its own detached thread so multiple clients (GTK app, GNOME extension, CLI tool) can connect simultaneously.

File: backend/src/main.cpp

Graceful signal handling

The backend had no signal handling — SIGTERM from systemd caused an abrupt exit without cleanup, leaving the socket file behind.

Fix: Installed SIGTERM/SIGINT handlers that cleanly break the accept loop, close the server socket, and unlink the socket file.

File: backend/src/main.cpp


Bug Fixes

set-fan-speed.sh — silent failure on missing target file

When the sysfs fan target file didn't exist, the script printed an error but continued executing, potentially writing to an unrelated path.

Fix: Exit with error code 1 if the target file doesn't exist. Added input validation for fan number and speed (must be positive integers). Upgraded to set -euo pipefail.

get_keyboard_color — double file open

get_keyboard_color() opened the sysfs color file twice: once to test existence via std::ifstream, then again via read_text_file().

Fix: Single call to read_text_file() with empty-string check.

About dialog icon — relative path failure

The about dialog loaded victus-icon.svg from CWD, which fails unless launched from the source directory.

Fix: Use the installed icon path via DATADIR compile-time macro (/usr/share/icons/hicolor/48x48/apps/victus-icon.svg).

Unused gtkmm_dep in root meson.build

gtkmm_dep = dependency('gtk4') was declared but never referenced. Each subproject correctly declares its own dependencies.

Fix: Removed the unused variable.


PR #10 Review Notes (GNOME Shell Extension)

The GNOME Shell extension in PR #10 is well-structured, but has these issues worth addressing:

  1. Synchronous I/O blocks GNOME Shell: _sendCommand() uses write_all() and read_bytes() synchronously after async connection setup. These block the GNOME Shell main thread, causing UI stuttering during every 3-second status poll. Should use write_bytes_async()/read_bytes_async().

  2. Hardcoded thermal sensor path: /sys/class/thermal/thermal_zone0/temp may not be the CPU sensor on all systems. The backend already does proper sensor discovery — the extension should query temperature through the backend protocol instead.

  3. Excessive notifications: Main.notify() fires on every fan mode or color change, which is intrusive. Consider removing or debouncing these.

  4. No reconnection logic: If the backend restarts, the cached connection becomes stale and all subsequent commands fail silently until the extension is restarted.

  5. Single-client backend assumption: The extension keeps a persistent socket connection. Without the multi-client fix in this PR, this would prevent the GTK frontend from connecting at all.


Additional Observations (not fixed in this PR)

  • Frontend blocks UI thread: send_command_async().get() is called from GTK signal handlers, blocking the main loop. Should use g_idle_add() callbacks.
  • main.hpp is redundant: The VictusControl class is fully defined in main.cpp.
  • victus-fan-sudoers is unused: Only victus-control-sudoers is installed.
  • Detached threads in frontend set_fan_rpm: Threads that access socket_client can outlive the object.
Open in Web Open in Cursor 

cursoragent and others added 4 commits March 22, 2026 21:44
…d injection

The backend passed user-supplied arguments (fan number, speed, mode,
hex color) directly to system() and popen(), which allowed shell
metacharacter injection by any socket client.

Replace all shell-based invocations with fork()+execvp() via a new
run_helper() function that never invokes a shell. Add is_safe_shell_arg()
validation as a defense-in-depth measure. Add is_valid_hex_color()
validation for RGB zone writes in keyboard.cpp.

Co-authored-by: Batuhan Bayazit <Batuhan4@users.noreply.github.com>
- Validate fan number and speed are positive integers before use
- Exit with error if the target sysfs file does not exist instead of
  silently continuing
- Use set -euo pipefail for consistent error handling
- Remove debug echo that ran on every invocation

Co-authored-by: Batuhan Bayazit <Batuhan4@users.noreply.github.com>
The variable was declared but never referenced by any subproject.
Each subproject correctly declares its own dependency('gtk4').

Co-authored-by: Batuhan Bayazit <Batuhan4@users.noreply.github.com>
The about dialog loaded victus-icon.svg from the current working
directory, which fails unless the user happens to launch the app
from the source tree. Use DATADIR to construct the absolute path
to the installed icon under the hicolor icon theme hierarchy.

Co-authored-by: Batuhan Bayazit <Batuhan4@users.noreply.github.com>
@cursor
Copy link
Copy Markdown

cursor Bot commented Mar 22, 2026

Cursor Agent can help with this pull request. Just @cursor in comments and I'll start working on changes in this branch.
Learn more about Cursor Agents

@github-actions
Copy link
Copy Markdown

🤖 Hi @Batuhan4, I've received your request, and I'm working on it now! You can track my progress in the logs for more details.

@github-actions
Copy link
Copy Markdown

🤖 I'm sorry @Batuhan4, but I was unable to process your request. Please see the logs for more details.

@Batuhan4
Copy link
Copy Markdown
Owner Author

Closing as superseded by the consolidated local fix branch and follow-up testing.

@Batuhan4 Batuhan4 closed this Mar 22, 2026
@Batuhan4 Batuhan4 deleted the cursor/project-code-audit-827e branch March 22, 2026 22:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants