Читать 6 мин

Владение сессией агента tmux: подтверждения и аудит

Владение сессией агента tmux может скрыть, кто подтвердил действие и какой процесс оставил аудиторский след. Узнайте, как связаны идентичность процесса, отключённые сессии, screen и свидетельства инцидента.

Владение сессией агента tmux: подтверждения и аудит

Мультиплексоры терминала решают реальную операционную проблему: они сохраняют работу после разрыва SSH-соединения, перехода ноутбука в режим сна или случайного закрытия окна терминала. Но та же постоянная доступность может скрыть, кому принадлежит AI-агент, действует ли ещё его разрешение и какой именно процесс отправил авторизованный запрос.

Ошибка возникает, когда окно tmux принимают за защищённую сессию. Это не так. tmux управляет процессами терминальных сессий. Его сервер может пережить клиент терминала, а панели могут пережить человека, который их создал. GNU screen обладает тем же базовым свойством. Если в модели разрешений, заметках об инциденте или процессе аудита вы говорите «сессия tmux», подразумевая одного исполнителя и один запуск агента, расследование уже стало сложнее, чем необходимо.

Особенно важно это в случаях, когда агент может обращаться к API или SSH-хостам через шлюз под управлением человека. Пользователь может запустить агента в панели, отключиться, передать имя сессии коллеге, подключиться к ней с другой машины, а позже запустить в той же панели второго агента. Для оператора все события выглядят непрерывными. В таблице процессов это отдельные факты.

Сессия tmux не равна запуску агента

Сессия tmux - это именованный набор окон и панелей, который хранится в долгоживущем сервере tmux. Запуск агента - это один процесс и созданные им дочерние процессы, ограниченные временем запуска и завершения. Это разные объекты. Если их объединить, область разрешений окажется слишком широкой или её будет невозможно объяснить позже.

Когда вы выполняете tmux new-session -s build, tmux запускает сервер или подключается к существующему. Сервер создаёт псевдотерминал для первой панели и запускает оболочку. Когда оболочка запускает агента, агент становится её потомком. Отключение разрывает соединение клиента с tmux. Обычно оно не завершает сервер, оболочку или агента.

Обычная последовательность выглядит безобидно:

  1. Maya запускает tmux new -s release и запускает агента в панели 0.
  2. Maya отключается перед встречей, а агент продолжает работу.
  3. Позже её коллега подключается к release, читает вывод панели и запускает следующую команду.
  4. Вечером Maya повторно использует панель 0 для другого процесса агента.

Имя сессии осталось release. Объекты, важные для безопасности, изменились. Было как минимум два процесса агентов, два взаимодействия с людьми и, возможно, разные события авторизации. История терминала не может превратить это в одну непрерывную идентичность.

GNU screen ведёт себя похожим образом. Отключённый сервер screen владеет окнами терминала и дочерними процессами. Команды отличаются, но вывод с точки зрения безопасности тот же: состояние подключения показывает доступ к мультиплексору терминала, а не владение каждым процессом внутри него.

В руководстве tmux описана модель клиент-сервер, а также сказано, что сервер управляет сессиями, окнами и панелями. Это не просто деталь реализации. Из формулировки понятно, где сохраняется непрерывность: на сервере, а не в приложении терминала, которое видит пользователь. Стройте авторизацию вокруг процесса, запрашивающего действие, а не вокруг контейнера-мультиплексора, в котором этот процесс оказался.

Родословная процессов отвечает на вопросы, на которые имена панелей не отвечают

Дерево процессов показывает, как запустился агент и какие оболочка и сервер tmux были его родителями. Заголовок панели показывает только метку, которую могли изменить, скопировать или забыть обновить.

В macOS или Linux начните расследование с узкого представления процессов, пока процесс ещё работает:

ps -axo pid,ppid,lstart,tty,stat,command | grep -E '[t]mux|[s]creen|[a]gent'

