Тихий взрыв в мире локальных LLM
Представьте: вы запускаете локальную языковую модель, думаете о приватности и безопасности. А в это время кто-то может выполнить произвольный код на вашей машине через бэкдор в серверной части llama.cpp. Звучит как плохой сон? Это реальность. В проекте обнаружили критическую уязвимость типа Out-of-bounds Write, которая ведёт к Remote Code Execution.
Хуже всего то, что многие пользователи даже не знают о проблеме. Уязвимость не получила официального CVE-номера (пока), но это не делает её менее опасной. Если вы используете llama-server или похожие инструменты на базе llama.cpp — читайте дальше. Сейчас расскажу, как проверить свою установку и что делать дальше.
⚠️ Важно: Уязвимость затрагивает версии llama.cpp с коммитами между b2715 и b3230. Если вы собирали из исходников в этот период — вы в зоне риска.
Что именно сломалось и почему это опасно
Всё началось с, казалось бы, невинного параметра n_discard в функции llama_kv_cache_seq_rm. Разработчики добавили его для оптимизации — чтобы удалять устаревшие данные из кэша ключей-значений. Логично? Да. Безопасно? Нет.
Проблема в том, что функция не проверяет границы массива при работе с этим параметром. Атакующий может передать специально сформированное значение n_discard, которое выйдет за пределы выделенной памяти. Это классический Out-of-bounds Write — одна из самых опасных уязвимостей в C/C++.
Почему Out-of-bounds Write так опасен?
Потому что она позволяет перезаписывать соседние участки памяти. Можно подменить указатели на функции, изменить переменные или даже выполнить произвольный код. В случае llama.cpp это даёт полный контроль над сервером, если он доступен из сети.
Как проверить свою версию за 30 секунд
Не нужно гадать. Вот конкретные шаги для проверки.
1 Проверка хэша коммита
Если вы собирали llama.cpp из исходников, перейдите в директорию с репозиторием и выполните:
git log --oneline -1
Вы увидите что-то вроде b2715 fix something. Первые 5 символов — это хэш коммита. Если он находится между b2715 и b3230 — у вас уязвимая версия.
2 Проверка бинарных сборок
Если вы использовали готовые бинарники (например, из релизов GitHub), проверьте версию:
./llama-server --version
Или просто запустите сервер — версия обычно отображается при старте. Уязвимы все версии, собранные после коммита b2715 и до фикса в b3230.
3 Проверка системных пакетов
В Debian и других дистрибутивах llama.cpp может быть упакован как системный пакет. Проверьте:
apt list --installed | grep llama.cpp
Если версия пакета основана на уязвимых коммитах — нужно обновить. Но здесь есть нюанс: многие дистрибутивы запаздывают с обновлениями. Лучше проверять хэш коммита, а не номер версии.
Что делать, если вы в зоне риска
Паниковать не нужно. Действуйте по плану.
Немедленные действия
- Остановите все запущенные экземпляры llama-server. Если сервер работает как демон — kill процесс.
- Обновите репозиторий до последней версии:
git pull origin master - Пересоберите проект. Не просто сделайте make — полностью очистите и пересоберите:
make clean && make - Проверьте, что коммит новее
b3230.
💡 Совет: Если вы используете llama.cpp в продакшене (да, некоторые так делают), рассмотрите возможность запуска в изолированном окружении. Например, в LXC-контейнере Proxmox или в Docker с ограниченными правами.
Если обновление невозможно
Бывает такое — проект завязан на конкретную версию, обновиться нельзя. Тогда:
- Примените патч вручную. Возьмите изменения из коммита
b3230и наложите на свою версию. - Ограничьте сетевой доступ. Запускайте сервер только на localhost (127.0.0.1), не открывайте порты наружу.
- Используйте фаервол. Заблокируйте входящие соединения на порт llama-server.
Как работает атака (технические детали)
Чтобы понять масштаб проблемы, нужно заглянуть в код. В функции llama_kv_cache_seq_rm есть цикл, который использует параметр n_discard для удаления элементов из кэша. Но нет проверки, что n_discard не превышает размер массива.
Атакующий через API llama-server может передать специально сформированный запрос с большим значением n_discard. Это приводит к записи за пределами выделенной памяти. Дальше — классический сценарий: перезапись указателей, выполнение произвольного кода, полный контроль над системой.
| Компонент | Статус | Рекомендация |
|---|---|---|
| llama-server (standalone) | Критически уязвим | Обновить немедленно |
| llama.cpp как библиотека | Условно уязвим | Проверить использование llama_kv_cache_seq_rm |
| GUI-обёртки (AnythingLLM, CLINE) | Зависит от реализации | Обновить базовую библиотеку llama.cpp |
Частые ошибки и как их избежать
Ошибка 1: «У меня старая версия, значит, я в безопасности»
Не факт. Уязвимость появилась в коммите b2715. Если у вас версия старше — вы безопасны. Но если вы обновились после этой даты и до b3230 — вы в зоне риска. Многие автоматически делают git pull, не проверяя изменения.
Ошибка 2: «Я не использую llama-server, только CLI»
Тогда вы, скорее всего, в безопасности. Уязвимость затрагивает именно серверную часть, которая принимает сетевые соединения. Но если вы используете llama.cpp как библиотеку в своём проекте и вызываете llama_kv_cache_seq_rm — проверьте свои вызовы этой функции.
Ошибка 3: «Я скачал бинарник с GitHub Releases»
Проверьте дату сборки. GitHub Actions автоматически собирает бинарники при каждом коммите. Если вы скачали бинарник между коммитами b2715 и b3230 — он уязвим.
Долгосрочные меры безопасности
Однажды обновившись, нельзя расслабляться. Вот что стоит сделать на постоянной основе:
- Подпишитесь на security advisory в репозитории llama.cpp на GitHub. Так вы узнаете о новых уязвимостях первыми.
- Используйте системы мониторинга для LLM-инфраструктуры. Инструменты вроде Vigil помогают отслеживать аномалии.
- Запускайте серверы в изоляции. Docker-контейнеры, виртуальные машины, отдельные пользователи — всё, что ограничивает ущерб при взломе.
- Регулярно обновляйтесь. Не застревайте на одной версии из-за «работает — не трогай».
Что делать, если вы разрабатываете на основе llama.cpp
Если вы создаёте собственные инструменты на базе llama.cpp (например, RPC-сервер или GUI-обёртку), вот ваш чек-лист:
- Проверьте, не вызываете ли вы
llama_kv_cache_seq_rmс пользовательскими данными - Добавьте валидацию всех входных параметров перед передачей в библиотеку
- Обновите зависимость llama.cpp до последней версии
- Рассмотрите использование санитайзеров (AddressSanitizer) при разработке
⚠️ Предупреждение: Не думайте, что «это же локальная модель, кто будет атаковать?». Локальные LLM становятся популярными, а уязвимые экземпляры сканируют боты. Ваш домашний сервер может быть целью.
Почему такие ошибки вообще происходят
llama.cpp — проект с открытым исходным кодом, который развивается бешеными темпами. Новые функции, оптимизации, поддержка разных аппаратных платформ. В этой гонке безопасность иногда отходит на второй план.
Параметр n_discard добавили для улучшения производительности. Разработчик думал о скорости, а не о безопасности. Классическая история. В C/C++ нет встроенной защиты от выхода за границы массивов — вся ответственность на программисте.
Что с этим делать? Во-первых, внедрять code review. Во-вторых, использовать инструменты статического анализа. В-третьих, не забывать про fuzzing-тесты. Кстати, о code review — почитайте мой материал про автоматический анализ кода с помощью LLM. Ирония в том, что языковые модели могут помочь находить уязвимости в коде, который их же запускает.
Что дальше?
Уязвимость уже исправлена, но это не последняя проблема в llama.cpp. Проект растёт, добавляются новые функции, сложность увеличивается. Будьте готовы к тому, что подобные инциденты будут повторяться.
Мой совет: относитесь к llama.cpp как к потенциально опасному ПО. Запускайте его в изоляции, ограничивайте сетевой доступ, регулярно обновляйтесь. И не забывайте проверять security advisory.
А если вы только начинаете работать с локальными LLM и думаете, какую конфигурацию собрать — почитайте мой гайд про оптимизацию llama.cpp под разное железо. Там есть и про безопасность тоже.
P.S. Если вы обнаружили уязвимую версию в продакшене — не паникуйте. Обновитесь, перезапустите сервис и проверьте логи на предмет подозрительной активности. И помните: безопасность локальных LLM — это не оксюморон. Это необходимость.