apostrophecms / sanitize-html

Clean up user-submitted HTML, preserving whitelisted elements and whitelisted attributes on a per-element basis. Built on htmlparser2 for speed and tolerance
MIT License
3.68k stars 349 forks source link

Cannot read property 'replace' of undefined #579

Closed tyzion closed 1 year ago

tyzion commented 1 year ago

Hi, I'm using sanitize-html version 2.7.3.

I can't figure out why but if I try to sanitize an html text with this configuration

const html = `</head><body><table align="center" border="0" cellpadding="0" cellspacing="0" width="100%" style="border-collapse: collapse; mso-table-lspace: 0pt; mso-table-rspace: 0pt; -ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%; padding: 0; margin: 0 auto; max-width: 420px !important;"><tr><td><!--[if gte mso 9]><table align='center' border='0' cellspacing='0' cellpadding='0' width='420' style='width:420px;'><tr><td align='center' valign='top' width='420' style='width:420px;'><![endif]--><table align="center" border="0" cellpadding="0" cellspacing="0" width="100%" style="border-collapse: collapse; mso-table-lspace: 0pt; mso-table-rspace: 0pt; -ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%; padding: 0; margin: 0 auto; max-width: 420px !important;"><tr><td><table align="center" border="0" cellpadding="0" cellspacing="0" width="100%" style="border-collapse: collapse; mso-table-lspace: 0pt; mso-table-rspace: 0pt; -ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%; padding: 0; margin: 0 auto; max-width: 420px !important;"><tbody><tr><td valign="top" style="padding-right: 0;padding-left: 0;padding-top: 50px;padding-bottom: 50px;text-align: left;mso-line-height-rule: exactly;-ms-text-size-adjust: 100%;-webkit-text-size-adjust: 100%;"><a href="https://link.trustpilot.com/ls/click?params" style="display:block;"><img src="https://cdn.trustpilot.net/emails/business/tp-logo-rgb.png" alt="Trustpilot" width="131" style="display:block;"></a></td></tr><tr><td valign="top" style="padding-right: 0px;padding-left: 0px;padding-top: 0;padding-bottom: 30px;text-align: left;mso-line-height-rule: exactly;-ms-text-size-adjust: 100%;-webkit-text-size-adjust: 100%;"><h1 style="font-size:24px;margin:0;padding:0;color:#000;font-weight:300;line-height:1.5;color:#000;font-family:'Lato', sans-serif;">Name ha scritto una nuova recensione</h1></td></tr></tbody></table></td></tr><tr><td><table align="center" border="0" cellpadding="0" cellspacing="0" width="100%" style="border-collapse: collapse; mso-table-lspace: 0pt; mso-table-rspace: 0pt; -ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%; padding: 0; margin: 0 auto; max-width: 420px !important;"><tbody><tr><td valign="top" style="padding-right: 0;padding-left: 0;padding-top: 0;padding-bottom: 30px;text-align: left;mso-line-height-rule: exactly;-ms-text-size-adjust: 100%;-webkit-text-size-adjust: 100%;"><h2 style="display:block;margin:0;padding:0;font-size:18px;font-weight:300;color:#606060;font-family:'Lato', sans-serif;">Ciao Name Surname,</h2></td></tr></tbody></table></td></tr><tr><td><table align="center" border="0" cellpadding="0" cellspacing="0" width="100%" style="border-collapse: collapse; mso-table-lspace: 0pt; mso-table-rspace: 0pt; -ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%; padding: 0; margin: 0 auto; max-width: 420px !important;"><tbody><tr><td valign="top" style="padding-right: 0px;padding-left: 0px;padding-top: 0px;padding-bottom: 50px;text-align: left;mso-line-height-rule: exactly;-ms-text-size-adjust: 100%;-webkit-text-size-adjust: 100%;"><p style="font-size:18px;margin:0;padding:0;color:#000;font-weight:300;color:#606060;font-family:'Lato', sans-serif;line-height:1.5;">Name ha scritto una nuova recensione a <span class="highlight-text" style="color: #000;font-weight:400;">5 stelle</span> di <span class="highlight-text" style="color: #000;font-weight:400;">fattura24.com</span>:<br><br><span class="quoted-text" style="margin:0;font-style:italic;">Ottime integrazioni con le API, facile UX e nulla viene perso. Consiglio!</span></p></td></tr></tbody></table></td></tr><tr><td style="padding-top:0px; padding-right:0; padding-bottom:50px; padding-left:0;" valign="top" align="center"><table border="0" cellpadding="0" cellspacing="0" style="background-color: #1244EE; max-width: 420px !important; border-collapse: separate !important;" bgcolor="#1244EE"><tbody><tr><td align="center" valign="middle" style="font-family: Helvetica; font-size: 18px;"><a href="https://link.trustpilot.com/ls/click?params" id="cta-link" style="font-size:18px;font-family:'Lato', sans-serif;line-height: 100%;text-align: center;text-decoration: none;color: #FFFFFF;mso-line-height-rule: exactly;-ms-text-size-adjust: 100%;-webkit-text-size-adjust: 100%;font-weight:300;padding-top:15px; padding-right:25px; padding-bottom:15px; padding-left:25px;display:inline-block;" target="_self">Leggi la recensione e rispondi</a></td></tr></tbody></table></td></tr><tr><td valign="top" style="padding-right: 0px;padding-left: 0px;padding-top: 0;padding-bottom: {{bottomPadding}}px;text-align: left;mso-line-height-rule: exactly;-ms-text-size-adjust: 100%;-webkit-text-size-adjust: 100%;"><p style="font-size:14px;margin:0;padding:0;color:#000;font-weight:300;color:#606060;font-family:'Lato', sans-serif;line-height:1.5;">Oppure leggi la recensione sulla tua pagina profilo: <a href="https://link.trustpilot.com/ls/click?params"></a></p></td></tr></table><!--[if gte mso 9]></td></tr></table><![endif]--></td></tr><tr><td><!--[if gte mso 9]><table align='center' border='0' cellspacing='0' cellpadding='0' width='420' style='width:420px;'><tr><td align='center' valign='top' width='420' style='width:420px;'><![endif]--><table align="center" border="0" cellpadding="0" cellspacing="0" width="100%" style="border-collapse: collapse; mso-table-lspace: 0pt; mso-table-rspace: 0pt; -ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%; max-width: 500px !important;"><tbody><tr><td valign="top" style="mso-line-height-rule: exactly;-ms-text-size-adjust: 100%;-webkit-text-size-adjust: 100%;border-top: 0;border-bottom: 0;padding-top:0;padding-bottom: 0;"><table border="0" cellpadding="0" cellspacing="0" width="100%" style="min-width: 100%; max-width: 420px !important;"><tbody><tr><td style="min-width:100%;"><table border="0" cellpadding="0" cellspacing="0" width="100%" style="min-width: 100%; border-top: 1px solid #b1b1b1; max-width: 420px !important;"><tbody><tr><td><span></span></td></tr></tbody></table></td></tr></tbody></table><table align="center" width="100%" border="0" cellpadding="0" cellspacing="0" style="min-width: 100%; border-collapse: collapse; mso-table-lspace: 0pt; mso-table-rspace: 0pt; -ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%; margin-top: 20px; margin-left: 0; margin-bottom: 0; margin-right: 0; max-width: 420px !important;"><tbody><tr><td valign="top" style="padding-right: 0px;padding-left: 0px;padding-top: 0;padding-bottom: 5px;mso-line-height-rule: exactly;-ms-text-size-adjust: 100%;-webkit-text-size-adjust: 100%;text-align:center;"><p style="font-weight:700;line-height:1;padding:0;margin:0;font-size:12px;color:#606060;font-family:'Lato', sans-serif;">Trustpilot A/S</p></td></tr></tbody></table><table align="center" width="100%" border="0" cellpadding="0" cellspacing="0" style="min-width: 100%; border-collapse: collapse; mso-table-lspace: 0pt; mso-table-rspace: 0pt; -ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%; padding: 0; max-width: 420px !important;"><tbody><tr><td valign="top" style="padding-right: 0px;padding-left: 0px;padding-top: 0;padding-bottom: 0;mso-line-height-rule: exactly;-ms-text-size-adjust: 100%;-webkit-text-size-adjust: 100%;text-align:center;"><a style="text-decoration:none;margin:0;padding:0;font-size:12px;font-weight:300;color:#606060;font-family:'Lato', sans-serif;">Pilestraede 58, quinto piano, 1112 Copenhagen K</a></td></tr></tbody></table><table align="center" width="100%" border="0" cellpadding="0" cellspacing="0" style="min-width: 100%; border-collapse: collapse; mso-table-lspace: 0pt; mso-table-rspace: 0pt; -ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%; padding: 0; max-width: 420px !important;"><tbody><tr><td valign="top" style="padding-right: 0px;padding-left: 0px;padding-top: 0;padding-bottom: 0px;mso-line-height-rule: exactly;-ms-text-size-adjust: 100%;-webkit-text-size-adjust: 100%;text-align:center;"><p style="margin:0;padding:0;font-size:12px;font-weight:300;color:#606060;font-family:'Lato', sans-serif;">Numero d'identificazione della società: id</p></td></tr></tbody></table></td></tr></tbody></table><!--[if gte mso 9]></td></tr></table><![endif]--></td></tr><tr><td><table align="center" width="100%" border="0" cellpadding="0" cellspacing="0" style="min-width: 100%; border-collapse: collapse; mso-table-lspace: 0pt; mso-table-rspace: 0pt; -ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%; padding: 0; max-width: 420px !important;"><tbody><tr><td valign="top" style="padding-right: 0px;padding-left: 0px;padding-top:60px;padding-bottom: 20px;mso-line-height-rule: exactly;-ms-text-size-adjust: 100%;-webkit-text-size-adjust: 100%;text-align:center;"><p style="font-size:12px;font-weight:300;color:#606060;font-family:'Lato', sans-serif;margin:0;padding:0;">Per gestire le tue notifiche, vai su <a href="https://link.trustpilot.com/ls/click?params" style="color:#000;">Impostazioni account</a>.</p></td></tr></tbody></table></td></tr></table><img src="https://link.trustpilot.com/wf/open?params" alt="" width="1" height="1" border="0" style="height:1px !important;width:1px !important;border-width:0 !important;margin-top:0 !important;margin-bottom:0 !important;margin-right:0 !important;margin-left:0 !important;padding-top:0 !important;padding-bottom:0 !important;padding-right:0 !important;padding-left:0 !important;"/></body></html>`