Важнее форма вывода, чем точные названия команд:

 8421     1 Tue Mar 12 09:14:03 2025 ??       Ss   tmux new-session -s release
 8430  8421 Tue Mar 12 09:14:04 2025 ttys002  S    -zsh
 9917  8430 Tue Mar 12 10:02:51 2025 ttys002  S+   agent-tool run deploy check

PID 9917 - предполагаемый процесс агента. PID 8430 - оболочка, которая его запустила. PID 8421 - сервер tmux. Значение tty помогает связать процесс с панелью, пока процесс существует, но не используйте его как постоянный идентификатор. Псевдотерминалы могут исчезнуть после завершения процесса и выглядеть иначе после создания нового терминала.

В macOS pstree не установлен по умолчанию. Эта команда показывает удобную связь родителей и потомков без установки дополнительного ПО:

ps -axo pid,ppid,user,lstart,command | sort -n

Для конкретного PID несколько раз проверяйте его родителя, пока не дойдёте до сервера tmux или службы запуска:

ps -p 9917 -o pid=,ppid=,user=,lstart=,tty=,command=
ps -p 8430 -o pid=,ppid=,user=,lstart=,tty=,command=

Запишите значения до завершения процессов. Оператор, который сначала выполнит tmux kill-session, может стереть самые полезные живые свидетельства: командные строки, связи родителей и потомков и время запуска. Завершение сессии всё ещё может быть правильной мерой локализации, но, когда позволяет ситуация, сначала сделайте короткий снимок.

У родословной процессов есть ограничения. Процесс может стать демоном, создать форк или намеренно сменить родителя. Агент также может поручить работу внешнему помощнику, и дерево потомков закончится на этом помощнике. Считайте родословную свидетельством контекста запуска, а не доказательством намерений человека. Нужны и записи действий, где указаны запрашивающий процесс и разрешение, позволившее выполнить действие.

Разрешение должно следовать за процессом агента, а не за подключённым терминалом

Авторизация на уровне сессии должна относиться к одному запуску процесса агента и заканчиваться после завершения этого процесса. Подключение, отключение, фокус панели и перезапуск эмулятора терминала не должны выдавать, продлевать или незаметно передавать это разрешение.

Авторизация на уровне сессии в Sallyport следует этому принципу: первый вызов нового процесса агента запрашивает подтверждение, показывает издателя кода процесса и сохраняет разрешение только для этого запуска. Разрешение не становится свойством имени сессии tmux или приглашения оболочки.

Такое ограничение устраняет несколько запутанных сценариев. Если пользователь отключился, а позже снова подключился, пока тот же процесс агента продолжает работу, процесс не изменился. Его авторизация сессии может оставаться действительной с учётом шлюза хранилища и учётных данных, для которых требуется подтверждение каждого вызова. Если агент завершился, оболочка в панели запустила нового агента, а панель выглядит так же, новый процесс должен получить новое решение об авторизации.

Не превращайте подключение к tmux в событие авторизации. Идея кажется привлекательной, потому что действие человека, tmux attach, выглядит полезным сигналом. Для использования учётных данных это неправильный сигнал. Подключение может произойти уже после запуска агента, выполняться другим человеком под той же локальной учётной записью или быть нужно лишь для просмотра вывода. Важнее всего то, что процесс может продолжать работу, даже когда к tmux не подключён ни один клиент.

Встречается и противоположная ошибка: каждую команду, введённую в подключённой панели, считают выполненной под контролем человека. Пользователь может подключиться, отойти и оставить агента работать. Видимый терминал не подтверждает присутствие.

Для чувствительных учётных данных подтверждение каждого использования решает другую задачу. Оно не устанавливает владельца процесса, а требует решения человека в момент запроса конкретного действия с учётными данными. Разделяйте эти идеи:

  • Шлюз хранилища решает, может ли действие вообще выполняться, пока секреты защищены.
  • Авторизация процесса решает, может ли этот запуск агента выполнять вызовы.
  • Подтверждение для конкретных учётных данных решает, нужно ли отдельное решение человека для определённого использования.

