Skip to content

Security: slavkiy/witgo

Security

SECURITY.md

Модель безопасности

Композиция компонентов

Component не получает доступ к Host, registry или пути соседних плагинов. Вызов другого компонента возможен только через WIT import, который приложение явно связало с совместимым зарегистрированным provider. Перед связыванием проверяются полный package/interface/version ID и structural signatures. WebAssembly-зависимости, использующие живые handles, компонуются до instantiation в один Store. Между независимыми Store и через Go callback handles не передаются и дают ErrCrossRuntimeHandle. Циклы графа, дубликаты точного ID и несовместимые resource identities отклоняются до запуска гостевого кода.

Кратко

witgo запускает WebAssembly Components через Wasmtime, но сам по себе не превращает untrusted plugin в “полностью безопасный объект”. Безопасность здесь слоистая:

  • Wasmtime изолирует guest WebAssembly;
  • Go host явно решает, какие imports дать plugin;
  • native Rust bridge остаётся доверенным кодом внутри процесса;
  • release-процесс должен контролировать целостность bridge и происхождение component-артефактов.

Что является доверенной частью

Доверенными считаются:

  • ваше Go-приложение;
  • ваши реализации host imports;
  • native Rust bridge;
  • embedded или явно указанный shared library bridge;
  • build и release pipeline, который эти артефакты публикует.

Если ошибка происходит в доверенном native-коде, она влияет на весь процесс.

Что считается изолируемой частью

Изолируется именно WebAssembly guest-код:

  • у него нет прямого доступа к памяти Go;
  • он не получает filesystem/network/environment автоматически;
  • он видит только те host imports, которые вы явно зарегистрировали.

Чего witgo не делает автоматически

Библиотека не:

  • включает WASI “по умолчанию”;
  • не даёт plugin сетевой доступ автоматически;
  • не выдаёт filesystem access автоматически;
  • не подписывает plugin;
  • не валидирует business-логическую корректность guest-кода;
  • не гарантирует, что timeout остановит зависший host callback.

Если plugin получает опасную возможность, это обычно происходит потому, что её явно дал host.

Contract validation как security boundary

ValidatePlugin полезен как предзапусковой фильтр, но важно не переоценивать его:

  • он проверяет интерфейс;
  • он не доказывает доброкачественность поведения;
  • он не делает plugin “доверенным”;
  • он не заменяет подпись артефакта, provenance и review.

Хорошая модель: validation - это gate на ABI, а не полная security-проверка.

Go overlays

Go overlay не расширяет возможности plugin и не меняет WIT ABI. Он обрабатывается доверенным generator до компиляции приложения и создаёт typed lower/lift code. Overlay-файлы следует review-ить как исходный Go-код: они выбирают публичные типы и codecs. Generator отклоняет pointers, channels, functions, interfaces, context.Context, unsafe.Pointer и неизвестные codecs.

Native bridge

Bridge загружается в тот же процесс, что и Go host.

Следствия:

  • нет отдельного sidecar-процесса;
  • нет IPC между Go и bridge;
  • нет отдельного sandbox для самого bridge;
  • memory bug или deadlock внутри bridge затрагивает весь процесс.

Именно поэтому bridge должен обновляться, проверяться и поставляться как доверенный release artifact.

Guest build toolchain

Guest generation и runtime loading имеют разные trust boundaries. wit-bindgen-go, go.bytecodealliance.org/cm, TinyGo, WIT package и wasm-tools, используемый TinyGo, являются build-time supply chain плагина. Они не получают полномочия host runtime, но их компрометация может изменить Canonical ABI glue или итоговый .wasm.

Для воспроизводимых builds:

  • закрепляйте версии wit-bindgen-go, TinyGo и WIT package;
  • устанавливайте wit-bindgen-go заранее и передавайте GuestBindgen, если build выполняется без сети;
  • проверяйте итоговый interface через wasm-tools component wit;
  • подписывайте именно готовый plugin.component.wasm;
  • на host всё равно выполняйте ValidatePlugin перед OpenPlugin.

ExportPlugin не выдаёт guest дополнительных capabilities. Доступны только те WIT imports, которые host предоставит при instantiation.

Рекомендации для production

1. Минимизируйте host surface

Регистрируйте только те imports, которые plugin действительно нужны.

Чем меньше host API, тем меньше поверхность атаки и неожиданного поведения.

2. Ограничивайте выполнение

Используйте RuntimeOptions:

  • Timeout;
  • Fuel или FuelPerCall;
  • MemoryLimitBytes;
  • InstanceLimit;
  • MaxResultBytes.

Это не “магическая защита от всего”, но это полезные защитные барьеры.

3. Проверяйте contract до instantiation

Сначала ValidatePlugin, потом OpenPlugin.

Это позволяет отсечь несовместимые или случайно подменённые plugins до реальных вызовов.

4. Контролируйте происхождение bridge

Если bridge задаётся через BridgePath или WITGO_COMPONENT_LIBRARY, используйте BridgeSHA256 или другой внешний контроль целостности.

5. Подписывайте и отслеживайте release artifacts

Для production-пайплайна важны:

  • checksums;
  • SBOM;
  • provenance/attestation;
  • platform signing, где это принято.

Reporting

Если вы нашли security-проблему в witgo, лучше не публиковать её как обычный issue с полным exploit-описанием.

Минимально полезный приватный отчёт должен содержать:

  • версию witgo;
  • платформу;
  • способ загрузки bridge;
  • минимальный reproducer;
  • наблюдаемое поведение;
  • ожидаемое безопасное поведение.

Если в репозитории позже появится выделенный канал security-reporting, этот документ стоит обновить и сослаться на него напрямую.

There aren't any published security advisories