Skip to content

Security hardening: socket squatting fix, metadata sanitization, file perms, CI supply chain - #4

Merged
SimplyJustJessie merged 2 commits into
mainfrom
claude/visual-redesign-dark-theme-e1o79q
Jul 18, 2026
Merged

Security hardening: socket squatting fix, metadata sanitization, file perms, CI supply chain#4
SimplyJustJessie merged 2 commits into
mainfrom
claude/visual-redesign-dark-theme-e1o79q

Conversation

@SimplyJustJessie

Copy link
Copy Markdown
Owner

A security audit of AutoRoute's attack surface — local IPC, untrusted PipeWire metadata, process spawning, file handling, and the CI/packaging supply chain — with fixes for everything found.

Findings fixed

1. Single-instance socket: local-user squat/spoof (the main finding)

With XDG_RUNTIME_DIR unset, the control socket fell back to a predictable name in the shared, world-writable temp dir (/tmp/autoroute.sock). Any local user could pre-bind it — permanently preventing AutoRoute from starting (it would conclude "primary already running" and exit) — or impersonate the primary. Now:

  • the fallback is a private per-user 0700 directory; the chmod doubles as an ownership check and fails closed if another user squatted the path;
  • the bound socket itself is chmod 0600 (defense-in-depth even inside XDG_RUNTIME_DIR).

2. Terminal escape-sequence injection via stream metadata

application.name, media.name, node.name are controlled by any client that opens a PipeWire stream. Control characters in them flowed verbatim into journald/console logs (classic ANSI-escape log injection: screen clearing, title changes, output spoofing) and into the UI. All app-controlled prop strings are now stripped of control characters at parse time — with regression tests covering ESC/BEL/tab/CRLF payloads (test count 65 → 67).

3. rules.json privacy

The rule set is effectively a log of which applications the user runs. The config dir is now created 0700 and the file written 0600 (the atomic-write temp file is re-permissioned before the move, so the final path never exists with loose perms). Existing dirs/files keep whatever the user chose.

4. CI / supply chain

  • Least-privilege workflow token: permissions: contents: read on CI (the default token could write).
  • Dependency vulnerability gate: dotnet list package --include-transitive --vulnerable now fails CI on any hit (current state: clean).
  • CodeQL: new C# scanning workflow — PRs, pushes to main, and a weekly schedule.
  • appimagetool integrity: build-appimage.sh accepts APPIMAGETOOL_SHA256 to pin the downloaded tool (its continuous tag is a moving target, so no hash is hard-coded — set the env in CI to enforce).

5. systemd sandbox hardening

The user service gains NoNewPrivileges, RestrictSUIDSGID, RestrictNamespaces, RestrictRealtime, LockPersonality, and ProtectKernelTunables/Modules/ControlGroups. MemoryDenyWriteExecute is deliberately omitted — the .NET JIT requires writable-executable pages. Also fixes the broken Documentation= URL.

6. Robustness nits

Both regex caches (UI + Engine matcher) are capped so a pathological stream of hot-reloaded rules.json edits can't grow them without bound.

Verified safe (no change needed)

  • Process spawning: pw-link/pw-dump/pw-mon invoked via ArgumentList (no shell, no injection), addressed by numeric ids only — untrusted node names never reach a command line; link props passed as JSON-escaped strings.
  • Parsers: System.Text.Json with default depth limits; rules deserialization is source-generated with no polymorphism.
  • User regexes: both matchers already enforce 100 ms backtracking timeouts and swallow malformed patterns.
  • Dependencies: dotnet list package --vulnerable reports no known-vulnerable packages (now enforced by CI).

Verification

  • Build clean; 67/67 tests, --smoke, --smoke-ui, --stress all pass in Debug and Release.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Jac4PWhnEzh7j5f5NaafJ1


Generated by Claude Code

…chain

Security audit of the attack surface (local IPC, untrusted PipeWire
metadata, process spawning, file handling, CI/packaging supply chain).
Process spawning was already safe (numeric ids only, ArgumentList — no
shell, escaped JSON props) and `dotnet list package --vulnerable` is
clean. Findings fixed:

- SingleInstanceGuard: with XDG_RUNTIME_DIR unset, the control socket
  landed at a predictable name in the shared world-writable temp dir,
  where any local user could squat or spoof it. The fallback is now a
  private 0700 per-user directory (chmod doubles as an ownership check
  and fails closed on a squatter's dir), and the bound socket is
  chmod 0600 as defense-in-depth.
- PwDumpReader: application.name / media.name / node.name are attacker-
  controlled by any client that opens a stream; control characters
  (incl. ESC) flowed verbatim into journald/console logs (terminal
  escape-sequence injection) and the UI. All app-controlled prop
  strings are now stripped of control chars, with regression tests.
- RuleStore: rules.json reveals which apps the user runs; the config
  dir is now created 0700 and the file written 0600 (atomic-write temp
  file re-permissioned before the move).
- Regex caches (both matchers): capped so a pathological stream of
  hot-reloaded rules.json edits cannot grow them without bound.
- CI: workflow token dropped to contents:read (least privilege), a
  dependency-vulnerability audit gate added, and a CodeQL C# workflow
  (PRs + weekly) introduced.
- build-appimage.sh: optional APPIMAGETOOL_SHA256 pin to verify the
  downloaded appimagetool (its "continuous" tag is a moving target, so
  no hash is hard-coded).
- systemd unit: sandbox hardening block (NoNewPrivileges,
  RestrictSUIDSGID/Namespaces/Realtime, LockPersonality,
  ProtectKernelTunables/Modules/ControlGroups —
  MemoryDenyWriteExecute deliberately omitted for the .NET JIT), and
  fixed the broken Documentation= URL.

Build clean; 67 tests, --smoke, --smoke-ui and --stress all pass in
Debug and Release.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jac4PWhnEzh7j5f5NaafJ1
@github-advanced-security

Copy link
Copy Markdown

You are seeing this message because GitHub Code Scanning has recently been set up for this repository, or this pull request contains the workflow file for the Code Scanning tool.

What Enabling Code Scanning Means:

  • The 'Security' tab will display more code scanning analysis results (e.g., for the default branch).
  • Depending on your configuration and choice of analysis tool, future pull requests will be annotated with code scanning analysis results.
  • You will be able to see the analysis results for the pull request's branch on this overview once the scans have completed and the checks have passed.

For more information about GitHub Code Scanning, check out the documentation.

LICENSE file (MIT, 2026 SimplyJessie), a license section in the README,
and the AUR PKGBUILD updated to license=('MIT') with the standard
/usr/share/licenses install — the last blocker before publishing it.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jac4PWhnEzh7j5f5NaafJ1
@SimplyJustJessie
SimplyJustJessie merged commit 97250c3 into main Jul 18, 2026
4 checks passed
SimplyJustJessie pushed a commit that referenced this pull request Aug 24, 2026
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.

3 participants