Эти средства отвечают на разные вопросы. Команда, которая использует одно широкое разрешение для долгоживущей терминальной сессии, выбрала удобство вместо границы, которую можно обосновать.

Повторно используемая панель может переносить путаницу с разрешениями между запусками

Обычно всё начинается с постоянной сессии work, которая превратилась в общий ящик для незавершённых команд. Кто-то запускает агента, отключается, возвращается через несколько часов, останавливает его, а затем запускает другого агента в той же оболочке. В панели по-прежнему видны прежняя переписка, переменные окружения и приглашение. Люди видят непрерывность там, где операционная система её не видит.

Представьте инцидент, в котором API получает разрушительный запрос в 16:43. В записи активности указан процесс агента. Команда открывает tmux и видит панель prod-fix с выводом, начинающимся в 09:00. Она предполагает, что инженер, создавший prod-fix, подтвердил запрос. Этот вывод может быть неверным по нескольким причинам:

  • Исходный агент мог завершиться в 10:15, а другой процесс мог запуститься в 16:40.
  • Второй инженер мог подключиться и выполнить новую команду запуска.
  • Заголовок панели мог сохраниться от предыдущей задачи.
  • Файл запуска оболочки мог экспортировать учётные данные или целевое окружение, которые уже не соответствуют текущей работе.
  • Процесс мог запуститься вне tmux и передавать вывод в панель другим способом.

Правильный вопрос звучит точнее: какой исполняемый процесс запросил действие в 16:43, кто подтвердил этот процесс и какого издателя кода показал интерфейс авторизации? Затем выясните, как этот процесс оказался в дереве процессов машины.

Не нужно делать обратный вывод и запрещать tmux. Новая сессия с узким назначением может упростить работу с инцидентом: она даёт операторам видимое рабочее пространство и сохраняет вывод при нестабильном соединении. Риск создаёт повторное использование универсальной сессии как контейнера для не связанных друг с другом запусков агентов.

Используйте имена, в которых указаны назначение и короткий идентификатор запуска, например deploy-4812 вместо work или main. Имя помогает человеку, но не используется для авторизации. После завершения запуска закрывайте сессию.

Для отключённой работы нужны владелец и решение о сроке завершения

Авторизуйте процесс, а не tmux
Sallyport авторизует каждый новый процесс агента, а не панель tmux, из которой его запустили.

Отключённая сессия tmux или screen может работать безопасно только тогда, когда кто-то явно согласился с тем, что она продолжит работу без подключённого терминала. Фраза «я думал, что всё остановилось» не заменяет модель владения.

Перед отключением агента, который может выполнять авторизованные действия, запишите в задаче, заметке об инциденте или передаче работы четыре факта: PID процесса агента, имя сессии tmux, заявленную задачу и человека, ответственного за остановку. Добавьте время, когда нужно проверить, следует ли продолжать работу. Это простая мера, которая предотвращает больше проблем, чем сложные схемы именования панелей.

Полезный шаблон запуска создаёт для работы новое пространство имён сокета, а не добавляет ещё одно окно в постоянный личный сервер:

tmux -L agent-4812 new-session -d -s agent-4812 \\\n  'exec agent-tool run "verify deployment 4812"'

tmux -L agent-4812 display-message -p \\\n  '#{session_name} #{session_created} #{pane_pid} #{pane_tty}'

Первая команда запускает отключённую сессию. exec важен, потому что заменяет процесс оболочки командой агента и делает PID панели более прямой отправной точкой для расследования. Без exec панель сначала принадлежит оболочке, которая позже создаёт агента как дочерний процесс. Это тоже можно расследовать, но появляется ещё один уровень.

Вторая команда выводит метаданные примерно в таком виде:

agent-4812 1731000000 9917 /dev/ttys002

Сохраните этот вывод там, где отслеживается задача. Позже процесс может создать дочерние процессы или завершиться, поэтому это не полная аудиторская запись. Но она даёт расследованию исходную точку для сопоставления данных процессов с журналами действий.

