Unescape HTML сущности в Javascript?


176

У меня есть некоторый код Javascript, который взаимодействует с бэкэндом XML-RPC. XML-RPC возвращает строки в форме:

<img src='myimage.jpg'>

Однако когда я использую Javascript для вставки строк в HTML, они отображаются буквально. Я не вижу изображения, я буквально вижу строку:

<img src='myimage.jpg'>

Я предполагаю, что HTML экранируется по каналу XML-RPC.

Как я могу удалить строку в Javascript? Я попробовал методы на этой странице, но безуспешно: http://paulschreiber.com/blog/2008/09/20/javascript-how-to-unescape-html-entities/

Каковы другие способы диагностики проблемы?


1
Попробуйте это: stackoverflow.com/questions/4480757/…
XP1

Ответы:


176

РЕДАКТИРОВАТЬ: Вы должны использовать API DOMParser, как подсказывает Владимир , я отредактировал свой предыдущий ответ, так как опубликованная функция представила уязвимость безопасности.

Следующий фрагмент кода старого ответа с небольшой модификацией: использование textareaвместо вместо divуменьшает уязвимость XSS, но все еще проблематично в IE9 и Firefox.

function htmlDecode(input){
  var e = document.createElement('textarea');
  e.innerHTML = input;
  // handle case of empty input
  return e.childNodes.length === 0 ? "" : e.childNodes[0].nodeValue;
}

htmlDecode("&lt;img src='myimage.jpg'&gt;"); 
// returns "<img src='myimage.jpg'>"

По сути, я создаю элемент DOM программно, назначаю закодированный HTML-код его innerHTML и извлекаю nodeValue из текстового узла, созданного при вставке innerHTML. Поскольку он просто создает элемент, но никогда не добавляет его, HTML-код сайта не изменяется.

Он будет работать в кросс-браузерном режиме (включая старые браузеры) и принимать все объекты символов HTML .

РЕДАКТИРОВАТЬ: старая версия этого кода не работала на IE с пустыми вводами , как показано здесь на jsFiddle (просмотр в IE). Версия выше работает со всеми входами.

ОБНОВЛЕНИЕ: кажется, это не работает с большой строкой, и это также представляет уязвимость безопасности , см. Комментарии.


Понятно, вы изменили на ', поэтому позвольте мне удалить мой комментарий назад, спасибо, он отлично работает, +1
ВАС

1
@ S.Mark: &apos;не принадлежит сущностям HTML 4, вот почему! w3.org/TR/html4/sgml/entities.html fishbowl.pastiche.org/2003/07/01/the_curse_of_apos
CMS

2
Смотрите также примечание @ kender о плохой безопасности этого подхода.
Джозеф Туриан

2
Смотрите мою заметку к @kender о плохом тестировании, которое он сделал;)
Роатин Март

24
Эта функция представляет угрозу безопасности, код JavaScript будет работать даже несмотря на то, что элемент не добавлен в DOM. Так что это только то, что нужно использовать, если входная строка является доверенной. Я добавил свой ответ, объяснив проблему и предложив безопасное решение. Как побочный эффект, результат не обрезается, если существует несколько текстовых узлов.
Владимир Палант

376

Большинство ответов, приведенных здесь, имеют огромный недостаток: если строка, которую вы пытаетесь преобразовать, не является доверенной, в результате вы получите уязвимость для межсайтового скриптинга (XSS) . Для функции в принятом ответе учтите следующее:

htmlDecode("<img src='dummy' onerror='alert(/xss/)'>");

Здесь строка содержит неэкранированный HTML-тег, поэтому вместо расшифровки чего-либо htmlDecodeфункция на самом деле будет выполнять код JavaScript, указанный внутри строки.

Этого можно избежать, используя DOMParser, который поддерживается во всех современных браузерах :

function htmlDecode(input) {
  var doc = new DOMParser().parseFromString(input, "text/html");
  return doc.documentElement.textContent;
}

console.log(  htmlDecode("&lt;img src='myimage.jpg'&gt;")  )    
// "<img src='myimage.jpg'>"

console.log(  htmlDecode("<img src='dummy' onerror='alert(/xss/)'>")  )  
// ""

Эта функция гарантированно не запускает какой-либо код JavaScript в качестве побочного эффекта. Любые HTML-теги будут игнорироваться, будет возвращен только текстовый контент.

