Unescape entità HTML in Javascript?


176

Ho del codice Javascript che comunica con un back-end XML-RPC. XML-RPC restituisce stringhe del modulo:

<img src='myimage.jpg'>

Tuttavia, quando uso JavaScript per inserire le stringhe in HTML, vengono visualizzate letteralmente. Non vedo un'immagine, vedo letteralmente la stringa:

<img src='myimage.jpg'>

La mia ipotesi è che l'HTML sia in fase di escape sul canale XML-RPC.

Come posso annullare l'escape della stringa in Javascript? Ho provato le tecniche su questa pagina, senza successo: http://paulschreiber.com/blog/2008/09/20/javascript-how-to-unescape-html-entities/

Quali sono altri modi per diagnosticare il problema?



Risposte:


176

EDIT: dovresti usare l'API DOMParser come suggerisce Wladimir , ho modificato la mia risposta precedente da quando la funzione pubblicata ha introdotto una vulnerabilità di sicurezza.

Il frammento seguente è il codice della vecchia risposta con una piccola modifica: l'utilizzo di un textareaanziché un divriduce la vulnerabilità XSS, ma è ancora problematico in IE9 e 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'>"

Fondamentalmente creo un elemento DOM a livello di codice, assegno l'HTML codificato al suo innerHTML e recupero il nodeValue dal nodo di testo creato sull'inserimento innerHTML. Poiché crea solo un elemento ma non lo aggiunge mai, nessun HTML del sito viene modificato.

Funzionerà su più browser (inclusi i browser meno recenti) e accetterà tutte le entità carattere HTML .

EDIT: la vecchia versione di questo codice non funzionava su IE con input vuoti, come evidenziato qui su jsFiddle (vista in IE). La versione sopra funziona con tutti gli input.

AGGIORNAMENTO: sembra che questo non funzioni con stringhe di grandi dimensioni e introduce anche una vulnerabilità di sicurezza , vedere i commenti.


Capito, hai cambiato in ", quindi lasciami cancellare il mio commento indietro, grazie, funziona alla grande, +1
YOU

1
@ S.Mark: &apos;non appartiene alle entità HTML 4, ecco perché! w3.org/TR/html4/sgml/entities.html fishbowl.pastiche.org/2003/07/01/the_curse_of_apos
CMS

2
Vedi anche la nota di @ kender sulla scarsa sicurezza di questo approccio.
Joseph Turian,

2
Vedi la mia nota a @kender in merito alle scarse prove che ha fatto;)
Roatin Marth,

24
Questa funzione costituisce un pericolo per la sicurezza, il codice JavaScript verrà eseguito anche se l'elemento non viene aggiunto al DOM. Quindi questo è solo qualcosa da usare se la stringa di input è attendibile. Ho aggiunto la mia risposta spiegando il problema e fornendo una soluzione sicura. Come effetto collaterale, il risultato non viene tagliato se esistono più nodi di testo.
Wladimir Palant,

375

La maggior parte delle risposte fornite qui presenta un enorme svantaggio: se la stringa che si sta tentando di convertire non è attendibile, si otterrà una vulnerabilità Cross-Site Scripting (XSS) . Per la funzione nella risposta accettata , considerare quanto segue:

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

La stringa qui contiene un tag HTML senza escape, quindi invece di decodificare qualsiasi cosa la htmlDecodefunzione eseguirà effettivamente il codice JavaScript specificato all'interno della stringa.

Questo può essere evitato usando DOMParser che è supportato in tutti i browser moderni :

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/)'>")  )  
// ""

Questa funzione è garantita per non eseguire alcun codice JavaScript come effetto collaterale. Eventuali tag HTML verranno ignorati, verrà restituito solo il contenuto del testo.

Nota di compatibilità : l'analisi di HTML DOMParserrichiede almeno Chrome 30, Firefox 12, Opera 17, Internet Explorer 10, Safari 7.1 o Microsoft Edge. Quindi tutti i browser senza supporto sono ben oltre la loro EOL e a partire dal 2017 gli unici che possono ancora essere visti allo stato brado di tanto in tanto sono versioni precedenti di Internet Explorer e Safari (di solito questi non sono ancora abbastanza numerosi da disturbare).


19
Penso che questa risposta sia la migliore perché ha menzionato la vulnerabilità XSS.
Константин Ван,