После завершения задачи явно завершите именованный сокет:

tmux -L agent-4812 kill-session -t agent-4812

Затем убедитесь, что ожидаемый PID агента завершился. Не считайте, что kill-session остановила всех потомков. Программы, создающие собственные сессии или фоновые помощники, могут пережить исходный псевдотерминал. Снова проверьте список процессов и воспользуйтесь шлюзом действий, чтобы отозвать активный запуск агента, если его записи показывают, что авторизация всё ещё действует.

У screen та же ловушка идентичности, но меньше подсказок

GNU screen создаёт отключённую сессию, к которой можно подключиться позже, а знакомые числовые идентификаторы могут казаться точнее, чем они есть. Они обозначают экземпляр сервера screen, а не конкретный процесс агента или подтверждение человека.

В руководстве GNU screen описаны отключённые сессии и команды вроде screen -ls и screen -r. Эти команды показывают, доступен ли сервер screen для подключения. Они не отвечают на вопрос, тот ли процесс в окне выполнял работу раньше и является ли текущий оператор человеком, который принял прежнее решение об авторизации.

Если screen участвует в инциденте, начните с таких проверок:

screen -ls
ps -axo pid,ppid,lstart,tty,stat,command | grep -E '[s]creen|[a]gent'

Результат вроде 12345.build (Detached) указывает на сессию screen, которую нужно изучить. Перед подключением сопоставьте её со временем запуска процессов и терминалами. Подключение может изменить то, что видит пользователь, запустить хуки оболочки или побудить интерактивную программу продолжить работу. В чувствительном инциденте сначала сохраните свидетельства, а необходимость взаимодействия пусть определит назначенный специалист.

Режим screen для нескольких пользователей требует особой осторожности. Он может предоставить другим локальным пользователям доступ к общей терминальной сессии. На контролируемой машине это может быть уместно, но ослабляет любое поверхностное утверждение, что «человек, который подключился», владеет процессами. Авторизация по-прежнему должна указывать запрашивающий процесс агента и требовать решения локального человека, управляющего шлюзом учётных данных.

Для аудиторских записей нужна точка объединения вне tmux

Связывайте запуски с действиями учётных данных
Один зашифрованный журнал с цепочкой хешей объединяет записи о запусках и вызовах для расследования.

Обоснованное расследование объединяет три вида записей: запись процесса операционной системы, запись авторизации и запись отдельного действия. Вывод tmux или screen может дополнить эти свидетельства, но не заменить их.

Для каждого проверяемого действия с учётными данными установите следующую последовательность:

  1. Найдите в записи активности время, назначение, метод и результат действия.
  2. Определите запуск агента, запросивший действие, и связанное с ним решение об авторизации.
  3. Сопоставьте сведения о процессе и время запуска с живым или сохранённым деревом процессов.
  4. Используйте метаданные сессии tmux или screen только для восстановления рабочего пространства оператора и передачи работы.
  5. Убедитесь, что аудиторская запись не менялась после сохранения.

Различие между журналом действий и прокруткой терминала принципиально. В прокрутке может отсутствовать часть вывода, старые записи могут быть вытеснены, там может оказаться вставленный текст другого процесса, а пользователь с доступом к сессии может изменить содержимое. Журнал действий должен описывать выполненную операцию и её результат. Если он защищён от незаметного изменения, расследование может проверить целостность набора записей, не полагаясь на терминал, который их показывал.

Sallyport сохраняет запуски агентов и отдельные вызовы в зашифрованном журнале аудита с цепочкой хешей, а sp audit verify позволяет проверить эту цепочку офлайн без ключа хранилища. Такая проверка доказывает целостность записанной последовательности, но не то, что заголовок tmux правильно указывает человека, вводившего команду. В отчётах об инцидентах разделяйте эти утверждения.

