Компонентная модель и безопасность

Разбираем компонентную модель и устройство песочницы Wasm.

Компонентная модель — это надстройка над Wasm, позволяющая модулям из разных языков соединяться через богатые типы, а не только числа.

Проблема «всё через числа»

Базовый Wasm знает только четыре числа. Чтобы один модуль использовал другой и обменивался строками, списками, записями, приходится вручную согласовывать протокол памяти — и для каждой пары языков он свой. Это мешает собирать приложение из готовых Wasm-кусков на разных языках. Компонентная модель решает это: вводит общий язык описания интерфейсов (WIT) с богатыми типами (строки, списки, варианты), и компоненты соединяются по этим описаниям автоматически.

Интерфейс на WIT

Интерфейс компонента описывают на языке WIT — он напоминает объявление типов. Помечаем language-text:

// интерфейс компонента на WIT
interface greeter {
  greet: func(name: string) -> string
  add: func(a: s32, b: s32) -> s32
}

Тут уже есть настоящий string и понятные типы. Инструменты генерируют по этому описанию «клей» так, что Rust-компонент и Go-компонент сцепляются, не зная деталей памяти друг друга. Это как интерфейсы между микросервисами, но внутри одного быстрого рантайма.

Почему Wasm безопасен

Безопасность Wasm стоит на нескольких столпах, заложенных в дизайн:

  • Песочница памяти — модуль видит только свою линейную память; выйти за неё нельзя (trap). Чужую память не прочитать.
  • Никаких неявных возможностей — модуль не может ничего, кроме того, что ему импортировали. Нет импорта файлов — нет доступа к файлам.
  • Защита потока управления — нельзя прыгнуть в произвольный адрес; вызовы только через проверенные функции и таблицы с проверкой сигнатур.
  • Валидация перед запуском — модуль проверяется на корректность типов до исполнения; некорректный не запустится.

Песочница наглядно

+-------------------------------------+
|            Хост (браузер/рантайм)    |
|   выдаёт ровно эти импорты -->       |
|   +-----------------------------+    |
|   |   Wasm-модуль (песочница)   |    |
|   |  - своя память (не выйти)   |    |
|   |  - только данные импорты    |    |
|   |  - проверенный поток вызовов|    |
|   +-----------------------------+    |
+-------------------------------------+

Как работает под капотом

Изоляция памяти обеспечивается тем, что вся «память» модуля — это один ArrayBuffer, и каждое обращение проверяется на границу (или, в продвинутых рантаймах, защищено аппаратными страницами памяти). Модуль физически не имеет указателя на что-либо вне своего буфера. Контроль возможностей — следствие того, что единственные «двери» наружу это импорты, а их задаёт хост. Поэтому даже вредоносный модуль не сможет прочитать чужие данные или вызвать то, что ему не дали.

Частые ошибки

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

Итоги

  • Компонентная модель соединяет Wasm-модули через богатые типы (WIT), а не числа.
  • Безопасность: песочница памяти, только явные импорты, защита потока, валидация.
  • Модуль не может выйти за свою память и вызвать то, что не импортировано.
  • Это делает Wasm безопасным форматом для чужого кода и плагинов.
Проверьте себя
1. Какую проблему решает компонентная модель?
AУскоряет числовые операции
BПозволяет модулям на разных языках обмениваться богатыми типами (строки, списки), а не только числами
CСжимает .wasm файлы
DДобавляет доступ к DOM
2. На чём основана изоляция памяти в Wasm?
AНа шифровании
BМодуль видит только свою линейную память, каждое обращение проверяется на границу
CНа паролях
DНа антивирусе
3. Почему модуль Wasm не может сделать то, что ему не разрешили?
AОн слишком медленный
BЕдинственные двери наружу — импорты, которые задаёт хост
CОн не умеет вызывать функции
DЭто запрещено лицензией