Примечание о совместимости : для анализа HTML DOMParserтребуется как минимум Chrome 30, Firefox 12, Opera 17, Internet Explorer 10, Safari 7.1 или Microsoft Edge. Таким образом, все браузеры без поддержки уже прошли EOL, и по состоянию на 2017 год единственными, которые все еще можно увидеть в дикой природе, иногда являются старые версии Internet Explorer и Safari (обычно их все еще недостаточно, чтобы беспокоиться).


19
Я думаю, что этот ответ является лучшим, потому что он упомянул уязвимость XSS.
Константин Ван

2
Обратите внимание, что (согласно вашей ссылке) DOMParserне поддерживал "text/html"до Firefox 12.0, и все еще есть некоторые последние версии браузеров, которые даже не поддерживаютDOMParser.prototype.parseFromString() . Согласно вашему упоминанию, DOMParserэто все еще экспериментальная технология, и в ней используются innerHTMLсвойства, которые, как вы также указали в ответ на мой подход , имеют эту уязвимость XSS (которую должны исправлять производители браузеров).
PointedEars

4
@PointedEars: кого волнует Firefox 12 в 2016 году? Проблемными являются Internet Explorer до 9.0 и Safari до 7.0. Если кто-то может позволить себе не поддерживать их (что, надеюсь, скоро будет всем), то DOMParser - лучший выбор. Если нет - да, обработка объектов только будет вариант.
Владимир Палант

4
@PointedEars: <script>теги, которые не выполняются, не являются механизмом безопасности, это правило просто исключает сложные временные проблемы, если настройка innerHTMLможет запускать синхронные сценарии как побочный эффект. Санитарная обработка HTML-кода - дело сложное и innerHTMLдаже не пытается - уже потому, что на веб-странице могут быть заданы встроенные обработчики событий. Это просто не механизм, предназначенный для небезопасных данных, полная остановка.
Владимир Палант

1
@ ИльяЗеленько: Планируете ли вы использовать этот код в узком цикле или почему производительность имеет значение? Ваш ответ снова уязвим для XSS, стоило ли оно того?
Владимир Палант

37

Если вы используете jQuery:

function htmlDecode(value){ 
  return $('<div/>').html(value).text(); 
}

В противном случае используйте объект кодирования Strictly Software , который имеет отличную htmlDecode()функцию.


59
Не (повторяйте НЕ) используйте это для пользовательского контента, отличного от контента, созданного этим пользователем. Если в значении есть тег <script>, содержимое скрипта будет выполнено!
Malvolio

Я не могу найти лицензию на это нигде на сайте. Вы знаете, что такое лицензия?
TRiG

В заголовке исходного кода есть лицензия, это GPL.
Крис Фулстоу,

6
ДА, эта функция открывает путь для XSS: попробуйте htmlDecode ("<script> alert (12) </ script> 123 & gt;")
Динис Круз

что означает $ ('<div />') ?
Эхо Ян

13

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

function unescapeHtml(html) {
    var el = document.createElement('div');
    return html.replace(/\&[#0-9a-z]+;/gi, function (enc) {
        el.innerHTML = enc;
        return el.innerText
    });
}

Регулярное выражение может быть немного более подходящим, /\&#?[0-9a-z]+;/giтак как # должно появляться только как 2-й символ, если он вообще есть.
TheAtomicOption

Это лучший ответ. Предотвращает уязвимость XSS и не удаляет теги HTML.
Эммануэль

6

Ответ CMS работает нормально, если только HTML-код, который вы хотите удалить, не очень длинный, длиннее 65536 символов. Потому что тогда в Chrome внутренний HTML разбивается на множество дочерних узлов, каждый длиной не более 65536, и вам нужно объединить их. Эта функция работает также для очень длинных строк:

function unencodeHtmlContent(escapedHtml) {
  var elem = document.createElement('div');
  elem.innerHTML = escapedHtml;
  var result = '';
  // Chrome splits innerHTML into many child nodes, each one at most 65536.
  // Whereas FF creates just one single huge child node.
  for (var i = 0; i < elem.childNodes.length; ++i) {
    result = result + elem.childNodes[i].nodeValue;
  }
  return result;
}

См. Этот ответ о innerHTMLмаксимальной длине для получения дополнительной информации: https://stackoverflow.com/a/27545633/694469


