TLDR: скопрометированный не-рут может стать рутом, если ему поможет скомпрометированный рут из другого контейнера.
Возможно это баян и ещё более возможно всем пофиг, но при наличии двух контейнеров, могущих общаться через UNIX-сокет (который через файлы типа «socket») они могут «делиться» друг с другом рут-правами (и другими). Общение через UNIX-сокет вполне может быть заложено штатно (например, nginx + php-fpm в разных контейнерах, связанные через локальный сокет), либо легко делается самостоятельно, если у двух контейнеров есть общий volume (в нём один может создать сокет а второй - подключиться к нему). На самом деле, в случае с volume всё может оказаться проще - один создаст suid-root бинарник а второй запустит, но кто-то может поставить туда nosuid/noexec и думать что этого достаточно - но нет.
Как поделиться правами: есть такая штука как SCM_RIGHTS, с помощью неё можно слать через сокет файловые дескрипторы. Допустим у нас есть контейнер A, в котором запущен с ограниченными правами злонамеренный, скомпрометированный либо просто принимающий внешние команды в роли демки (с расчётом на «он никуда не вылезет») софт. И есть контейнер B, в котором злонамеренный софт как-то смог получить рут-права. Непривилегированный процесс в контейнере A делает open(«/»), шлёт через сокет полученный файловый дескриптор привилегированному процессу в контейнере B, после чего привилегированный процесс из контейнера B через функции openat() и подобные получает полный рут-доступ к файловой системе контейнера A.
У меня было подозрение, что, оказавшись в не своём контейнере, файловый дескриптор чужой файловой системы позволит ещё как-то поразвлекаться, но сходу не прокатило. Например, могло оказаться, что к нему в новом контейнере бы применилось пространство монтирования нового контейнера и перестала бы работать контейнериация файловой системы старого, но походу нет.