Добавить html в элемент jQuery без запуска скриптов внутри html

Я написал некоторый код, который берет строку html и очищает от него любой уродливый HTML, используя jQuery (см. ранний прототип в этот вопрос SO). Это работает очень хорошо, но я наткнулся на проблему:

При использовании .append(), чтобы обернуть html в div, все элементы script в коде оцениваются и запускаются (см. этот ответ SO для объяснение, почему это происходит). Я не хочу этого, я просто хочу, чтобы они были удалены, но я могу справиться с этим позже, если они не запущены.

Я использую этот код:

var wrapper = $('<div/>').append($(html));

Я попытался сделать это следующим образом:

var wrapper = $('<div>' + html + '</div>');

Но это просто приводит к ошибке "Access denied" в IE, которую исправляет функция append() (см. ответ, на который я ссылался выше).

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

Мои вопросы:

  • Как обернуть часть неизвестного html без запуска скриптов внутри него, предпочтительно удаляя их вообще?

  • Должен ли я выкинуть jQuery из окна и сделайте это с помощью обычного JavaScript и DOM-манипуляция вместо этого? Это поможет?

То, что я не пытаюсь сделать:

Я не пытаюсь поставить какой-то слой безопасности на стороне клиента. Я очень хорошо понимаю, что это было бы бессмысленно.

Обновление: предложение Джеймса

Джеймс предположил, что я должен отфильтровать элементы script, но посмотрите на эти два примера (первоначальное первое и предложение Джеймса):
jQuery("<p/>").append("<br/>hello<script type='text/javascript'>console.log('gnu!'); </script>there")

хранит текстовые узлы, но пишет gnu!

jQuery("<p/>").append(jQuery("<br/>hello<script type='text/javascript'>console.log('gnu!'); </script>there").not('script'))`

Не записывает gnu!, но также теряет текстовые узлы.

Обновление 2:

Джеймс обновил свой ответ, и я принял его. Однако см. Мой последний комментарий к его ответу.

Ответы

Ответ 1

Как насчет удаления скриптов в первую очередь?

var wrapper = $('<div/>').append($(html).not('script'));

Забастовкa >

  • Создать контейнер div
  • Используйте простой JS для размещения html в div
  • Удалите все элементы script в div

Предполагая, что элементы script в html не вложены в другие элементы:

var wrapper = document.createElement('div');
wrapper.innerHTML = html;
$(wrapper).children().remove('script');

Забастовкa >

var wrapper = document.createElement('div');
wrapper.innerHTML = html;
$(wrapper).find('script').remove();

Это работает для случая, когда html является просто текстом и где html имеет текст вне любых элементов.

Ответ 2

Ниже приведен альтернативный способ предотвращения запуска скриптов из загруженного html:

function preventJS(html) {
     return html.replace(/<script(?=(\s|>))/i, '<script type="text/xml" ');
}

Подробнее здесь описано JavaScript: как предотвратить выполнение JavaScript внутри html, добавляемого в DOM. Вероятно, это решение будет полезно для кого-то.

Ответ 3

Вы должны удалить элементы script:

var wrapper = $('<div/>').append($(html).remove("script"));

Забастовкa >

Вторая попытка:

node -validator может использоваться в браузере: https://github.com/chriso/node-validator

var str = sanitize(large_input_str).xss();

В качестве альтернативы PHPJS имеет функцию strip_tags (regex/evil based): http://phpjs.org/functions/strip_tags:535