Полезная заметка об инциденте не должна содержать фразу вроде «это сделала сессия tmux release». Напишите: «В 16:43 запуск агента [идентификатор] запросил [действие]. Запрос поступил от процесса [идентификатор], запущенного в [время]. На момент сохранения процесса был потомком [оболочка или служба], связанного с сервером tmux [PID]. [Человек] подтвердил запуск после проверки показанного издателя процесса». Указывайте только факты, которые можно подтвердить.

Такая формулировка также показывает пробелы. Если до локализации не удалось сохранить цепочку родителей, так и напишите. Если система не хранит нужную идентичность процесса, не подменяйте этот факт именем панели.

Идентичность подписи кода и локальной учётной записи решают разные задачи

Проверяйте записи после локализации инцидента
Проверяйте зашифрованную цепочку аудита офлайн с помощью sp audit verify, не открывая хранилище.

Локальная учётная запись macOS показывает пользователя операционной системы. Издатель подписи кода показывает, кто подписал исполняемый файл. Сессия tmux показывает терминальный сервер. Ни один из этих идентификаторов не означает того же, что остальные, и каждый помогает выявить свою проблему.

Идентичность локальной учётной записи помогает определить, какая учётная запись владела процессом. Но она не говорит, поступил ли бинарный файл от ожидаемого издателя или использовал ли другой человек разблокированную учётную запись. Издатель подписи кода помогает распознать исполняемый файл, запрашивающий доступ. Но он не говорит, был ли процесс запущен в правильной панели tmux или соответствовала ли задача цели.

Поэтому карточка подтверждения, начинающаяся с издателя подписи кода, полезна, когда новый процесс агента запрашивает действие. Она даёт человеку стабильный сигнал, который сохраняется после переименования панелей, копирования конфигурации tmux и перезапуска эмулятора терминала. Она также показывает неожиданные неподписанные или иначе подписанные исполняемые файлы в нужный момент.

Не сводите это к слепому правилу «тот же издатель значит безопасно». Надёжный издатель может выпустить ошибочную версию, локальная обёртка может вызвать одобренный бинарный файл в небезопасном контексте, а подписанный процесс может получить опасные инструкции. Идентичность процесса сужает объект авторизации. Подтверждение отдельных вызовов для выбранных учётных данных и полный журнал действий закрывают риски, которые сама идентичность не устраняет.

В расследовании на macOS сведения о подписи бинарного файла можно проверить с помощью codesign:

codesign -dv --verbose=4 "$(command -v agent-tool)" 2>&1 | \\\n  grep -E 'Identifier=|TeamIdentifier=|Authority='

Обычно вывод содержит строки Identifier=, TeamIdentifier= и одну или несколько строк Authority=. Сохраните его, если нужно объяснить, почему интерфейс авторизации распознал процесс. Не заменяйте свидетельство о подписи путём вроде /usr/local/bin/agent-tool. Пути легко скрыть другим файлом, заменить или направить через символическую ссылку.

Перестаньте использовать постоянные общие сессии для привилегированной работы агентов

Постоянный сервер tmux с именем dev, main или shared - плохое место для запуска агентов, которым доступны рабочие учётные данные. Он упрощает текущую работу, но смешивает людей, задачи, историю оболочки, состояние окружения и сроки жизни процессов, пока уже никто не может сказать, где закончился один запуск.

Отделяйте личную интерактивную работу с мультиплексором от выполнения агентов. Давайте каждому запуску агента собственную сессию или сокет. Запускайте его записанной командой, сохраняйте PID и время запуска, назначайте владельца до отключения. Если другому инженеру нужно продолжить задачу, он должен запустить новый процесс агента и получить новое решение об авторизации, а не по привычке унаследовать старую панель.

Команды часто сопротивляются этому, потому что повторное использование сессии кажется эффективным. Оно эффективно до тех пор, пока агент не отправит запрос после завершения исходной задачи и команда реагирования не потратит час на чтение прокрутки. Новые границы процессов занимают секунды. Восстановление размытой границы требует гораздо больше времени и часто заканчивается предположением вместо ответа.