text = sanitize(html, {
    allowedTags: [
        "address", "article", "aside", "footer", "header", "h1", "h2", "h3", "h4",
        "h5", "h6", "hgroup", "main", "nav", "section", "dd", "div",
        "dl", "dt", "figcaption", "figure", "hr", "li", "main", "ol", "p", "pre",
        "ul", "a", "abbr", "b", "bdi", "bdo", "br", "cite", "code", "data", "dfn",
        "em", "i", "kbd", "mark", "q", "rb", "rp", "rt", "rtc", "ruby", "s", "samp",
        "small", "span", "strong", "sub", "sup", "time", "u", "var", "wbr", "caption",
        "col", "colgroup", "table", "tbody", "td", "tfoot", "th", "thead", "tr", "img"
    ],
    transformTags: {
        'a': function(tagName, attribs) {
            console.log('tagName: ', tagName)
            if (tagName === 'a') return {
                tagName: 'a',
                attribs: {
                    target: '_blank',
                    href: attribs.href
                }
            };
        }
    }
})

It will throw the error:

              TypeError: Cannot read property 'replace' of undefined
               at naughtyHref (/path/node_modules/sanitize-html/index.js:619:17)
               at /path/node_modules/sanitize-html/index.js:326:19
               at /path/node_modules/sanitize-html/index.js:18:7
               at Array.forEach (<anonymous>)
               at each (/path/node_modules/sanitize-html/index.js:17:22)
               at Object.onopentag (/path/node_modules/sanitize-html/index.js:283:9)
               at Parser.onopentagend (/path/node_modules/htmlparser2/lib/Parser.js:175:86)
               at Tokenizer.stateBeforeAttributeName (/path/node_modules/htmlparser2/lib/Tokenizer.js:267:22)
               at Tokenizer.parse (/path/node_modules/htmlparser2/lib/Tokenizer.js:646:22)
               at Tokenizer.write (/path/node_modules/htmlparser2/lib/Tokenizer.js:123:14)   

Can you help me figure out the issue?

boutell commented 1 year ago

You can put your sample code between lines of three backticks to quote it as code for github.

tyzion commented 1 year ago

Sure thing!

Is this better?

boutell commented 1 year ago

Yes thanks. Your function does not always return a value. Undefined is not a legal value and leads to problems. You need to return something all the time.

tyzion commented 1 year ago

Thanks a lot! Even though I just changed the function and used the sanitize.simpleTransform(tag, attribs)