2
Nota che (secondo il tuo riferimento) DOMParsernon era supportato "text/html"prima di Firefox 12.0 e ci sono ancora alcune versioni più recenti dei browser che non supportano nemmenoDOMParser.prototype.parseFromString() . Secondo il tuo riferimento, DOMParserè ancora una tecnologia sperimentale e gli stand-in usano la innerHTMLproprietà che, come hai anche sottolineato in risposta al mio approccio , ha questa vulnerabilità XSS (che dovrebbe essere risolta dai fornitori di browser).
Orecchie appuntite

4
@PointedEars: a chi importa di Firefox 12 nel 2016? Quelli problematici sono Internet Explorer fino alla 9.0 e Safari fino alla 7.0. Se uno può permettersi di non sostenerli (che si spera saranno presto tutti), allora DOMParser è la scelta migliore. In caso contrario, sì, solo le entità di elaborazione sarebbero un'opzione.
Wladimir Palant,

4
@PointedEars: i <script>tag che non vengono eseguiti non sono un meccanismo di sicurezza, questa regola evita semplicemente i difficili problemi di temporizzazione se l'impostazione innerHTMLpotrebbe eseguire script sincroni come effetto collaterale. La disinfezione del codice HTML è una faccenda complicata e innerHTMLnon ci prova nemmeno, già perché la pagina web potrebbe effettivamente voler impostare gestori di eventi in linea. Questo semplicemente non è un meccanismo destinato a dati non sicuri, punto e basta.
Wladimir Palant,

1
@ ИльяЗеленько: prevedi di utilizzare questo codice in un ciclo stretto o perché le prestazioni sono importanti? La tua risposta è di nuovo vulnerabile a XSS, ne è valsa davvero la pena?
Wladimir Palant,

37

Se stai usando jQuery:

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

In caso contrario, utilizzare Encoder Object di Strictly Software , che ha una htmlDecode()funzione eccellente .


59
Non (ripetere NOT) utilizzarlo per contenuti generati dall'utente diversi da quelli generati da questo utente. Se c'è un tag <script> nel valore, il contenuto dello script verrà eseguito!
Malvolio,

Non riesco a trovare una licenza per questo da nessuna parte sul sito. Sai qual è la licenza?
TRiG

C'è una licenza nell'intestazione del codice sorgente, è GPL.
Chris Fulstow,

6
SÌ, quella funzione apre la strada a XSS: prova htmlDecode ("<script> alert (12) </script> 123 & gt;")
Dinis Cruz,

che significato ha $ ('<div />') ?
Echo Yang,

13

Il trucco è utilizzare la potenza del browser per decodificare i caratteri HTML speciali, ma non consentire al browser di eseguire i risultati come se fosse un vero HTML ... Questa funzione utilizza un regex per identificare e sostituire i caratteri HTML codificati, un carattere Al tempo.

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

Il regex può essere abbinato un po 'più stretto /\&#?[0-9a-z]+;/gipoiché # dovrebbe apparire solo come il 2 ° carattere, se non del tutto.
TheAtomicOption

Questa è la risposta migliore Evita la vulnerabilità di XSS e non elimina i tag HTML.
Emmanuel,

6

La risposta di CMS funziona benissimo, a meno che l'HTML che si desidera eliminare sia molto lungo, più lungo di 65536 caratteri. Perché quindi in Chrome l'HTML interno viene suddiviso in molti nodi figlio, ciascuno lungo al massimo 65536, e devi concatenarli. Questa funzione funziona anche per stringhe molto lunghe:

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;
}

Vedi questa risposta sulla innerHTMLlunghezza massima per maggiori informazioni: https://stackoverflow.com/a/27545633/694469


3

Non è una risposta diretta alla tua domanda, ma non sarebbe meglio per il tuo RPC restituire una struttura (sia essa XML o JSON o altro) con quei dati di immagine (URL nel tuo esempio) all'interno di quella struttura?

Quindi puoi semplicemente analizzarlo nel tuo javascript e creare il <img>javascript stesso.

La struttura che ricevi da RPC potrebbe apparire come:

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