3

Не прямой ответ на ваш вопрос, но не лучше ли для вашего RPC вернуть некоторую структуру (будь то XML, JSON или что-то еще) с этими данными изображения (URL в вашем примере) внутри этой структуры?

Затем вы можете просто проанализировать его в своем javascript и создать сам <img>JavaScript.

Структура, которую вы получаете от RPC, может выглядеть так:

{"img" : ["myimage.jpg", "myimage2.jpg"]}

Я думаю, что так будет лучше, поскольку внедрение кода, полученного из внешнего источника, на вашу страницу не выглядит очень безопасным. Представьте, что кто-то захватывает ваш XML-RPC-скрипт и помещает туда что-то, что вам не нужно (даже некоторый javascript ...)


Есть ли у подхода @CMS, описанного выше, этот недостаток безопасности?
Джозеф Туриан

Я только что проверил следующий аргумент, переданный функции htmlDecode: htmlDecode ("& lt; img src = 'myimage.jpg' & gt; & lt; script & gt; document.write ('xxxxx'); & lt; / script & gt;") и он создает Элемент <script> </ script>, который может быть плохим, imho. И я все еще думаю, что лучше возвращать структуру вместо вставляемого текста, например, вы можете хорошо обрабатывать ошибки.
Кендер

1
Я только попробовал, htmlDecode("&lt;img src='myimage.jpg'&gt;&lt;script&gt;alert('xxxxx');&lt;/script&gt;")и ничего не случилось. Я получил декодированную строку HTML обратно, как и ожидалось.
Роатин Март

2

Крис ответ хороший и элегантный , но оно не выполняется , если значение не определено . Просто простое улучшение делает это твердым:

function htmlDecode(value) {
   return (typeof value === 'undefined') ? '' : $('<div/>').html(value).text();
}

Если улучшить, то сделайте:return (typeof value !== 'string') ? '' : $('<div/>').html(value).text();
SynCap

2

Не за что ... просто посыльный ... полный кредит переходит на ourcodeworld.com, ссылка ниже.

window.htmlentities = {
        /**
         * Converts a string to its html characters completely.
         *
         * @param {String} str String with unescaped HTML characters
         **/
        encode : function(str) {
            var buf = [];

            for (var i=str.length-1;i>=0;i--) {
                buf.unshift(['&#', str[i].charCodeAt(), ';'].join(''));
            }

            return buf.join('');
        },
        /**
         * Converts an html characterSet into its original character.
         *
         * @param {String} str htmlSet entities
         **/
        decode : function(str) {
            return str.replace(/&#(\d+);/g, function(match, dec) {
                return String.fromCharCode(dec);
            });
        }
    };

Полный кредит: https://ourcodeworld.com/articles/read/188/encode-and-decode-html-entities-using-pure-javascript


2

Это наиболее полное решение, которое я пробовал до сих пор:

const STANDARD_HTML_ENTITIES = {
    nbsp: String.fromCharCode(160),
    amp: "&",
    quot: '"',
    lt: "<",
    gt: ">"
};

