Skip to content

fix(web): re-validate stored session name + exact-match tmux target#65

Merged
tzone85 merged 1 commit into
mainfrom
fix/handlekill-session-revalidate
Jun 11, 2026
Merged

fix(web): re-validate stored session name + exact-match tmux target#65
tzone85 merged 1 commit into
mainfrom
fix/handlekill-session-revalidate

Conversation

@tzone85

@tzone85 tzone85 commented Jun 11, 2026

Copy link
Copy Markdown
Owner

Summary

handleKill validated the incoming agent_id with sanitize.ValidIdentifier but accepted the projection-read sessionName at face value before shelling out to tmux kill-session -t <sessionName>. ValidIdentifier permits . (story IDs use it for split-depth notation), and tmux's target syntax treats session.0 as "pane 0 of that session" — killing the wrong thing if the projection ever contained a tampered or migrated row with a dot.

Changes

  • New sanitize.ValidTmuxTarget: stricter than ValidIdentifier — excludes . (pane separator) and : (window separator). Documented why.
  • handleKill re-validates the read-back sessionName; refuses + logs on failure rather than running tmux.
  • Switch the tmux invocation to tmux kill-session -t =<sessionName>. The leading = is tmux's exact-match prefix — even substring-match cases that slipped past ValidTmuxTarget can no longer target adjacent sessions.

Test plan

  • TestValidTmuxTarget table-driven (session.0, session:1, empty, shell metachars, happy paths).
  • TestHandleKill_RejectsUnsafeStoredSessionName seeds an agent with "nxd-session.0" SessionName (passes ValidIdentifier, fails the new ValidTmuxTarget), asserts handleKill refuses.
  • go build ./..., go vet ./..., go test ./... -count=1 -timeout 240s all green locally.

Audit traceability

Security finding SEC-H3 (2026-06-11 sweep).

handleKill validated the incoming agent_id with sanitize.ValidIdentifier
but accepted the projection-read sessionName at face value before
shelling out to `tmux kill-session -t <sessionName>`. ValidIdentifier
allows `.` (story IDs use it for split-depth notation), and tmux's
target syntax treats `session.0` as "pane 0 of that session" —
killing the wrong thing if the projection ever contained a tampered or
migrated row with a dot.

- Add sanitize.ValidTmuxTarget: stricter than ValidIdentifier — excludes
  `.` (pane separator) and `:` (window separator). Documented why.
- handleKill re-validates the read-back sessionName; refuses + logs on
  failure rather than running tmux.
- Switch the tmux invocation to `tmux kill-session -t =<sessionName>`.
  The leading `=` is tmux's exact-match prefix — even substring-match
  cases that slipped past ValidTmuxTarget can no longer target adjacent
  sessions.

3 new tests:
- TestValidTmuxTarget — table-driven, covers session.0 / session:1 /
  empty / shell metachars / happy paths.
- TestHandleKill_RejectsUnsafeStoredSessionName — seeds an agent with
  a "nxd-session.0" SessionName (passes ValidIdentifier on insert,
  fails the new ValidTmuxTarget on read) and asserts handleKill
  refuses without running tmux.

Surfaced by the 2026-06-11 security audit (SEC-H3).
@tzone85 tzone85 merged commit 5ef7286 into main Jun 11, 2026
9 of 10 checks passed
@tzone85 tzone85 deleted the fix/handlekill-session-revalidate branch June 11, 2026 10:56
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.

1 participant