fix: v0.5.0 security and robustness fixes from the 2026-10-07 review
build-deb / Lint, test, package (push) Successful in 1m49s
build-deb / Deploy to CT 126 (push) Skipped
build-deb / Notify on failure (push) Skipped

- Ask Claude: strip control characters, send as bracketed paste (closes #2)
- end: forget before kill, so ending from inside a session leaves no ghost (closes #3)
- reconnects use `attach --existing` and never resurrect ended/renamed sessions (closes #4)
- repo: git --no-optional-locks, no safe.directory override, refresh on connect/bell/60s (closes #5)
- uploads: unique names via mktemp, cleanup trap on hangup (closes #6)
- clipboard: write-only OSC 52 provider, tmux allow-passthrough off (closes #7)
- uploads: size check up front, streamed slices, idle timeout (closes #9)
- --list: path last in TSV rows, tolerant numbers (closes #10)
- tokens via curl config on stdin; userinfo stripped from remote URLs (closes #11)
- ttyd max clients 32 and at most 2 concurrent side-channel calls (#8; BroadcastChannel polling still open)
- tmux: fixed terminal-features index (no duplicates on re-source), no status-right clock

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-07 20:15:47 -04:00
co-authored by Claude Opus 5.5
parent 364bd9b66f
commit 7aa624bc13
9 changed files with 192 additions and 50 deletions
+8
View File
@@ -67,6 +67,14 @@ export function slugify(text) {
.replace(/^[-_]+/, '').replace(/-+$/, '').slice(0, 64);
}
// Untrusted text (e.g. Grafana alert annotations) typed into a terminal: drop
// every control character so it can't run a command (newline in a shell),
// submit early (CR) or inject escape sequences (devdesk#2).
export function pasteSafe(text) {
// eslint-disable-next-line no-control-regex
return String(text ?? '').replace(/[\x00-\x1f\x7f]+/g, ' ');
}
export function stripAnsi(text) {
// eslint-disable-next-line no-control-regex
return text.replace(/\x1b\[[0-9;?]*[ -/]*[@-~]/g, '').replace(/\x1b\][^\x07\x1b]*(\x07|\x1b\\)/g, '');