const replaceHtmlEntities = plainTextString => {
    return plainTextString
        .replace(/&#(\d+);/g, (match, dec) => String.fromCharCode(dec))
        .replace(
            /&(nbsp|amp|quot|lt|gt);/g,
            (a, b) => STANDARD_HTML_ENTITIES[b]
        );
};

"Самый полный"? Вы пытались запустить его на самом деле комплексный набор тестов ?
Дан Даскалеску

1

Я был достаточно сумасшедшим, чтобы пройти и сделать эту функцию, которая должна быть довольно, если не полностью, исчерпывающей:

function removeEncoding(string) {
    return string.replace(/&Agrave;/g, "À").replace(/&Aacute;/g, "Á").replace(/&Acirc;/g, "Â").replace(/&Atilde;/g, "Ã").replace(/&Auml;/g, "Ä").replace(/&Aring;/g, "Å").replace(/&agrave;/g, "à").replace(/&acirc;/g, "â").replace(/&atilde;/g, "ã").replace(/&auml;/g, "ä").replace(/&aring;/g, "å").replace(/&AElig;/g, "Æ").replace(/&aelig;/g, "æ").replace(/&szlig;/g, "ß").replace(/&Ccedil;/g, "Ç").replace(/&ccedil;/g, "ç").replace(/&Egrave;/g, "È").replace(/&Eacute;/g, "É").replace(/&Ecirc;/g, "Ê").replace(/&Euml;/g, "Ë").replace(/&egrave;/g, "è").replace(/&eacute;/g, "é").replace(/&ecirc;/g, "ê").replace(/&euml;/g, "ë").replace(/&#131;/g, "ƒ").replace(/&Igrave;/g, "Ì").replace(/&Iacute;/g, "Í").replace(/&Icirc;/g, "Î").replace(/&Iuml;/g, "Ï").replace(/&igrave;/g, "ì").replace(/&iacute;/g, "í").replace(/&icirc;/g, "î").replace(/&iuml;/g, "ï").replace(/&Ntilde;/g, "Ñ").replace(/&ntilde;/g, "ñ").replace(/&Ograve;/g, "Ò").replace(/&Oacute;/g, "Ó").replace(/&Ocirc;/g, "Ô").replace(/&Otilde;/g, "Õ").replace(/&Ouml;/g, "Ö").replace(/&ograve;/g, "ò").replace(/&oacute;/g, "ó").replace(/&ocirc;/g, "ô").replace(/&otilde;/g, "õ").replace(/&ouml;/g, "ö").replace(/&Oslash;/g, "Ø").replace(/&oslash;/g, "ø").replace(/&#140;/g, "Œ").replace(/&#156;/g, "œ").replace(/&#138;/g, "Š").replace(/&#154;/g, "š").replace(/&Ugrave;/g, "Ù").replace(/&Uacute;/g, "Ú").replace(/&Ucirc;/g, "Û").replace(/&Uuml;/g, "Ü").replace(/&ugrave;/g, "ù").replace(/&uacute;/g, "ú").replace(/&ucirc;/g, "û").replace(/&uuml;/g, "ü").replace(/&#181;/g, "µ").replace(/&#215;/g, "×").replace(/&Yacute;/g, "Ý").replace(/&#159;/g, "Ÿ").replace(/&yacute;/g, "ý").replace(/&yuml;/g, "ÿ").replace(/&#176;/g, "°").replace(/&#134;/g, "†").replace(/&#135;/g, "‡").replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/&#177;/g, "±").replace(/&#171;/g, "«").replace(/&#187;/g, "»").replace(/&#191;/g, "¿").replace(/&#161;/g, "¡").replace(/&#183;/g, "·").replace(/&#149;/g, "•").replace(/&#153;/g, "™").replace(/&copy;/g, "©").replace(/&reg;/g, "®").replace(/&#167;/g, "§").replace(/&#182;/g, "¶").replace(/&Alpha;/g, "Α").replace(/&Beta;/g, "Β").replace(/&Gamma;/g, "Γ").replace(/&Delta;/g, "Δ").replace(/&Epsilon;/g, "Ε").replace(/&Zeta;/g, "Ζ").replace(/&Eta;/g, "Η").replace(/&Theta;/g, "Θ").replace(/&Iota;/g, "Ι").replace(/&Kappa;/g, "Κ").replace(/&Lambda;/g, "Λ").replace(/&Mu;/g, "Μ").replace(/&Nu;/g, "Ν").replace(/&Xi;/g, "Ξ").replace(/&Omicron;/g, "Ο").replace(/&Pi;/g, "Π").replace(/&Rho;/g, "Ρ").replace(/&Sigma;/g, "Σ").replace(/&Tau;/g, "Τ").replace(/&Upsilon;/g, "Υ").replace(/&Phi;/g, "Φ").replace(/&Chi;/g, "Χ").replace(/&Psi;/g, "Ψ").replace(/&Omega;/g, "Ω").replace(/&alpha;/g, "α").replace(/&beta;/g, "β").replace(/&gamma;/g, "γ").replace(/&delta;/g, "δ").replace(/&epsilon;/g, "ε").replace(/&zeta;/g, "ζ").replace(/&eta;/g, "η").replace(/&theta;/g, "θ").replace(/&iota;/g, "ι").replace(/&kappa;/g, "κ").replace(/&lambda;/g, "λ").replace(/&mu;/g, "μ").replace(/&nu;/g, "ν").replace(/&xi;/g, "ξ").replace(/&omicron;/g, "ο").replace(/&piρ;/g, "ρ").replace(/&rho;/g, "ς").replace(/&sigmaf;/g, "ς").replace(/&sigma;/g, "σ").replace(/&tau;/g, "τ").replace(/&phi;/g, "φ").replace(/&chi;/g, "χ").replace(/&psi;/g, "ψ").replace(/&omega;/g, "ω").replace(/&bull;/g, "•").replace(/&hellip;/g, "…").replace(/&prime;/g, "′").replace(/&Prime;/g, "″").replace(/&oline;/g, "‾").replace(/&frasl;/g, "⁄").replace(/&weierp;/g, "℘").replace(/&image;/g, "ℑ").replace(/&real;/g, "ℜ").replace(/&trade;/g, "™").replace(/&alefsym;/g, "ℵ").replace(/&larr;/g, "←").replace(/&uarr;/g, "↑").replace(/&rarr;/g, "→").replace(/&darr;/g, "↓").replace(/&barr;/g, "↔").replace(/&crarr;/g, "↵").replace(/&lArr;/g, "⇐").replace(/&uArr;/g, "⇑").replace(/&rArr;/g, "⇒").replace(/&dArr;/g, "⇓").replace(/&hArr;/g, "⇔").replace(/&forall;/g, "∀").replace(/&part;/g, "∂").replace(/&exist;/g, "∃").replace(/&empty;/g, "∅").replace(/&nabla;/g, "∇").replace(/&isin;/g, "∈").replace(/&notin;/g, "∉").replace(/&ni;/g, "∋").replace(/&prod;/g, "∏").replace(/&sum;/g, "∑").replace(/&minus;/g, "−").replace(/&lowast;/g, "∗").replace(/&radic;/g, "√").replace(/&prop;/g, "∝").replace(/&infin;/g, "∞").replace(/&OEig;/g, "Œ").replace(/&oelig;/g, "œ").replace(/&Yuml;/g, "Ÿ").replace(/&spades;/g, "♠").replace(/&clubs;/g, "♣").replace(/&hearts;/g, "♥").replace(/&diams;/g, "♦").replace(/&thetasym;/g, "ϑ").replace(/&upsih;/g, "ϒ").replace(/&piv;/g, "ϖ").replace(/&Scaron;/g, "Š").replace(/&scaron;/g, "š").replace(/&ang;/g, "∠").replace(/&and;/g, "∧").replace(/&or;/g, "∨").replace(/&cap;/g, "∩").replace(/&cup;/g, "∪").replace(/&int;/g, "∫").replace(/&there4;/g, "∴").replace(/&sim;/g, "∼").replace(/&cong;/g, "≅").replace(/&asymp;/g, "≈").replace(/&ne;/g, "≠").replace(/&equiv;/g, "≡").replace(/&le;/g, "≤").replace(/&ge;/g, "≥").replace(/&sub;/g, "⊂").replace(/&sup;/g, "⊃").replace(/&nsub;/g, "⊄").replace(/&sube;/g, "⊆").replace(/&supe;/g, "⊇").replace(/&oplus;/g, "⊕").replace(/&otimes;/g, "⊗").replace(/&perp;/g, "⊥").replace(/&sdot;/g, "⋅").replace(/&lcell;/g, "⌈").replace(/&rcell;/g, "⌉").replace(/&lfloor;/g, "⌊").replace(/&rfloor;/g, "⌋").replace(/&lang;/g, "⟨").replace(/&rang;/g, "⟩").replace(/&loz;/g, "◊").replace(/&#039;/g, "'").replace(/&amp;/g, "&").replace(/&quot;/g, "\"");
}

Используется так:

let decodedText = removeEncoding("Ich hei&szlig;e David");
console.log(decodedText);

Печать: Ich Heiße David

PS это заняло как полтора часа, чтобы сделать.


0

Чтобы скрыть HTML-сущности * в JavaScript, вы можете использовать небольшую библиотеку html-escaper :npm install html-escaper

import {unescape} from 'html-escaper';

unescape('escaped string');

Или используйте unescapeфункцию Lodash или Underscore , если вы ее используете.


*) Пожалуйста , обратите внимание , что эти функции не охватывают всех HTML сущностей, но только самые распространенные из них, то есть &, <, >, ', ". Для того, чтобы все HTML экранирования в сущности вы можете использовать он библиотеку.


-1

Я использую это в своем проекте: вдохновленный другими ответами, но с дополнительным безопасным параметром, может быть полезен, когда вы имеете дело с украшенными персонажами

var decodeEntities=(function(){

    var el=document.createElement('div');
    return function(str, safeEscape){

        if(str && typeof str === 'string'){

            str=str.replace(/\</g, '&lt;');

            el.innerHTML=str;
            if(el.innerText){

                str=el.innerText;
                el.innerText='';
            }
            else if(el.textContent){

                str=el.textContent;
                el.textContent='';
            }

            if(safeEscape)
                str=str.replace(/\</g, '&lt;');
        }
        return str;
    }
})();

И это можно использовать как:

var label='safe <b> character &eacute;ntity</b>';
var safehtml='<div title="'+decodeEntities(label)+'">'+decodeEntities(label, true)+'</div>';

-1

Все остальные ответы здесь имеют проблемы.

Методы document.createElement ('div') (включая методы, использующие jQuery) выполняют любой переданный в него javascript (проблема безопасности), а метод DOMParser.parseFromString () удаляет пробелы. Вот чистое решение JavaScript, которое не имеет ни одной проблемы:

function htmlDecode(html) {
    var textarea = document.createElement("textarea");
    html= html.replace(/\r/g, String.fromCharCode(0xe000)); // Replace "\r" with reserved unicode character.
    textarea.innerHTML = html;
    var result = textarea.value;
    return result.replace(new RegExp(String.fromCharCode(0xe000), 'g'), '\r');
}

TextArea используется специально, чтобы избежать выполнения кода JS. Это проходит эти:

htmlDecode('&lt;&amp;&nbsp;&gt;'); // returns "<& >" with non-breaking space.
htmlDecode('  '); // returns "  "
htmlDecode('<img src="dummy" onerror="alert(\'xss\')">'); // Does not execute alert()
htmlDecode('\r\n') // returns "\r\n", doesn't lose the \r like other solutions.

1
Нет, использование другого тега не решает проблему. Это все еще уязвимость XSS, попробуйте htmlDecode("</textarea><img src=x onerror=alert(1)>"). Вы опубликовали это после того, как я уже указал на этот вопрос в ответе Серхио Белевского.
Владимир Палант

Я не могу воспроизвести проблему, которую вы описываете. У меня есть ваш код в этом JsFiddle, и при запуске не отображается предупреждение. jsfiddle.net/edsjt15g/1 Можете посмотреть? Какой браузер вы используете?
EricP

2
Я использую Firefox. Chrome действительно обрабатывает этот сценарий по-другому, поэтому код не выполняется - однако это не то, на что вам следует полагаться.
Владимир Палант

-1
var encodedStr = 'hello &amp; world';

var parser = new DOMParser;
var dom = parser.parseFromString(
    '<!doctype html><body>' + encodedStr,
    'text/html');
var decodedString = dom.body.textContent;

console.log(decodedString);

@ Владимир Палант (автор AdBlock Plus) уже дал ответ DOMParser 4 годами ранее. Вы читали предыдущие ответы, прежде чем опубликовать свой?
Дан Даскалеску

-7

Есть вариант, который на 80% продуктивнее ответов на самом верху.

См. Тест: https://jsperf.com/decode-html12345678/1

тест производительности

console.log(decodeEntities('test: &gt'));

function decodeEntities(str) {
  // this prevents any overhead from creating the object each time
  const el = decodeEntities.element || document.createElement('textarea')

  // strip script/html tags
  el.innerHTML = str
    .replace(/<script[^>]*>([\S\s]*?)<\/script>/gmi, '')
    .replace(/<\/?\w(?:[^"'>]|"[^"]*"|'[^']*')*>/gmi, '');

  return el.value;
}

Если вам нужно оставить теги, удалите два .replace(...)вызова (вы можете оставить первый, если вам не нужны скрипты).


6
Поздравляем, вам удалось скрыть уязвимость с помощью фиктивной санитарной логики, и все это для выигрыша в производительности, который не будет иметь значения на практике. Попробуйте позвонить decodeEntities("</textarea '><img src=x onerror=alert(1) \">")в Firefox. Пожалуйста, прекратите попытки дезинфицировать HTML-код с помощью регулярных выражений.
Владимир Палант
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.