Первое операционное изменение простое: запретите безымянные долгоживущие сессии tmux и screen для агентов с авторизованным доступом. Создавайте короткоживущую сессию для каждого запуска, записывайте идентичность запуска и закрывайте её после завершения. Такая политика даёт системам авторизации и расследованиям настоящую границу, с которой можно работать.

Вопросы и ответы

Продолжит ли AI-агент работать после закрытия терминала в tmux?

Сессия tmux - это серверный процесс, который владеет псевдотерминалами, окнами и панелями. Она может сохранить оболочку или процесс агента после отключения эмулятора терминала, поэтому видимое окно терминала не показывает надёжно, кому принадлежит выполняемая работа.

Можно ли определить владельца агента по имени панели tmux?

Нет. Панель tmux показывает, где у процесса есть терминал, но не то, какой человек подтвердил его полномочия. Для этого расследованию нужны PID агента, родительский процесс, время запуска, запись о действии с учётными данными и запись об авторизации.

Безопасны ли отключённые сессии tmux для автономных агентов программирования?

Отключённая сессия сама по себе не опасна, но для неё нужны явный владелец, назначение и правило завершения. Считайте безымянную сессию, пережившую своего оператора, работой, которую нужно проверить, особенно если она всё ещё может выполнять авторизованные вызовы.

Должна ли авторизация сессии сохраняться после отключения и повторного подключения к tmux?

Практический охват авторизации должен ограничиваться одним запуском процесса агента и заканчиваться после его завершения. Подключение к tmux и отключение от него не должны продлевать авторизацию, а новый агент, запущенный в старой панели, должен получить отдельное разрешение.

Почему долгоживущие сессии screen опасны с точки зрения безопасности?

Да, это может быть проблемой, поскольку сервер и дочерние процессы способны оставаться активными, пока ни один пользователь не подключён к терминалу. Застарелый процесс легко пропустить, если люди повторно используют имя сессии или считают, что закрытие ноутбука завершило запуск.

Как расследовать действие, выполненное из tmux?

Начните с ps, чтобы записать PID, PPID, время запуска, терминал и командную строку. Затем сохраните метаданные панели tmux и сопоставьте их с журналами действий по времени, идентификатору процесса и идентификатору запуска агента, а не по одному имени панели.

То же ли самое tmux, что и мультиплексирование SSH-соединений?

Нет. Мультиплексирование SSH повторно использует SSH-соединение, а tmux мультиплексирует терминалы и дочерние процессы. Они создают разные виды свидетельств и разные сценарии сбоев, хотя оба механизма могут оторвать последующее действие от человека, который его запустил.

Как правильно остановить подозрительную сессию tmux?

Команда tmux kill-session -t name просит сервер завершить сессию и её панели, но сначала проверьте, что именно выполняется. Процесс мог выйти из группы процессов панели, поэтому после этого проверьте дерево процессов и не объявляйте инцидент закрытым слишком рано.

Можно ли считать журналы tmux аудиторским следом?

Они полезны для непрерывности работы, журналов и передачи задач, но не доказывают, кто запустил процесс или подтвердил его. Сохраняйте их как дополнительные свидетельства и сопоставляйте с данными процессов операционной системы и записями аудита шлюза действий.

Как безопасно запускать несколько агентов в tmux?

Используйте отдельный сокет или сессию для каждого запуска агента, дайте ей понятное для расследования имя и сразу запишите PID запуска. Не превращайте универсальную сессию разработчика в место хранения агентов, у которых есть доступ к рабочим системам.

Sallyport

Sallyport выполняет API-вызовы и SSH-команды за вашего ИИ-агента. Ключи остаются в локальном хранилище на вашем Mac; вы подтверждаете каждый запуск, и каждое действие попадает в запечатанный журнал.

© 2026 Sallyport · Открытый код по лицензии Apache-2.0 · Oleg Sotnikov