Конфигурация на основе белых списков возможностей
- title
- Конфигурация на основе белых списков возможностей
- type
- concept
- summary
- Паттерн встраиваемых скриптов: язык стартует с нуля возможностей, а хост регистрирует каждую явно, вместо вырезания опасного из полного языка
- tags
- config-languages, embedded-scripting, capability-security
- created
- 2026-05-11
- updated
- 2026-05-11
- lang
- ru
- translation_of
- whitelist-capability-config
- source_updated
- 2026-05-11
- translated
- 2026-09-01
- translator
- lllm/antigravity/gemini-3.7-flash-medium
Паттерн для встраиваемых конфигураций или скриптов, где хост-приложение явно объявляет, возможность за возможностью, к чему именно автор конфига может обращаться. Это противоположно подходу с чёрными списками, типичному для встроенного Lua или Python: загрузить язык целиком, затем попытаться вырезать os, io, require и надеяться, что ничто другое не приведёт к эскалации привилегий.
В заметке ryelang-whitelist-config это сформулировано предельно чётко: "чёрные списки защищают от известных угроз, но всегда остаются неизвестные, а защититься от того, о чём ты даже не подозреваешь, невозможно". Аргумент о неизвестных неизвестных - ровно тот же, что лежит в основе сетевых политик с запретом по умолчанию (default-deny) и операционных систем на базе возможностей (capabilities).
Две проблемы, на которые реагирует паттерн
Сползание снизу вверх (bottom-up creep). Конфиги, начинавшиеся как простые пары ключ-значение в стиле INI, со временем переизобретают целый язык. YAML оброс шаблонизаторами (Helm, Ansible), в Nginx появился if, в Terraform придумали HCL с костылями вроде блоков dynamic из-за нехватки if. Скрытый язык получается неформальным, часто противоречивым, и обрастает цепочкой из парсера, шаблонизатора и вычислителя, которую никто изначально не проектировал как единое целое. Десятое правило Гринспена в применении к конфигурациям.
Встраивание сверху вниз (top-down embedding). "Просто встроим Lua". Теперь в конфиге можно делать абсолютно всё, включая os.execute и io.open. В качестве защиты опасные привязки пытаются вырезать перед вычислением ненадежного кода. Для этого нужно досконально знать всю поверхность потенциальных угроз, чего на практике не бывает.
Альтернатива с белыми списками - взять язык, где таких конструкций изначально нет, и предоставить в хосте API для поштучной регистрации каждой возможности.
Два способа реализации
Жёстко ограниченный диалект. Канонический пример - Starlark: синтаксис Python, без рекурсии, без while, без ввода-вывода. Набор ограничений зафиксирован на уровне самого языка. Модули регулируются списками импорта. Можно отказаться от регистрации модуля целиком, но нельзя отключить только одну встроенную функцию внутри него.
Язык без зарезервированных конструкций. rye-lang служит примером, на котором построена упомянутая статья. Базовый вычислитель умеет только разбирать синтаксис и связывать имена - и больше ничего. if, fn, +, * - это обычные функции стандартной библиотеки, которые регистрируются на усмотрение разработчика. Можно выдать _+ без _* или if без loop. Гранулярность - на уровне отдельных слов.
Компромисс здесь между зрелостью и выразительностью: Starlark проверен в продакшене на масштабах Bazel; подход Rye - это скорее исследовательский поиск с меньшим радиусом поражения на каждую выданную возможность.
Что всё равно потребуется поверх
Белые списки возможностей контролируют, какие слова существуют. Они не контролируют, какой объём работы выполняет интерпретатор. Оба языка также предоставляют лимиты выполнения - глубину стека вызовов, общее число операций, астрономическое время - чтобы зависший или бесконечный код приводил к ошибке, а не к отказу системы.
Кроме того, это не ограничивает побочные эффекты на стороне хоста для тех встроенных функций, которые вы всё-таки зарегистрировали. Предостережение в финале ryelang-whitelist-config прямо говорит: "это контроль возможностей, а не песочница безопасности". Rye исполняется прямо в процессе хоста; если зарегистрировать read-file, конфиг сможет прочитать любой файл, доступный хосту. Для недоверенного ввода поверх нужен полноценный барьер изоляции - процессы, seccomp или отдельная виртуальная машина. Четырёхуровневая модель подробно описана в sandboxing-ai-agents.
Где это применяется
- Config-as-code в доверенной среде, когда нужно сохранить выразительную поверхность компактной (контекст статьи о Rye)
- Системы плагинов, где сторонние авторы получают строго фиксированный набор хост-примитивов и ничего сверх того
- Языки действий для AI-агентов, где каждая новая возможность добавляется осознанным решением (схоже с областями видимости возможностей в mcp-vs-skills)
- Игровые скрипты, где геймдизайнеры оперируют словарём, подготовленным программистами
См. также
- ryelang-whitelist-config - статья, раскладывающая паттерн по шести шагам
- rye-lang - пример реализации
- no-silver-bullet - случайная сложность конфигурационных языков как повторяющийся паттерн
- sandboxing-ai-agents - уровень поверх контроля возможностей, когда входные данные враждебны