Javascript 如何安全地从任意html中提取文本内容

Javascript 如何安全地从任意html中提取文本内容,javascript,html,content-security-policy,Javascript,Html,Content Security Policy,我有一些我无法控制的用户生成的html 我只想从这个html块中提取文本(textContent,innerText,无论什么),以显示在网站上 考虑到这些html内容可能包含诸如脚本标记、iframe、样式标记或其他类似的恶意代码,如何安全地获取文本 这是一个输入示例: <p style="text-align:center;"><em>whatever</em></p> <style>body { display: none } &

我有一些我无法控制的用户生成的html

我只想从这个html块中提取文本(
textContent
innerText
,无论什么),以显示在网站上

考虑到这些html内容可能包含诸如脚本标记、iframe、样式标记或其他类似的恶意代码,如何安全地获取文本

这是一个输入示例:

<p style="text-align:center;"><em>whatever</em></p>
<style>body { display: none } </style>

<p><em>Some more whatever</em></p>
<script>alert('lala')</script>
无论什么

正文{显示:无} 再来点什么都行

警报(“拉拉”) 这就是我所期待的:

随便

再来点什么都行

据我所知,解决方案不应该向DOM追加内容,因为这可能会增加XSS攻击的可能性。
使用白名单/黑名单很好,但并不理想,因为很难维护(想出)和保持更新。

如果使用
innerText
属性而不是
textContent
,那么任何标记的内容都不会被返回。

您可以使用
*:not()
选择器以获取所有元素并排除
脚本
元素

const-arbiryhtml=`

再来点什么都行

警惕(“拉拉”)`; 函数getTextFromHTML(任意HTML){ var a=document.createElement('div') a、 innerHTML=任意HTML; //在选择器字符串处排除'script'元素 return[…a.querySelectorAll('*:not(script)] //筛选没有“firstElementChild”的节点` .filter(({firstElementChild})=>!firstElementChild) //return`textContent` .map(({textContent})=>textContent) }
console.log(getTextFromHTML(arbitraryHTML))
解析字符串,确保其中没有不需要的东西,如
脚本
标记等,如果有,则以错误拒绝它。应该添加解析是出于考虑。不要信任客户端。让您的服务器来处理。为什么问题中的示例代码不是一个选项?预期的“恶意代码”将是一个字符串。@Teemu我删除了我的答案,因为我认为它听起来不适用于所有需要说明的不同编码。感谢您的洞察力,Teemu:)它确实返回了脚本内容。看起来很有希望!试图想出利用这种方法的方法。@enapupe“利用”是什么意思?如果
script
元素不打算包含在生成的
NodeList
中,则可以使用
:not()
伪类选择器将其排除。您最终想要确定和实现什么?因为这个html代码将来自用户,而我无法控制它,所以我想确保人们不能以任何方式利用它。最明显的是添加一个脚本标记,但是您也可以通过添加带有特定src或iframe的img标记来进行恶意操作。一个带有高级选择器的系统也可能会把事情搞砸(如果你把代码附加到dom中的话),我更喜欢一个解决方案,我不需要一直在排除列表中添加元素。正如我在前面的评论中提到的,
style
元素是另一个可以在任意html中找到的元素,如果实际目标是“在网站上显示”,它会弄乱文本内容(我认为)@enapupe。你可以使用
元素,从html字符串中删除元素是没有意义的,因为元素的
.value
是字符串“HTML元素表示多行纯文本编辑控件”,而不是可执行代码。