Использование Google Caja для запуска пользовательского Javascript

Похоже, что официальные примеры используют caja.js, который просто оборачивает iframe для загрузки URL-адреса с сервера, на котором размещена служба компиляции caja, которая, в свою очередь, получает данные от некоторых URL. Соответствующий API для этого доступен здесь.

Однако на самом деле я хочу просто безопасно (и неоднократно) запускать предоставленный пользователем фрагмент Javascript, например:

for (var i = 0; i < N; ++i) {
    var x = getUserResult(currentState);
    updateState(currentState, x);
}

Есть ли способ сделать это напрямую? Код здесь содержит компилятор. Почему я не могу просто использовать это для компиляции кода, а затем запускать его в эмулируемом контексте? Это потому, что единственный способ получить безопасный контекст в браузере — это iframe? И если да, то можно ли каким-либо образом использовать iframe для прямого запуска данного исходного кода без необходимости его извлечения из внешнего URL-адреса?


person Domi    schedule 20.03.2014    source источник


Ответы (1)


Кахе нужен iframe несмотря ни на что. Оба режима выполнения требуют набора глобальных переменных JavaScript (полученных путем создания фрейма), которые доступны для радикального изменения для обеспечения безопасного выполнения.

Modern Caja (режим ES5) не требует компиляции на стороне сервера; при условии, что браузер совместим, вы можете использовать Caja стандартным способом, и с сервером никогда не будет связи. Чтобы принудительно это сделать, укажите es5Mode: true в параметрах caja.initialize.

Вы можете загрузить гостевой код один раз и многократно выполнять его; просто предоставьте api, который позволяет гостю передать функцию, когда она загружена, а затем вызовите функцию, когда захотите.


Для вашего варианта использования также можно было бы использовать SES, современную подсистему проверки безопасности Caja, вообще не используя саму Caja; это позволит вам пропустить какие-либо фреймы, но потребует, чтобы вы написали код, совместимый с SES; то есть,

  • воздержание от изменения глобальных объектов, таких как Object.prototype, и
  • защита всех объектов, прямо или косвенно подвергающихся воздействию пользовательского кода, с помощью Object.freeze().)

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

person Kevin Reid    schedule 21.03.2014
comment
Отличный ответ. Еще один вопрос: есть пример кода? Потому что стандартные примеры так не делают. - person Domi; 21.03.2014
comment
developers.google.com/caja/docs/callingguestcode — это пример гостевого -написанная функция, вызываемая хостом. - person Kevin Reid; 21.03.2014
comment
Извините, я должен был быть более явным. Я имел в виду пример кода SES? В приведенных примерах используется только iframe, а гостевой код всегда предоставляется через URL-адрес. - person Domi; 21.03.2014
comment
@ Доми Хороший вопрос. Я не знаю, был ли действительно какой-либо пример кода SES, написанный вне статей Марка Миллера. Я думаю, что это хороший вопрос для обсуждения в списке рассылки посмотреть, не трясется ли у кого память, и если нет, начать дискуссию о том, что писать. - person Kevin Reid; 22.03.2014
comment
@Domi Die, у тебя есть какие-нибудь успехи в этом? Мне бы тоже было интересно. - person heinob; 02.11.2014
comment
@heinob Нет, мне пришлось пока заморозить этот проект. Я использовал обработчиков потоков с белым списком в основном безопасных функций, как описано здесь. - person Domi; 02.11.2014