Files
tai/research/shell-multiplexer-auto-attach/elastic-detection-rule-interactive-terminal-python.md
T
retoorandClaude Sonnet 5 9dbd1fe667 Add plexer subsystem, container test infra, and last-resort opencode box backend
- Plexer: always-active terminal multiplexing. NativePlexerController/
  TmuxPlexerController share one interface, chosen by which env var is
  already set (TAI_PLEXER_SOCKET vs TMUX_PANE); NativePlexerBackend is
  the pty.fork()-based wrapper (raw mode, SIGWINCH resize forwarding,
  a Unix-socket control protocol, continuous session logging, a
  Ctrl+A prefix key distinct from tmux's own Ctrl+B). Auto-wraps new
  interactive shells via a .bashrc hook mirroring the existing
  command-not-found install pattern, gated on $TMUX/$TAI_PLEXER_ACTIVE/
  a $HOME/.tai-no-plexer bypass. New plexer_send/read/type/status
  tools, env-gated on a detected controller.
- tests/container.py + docker-compose.yml + tests/docker/Dockerfile:
  a disposable podman/docker image for the tests that must never touch
  a real machine (installing the plexer hook into a real ~/.bashrc, a
  live tmux session). Required suite (test_seal.py, test_tai.py,
  tests/plexer.py, tests/bashrc.py) gates the result; tests/rag.py
  runs as best-effort since its real-LLM dependency can't be satisfied
  inside a disposable container with no nested engine.
- tests/bashrc.py: real end-to-end hook install + bash -i auto-wrap,
  anti-recursion, tmux-active skip, non-interactive skip, a live
  TmuxPlexerController test, and an install/uninstall round-trip.
- tests/plexer.py: NativePlexerBackend under a real pty, plus a
  dedicated robustness pass (file permissions, >64KB payload framing,
  a malformed control request, a genuine self-deadlock fix in the
  write-to-child path).
- tai_test.py: the shared async process-driving framework (pipe/pty
  transport, group-wide kill-and-reap, a StdinBridge for --interactive)
  both test files build on.
- ChatClient last-resort backend: when there's no local opencode CLI
  but the sandbox box is already running, install opencode into it
  (official Node tarball, not apt -- apt's nodejs/npm pull in
  webpack/babel/jest as transitive deps) and route through it instead
  of giving up. Only reachable after the first retry round already
  failed everything else; never creates the box itself. TmuxPlexerController.status()
  fixed to use `list-panes` instead of `display-message -p`, which
  silently fell back to the default pane instead of erroring against
  a dead target.
- Fix 4 pre-existing test_tai.py bugs surfaced by running it in a
  clean environment for the first time: two stale mock signatures
  (subprocess.run's stdout= kwarg, Chat.complete's deadline= kwarg),
  one $TMUX-dependent catalog assertion, one tty-dependent color
  assertion.
- research/: a sourced research archive (Source Dossier/Citation
  Card/Conclusion tiers) backing the above design decisions, with its
  own audit.py consistency checker.
- .gitignore: fix a blanket *.md rule that was about to silently drop
  the entire research/ archive from version control; add __pycache__/
  and the one-off debug transcript this session started from.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-10 04:36:05 +02:00

2.8 KiB

Interactive Terminal Spawned via Python (Elastic detection rule)

Metadata

Field Value
Institute Molodetz Institute — Research & Retrieval Division
Subject shell-multiplexer-auto-attach
Document type Source Dossier
Tier 1
Source title Interactive Terminal Spawned via Python
Source URL https://detection.fyi/elastic/detection-rules/linux/execution_python_tty_shell/
Source publisher / author Elastic (detection-rules), mirrored by detection.fyi
Source type vendor docs
Source date (published) Unknown — not stated
Date researched 2026-10-09
Researched by tai (agent), model: Claude Sonnet 5, on behalf of retoor
Research method web search synthesis
Confidence High
Status Active

Summary

A security detection rule (also mirrored at elastic.co's own docs) that fires when a Python process spawns an interactive pty-backed shell — a pattern commonly associated with reverse shells, but one the rule's own documentation explicitly acknowledges is also produced by legitimate administrative scripts and automation tools. The prescribed remediation for false positives is to identify and allowlist the specific known-good tools, not to weaken the detection signal itself.

Key findings

  • A security vendor, writing a detection rule specifically meant to catch malicious activity, independently concludes that "spawns an interactive pty" is not by itself a reliable signal of anything in particular (malicious or benign) — it needs context (which process, with what parent, doing what) to be meaningful.
  • The recommended fix for false positives is allowlisting by known tool identity, not by relaxing the pty-interactivity check — i.e., the right axis to add is "who/what is doing this," not "make the interactivity test looser."

Pros / strengths

  • Comes from the security-detection domain, which has spent years dealing with exactly this ambiguity at scale (distinguishing legitimate automation from malicious activity using the same low-level signals) — directly transferable experience for this subject's human-vs-automation problem.

Cons / limitations / caveats

  • Framed around detecting malicious reverse shells, not around a shell startup hook's design; the finding (allowlist by identity, not by loosening the raw signal) transfers, but the specific rule logic itself does not.

Relevance to tai

Validates the proposal's approach of combining $-/$TMUX/$SSH_TTY with an explicit allowlist/denylist of known parent-process names or environment markers (e.g. skip auto-attach when the parent is claude, code, a CI runner, etc.) rather than trying to find one perfect universal signal — exactly the security industry's own conclusion on the identical underlying ambiguity.

Changelog

Date Change
2026-10-09 Initial dossier created.