Penso che sia meglio in questo modo, poiché iniettare un codice che proviene da una fonte esterna nella tua pagina non sembra molto sicuro. Immaginare qualcuno che dirotta il tuo script XML-RPC e mette qualcosa che non vorresti lì dentro (anche un po 'di javascript ...)


L'approccio @CMS sopra ha questo difetto di sicurezza?
Joseph Turian,

Ho appena verificato il seguente argomento passato a htmlDecode fuction: htmlDecode ("& lt; img src = 'myimage.jpg' & gt; & lt; script & gt; document.write ('xxxxx'); & lt; / script & gt;") e crea il <script> </script> elemento che può essere negativo, imho. E penso ancora che sia meglio restituire una struttura invece del testo da inserire, ad esempio puoi gestire bene gli errori.
kender il

1
Ho appena provato htmlDecode("&lt;img src='myimage.jpg'&gt;&lt;script&gt;alert('xxxxx');&lt;/script&gt;")e non è successo niente. Ho recuperato la stringa HTML decodificata come previsto.
Roatin Marth,

2

La risposta di Chris è bella ed elegante, ma fallisce se il valore non è definito . Solo un semplice miglioramento lo rende solido:

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

Se migliora, allora:return (typeof value !== 'string') ? '' : $('<div/>').html(value).text();
SynCap il

2

Di niente ... solo un messaggero ... il credito completo va a ourcodeworld.com, link sotto.

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);
            });
        }
    };

Credito completo: https://ourcodeworld.com/articles/read/188/encode-and-decode-html-entities-using-pure-javascript


2

Questa è la soluzione più completa che ho provato finora:

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]
        );
};

"Il più completo"? Hai provato a eseguirlo su una suite di test davvero completa ?
Dan Dascalescu,

1

Sono stato abbastanza pazzo da svolgere e rendere questa funzione che dovrebbe essere piuttosto, se non completamente, esaustiva:

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, "\"");
}

Usato così:

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

stampe: Ich Heiße David

PS questo ci è voluto circa un'ora e mezza per essere realizzato.


0

Per annullare l' escape di entità HTML * in JavaScript è possibile utilizzare la piccola libreria html-escaper :npm install html-escaper

import {unescape} from 'html-escaper';

unescape('escaped string');

O unescapefunzioni da Lodash o Underscore , se lo stai usando.


*) Si noti che queste funzioni non coprono tutte le entità HTML, ma solo quelli più comuni, vale a dire &, <, >, ', ". Per unescape tutte le entità HTML è possibile utilizzare lo biblioteca.


-1

Lo uso nel mio progetto: ispirato ad altre risposte ma con un parametro extra sicuro, può essere utile quando si affrontano personaggi decorati

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;
    }
})();

Ed è utilizzabile come:

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

-1

Tutte le altre risposte qui hanno problemi.

I metodi document.createElement ('div') (inclusi quelli che usano jQuery) eseguono qualsiasi javascript passato (un problema di sicurezza) e il metodo DOMParser.parseFromString () taglia gli spazi bianchi. Ecco una soluzione javascript pura che non ha nessun problema:

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 viene utilizzato specificamente per evitare il codice di esecuzione. Passa questi:

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
No, l'utilizzo di un tag diverso non risolve il problema. Questa è ancora una vulnerabilità XSS, prova htmlDecode("</textarea><img src=x onerror=alert(1)>"). Hai pubblicato questo post dopo aver già segnalato questo problema nella risposta di Sergio Belevskij.
Wladimir Palant,

Non riesco a riprodurre il problema che descrivi. Ho il tuo codice in questo JsFiddle e non viene visualizzato alcun avviso durante l'esecuzione. jsfiddle.net/edsjt15g/1 Puoi dare un'occhiata? Quale browser utilizzate?
EricP

2
Sto usando Firefox. Chrome infatti gestisce questo scenario in modo diverso, quindi il codice non viene eseguito, ma non qualcosa su cui dovresti fare affidamento.
Wladimir Palant,

-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);

@Wladimir Palant (autore di AdBlock Plus) ha già dato la risposta a DOMParser 4 anni prima. Hai letto le risposte precedenti prima di pubblicare le tue?
Dan Dascalescu,

-7

Esiste una variante dell'80% produttiva come le risposte ai vertici.

Vedi il benchmark: https://jsperf.com/decode-html12345678/1

test della prestazione

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;
}

Se devi lasciare tag, rimuovi le due .replace(...)chiamate (puoi lasciare la prima se non hai bisogno di script).


6
Congratulazioni, sei riuscito a oscurare la vulnerabilità con una logica di sanitizaion fasulla, il tutto per una vittoria in termini di prestazioni che non ha importanza nella pratica. Prova a chiamare decodeEntities("</textarea '><img src=x onerror=alert(1) \">")in Firefox. Smetti di tentare di disinfettare il codice HTML con espressioni regolari.
Wladimir Palant,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.