从html中删除标签方法的安全性问题

Security concern over method of removing tags from html

本文关键字:安全性 问题 方法 标签 html 删除      更新时间:2023-09-26

我正在使用findAndReplaceDOMText,这是一个库,可以让您包装跨多个标记的文本。

考虑将o b包装在以下html中的<em>标签中:

<p>foo <span>bar</span></p>

生成以下内容:

<p>fo<em>o </em><span><em>b</em>ar</span></p>

这个效果很好。我担心的是,我的删除这些标签的策略可能会打开代码注入的可能性。下面的代码的工作,我只是担心潜在的代码注入机会,特别是因为我在一个chrome扩展工作,所以目标页面的HTML可能是畸形的。

import $ from 'jquery'
export default function clearMarks() {
  $(".deepSearch-highlight").parent().each(function() {
    const contents = []
    const $parent = $(this)
    $parent.contents().each(function() {
      const $node = $(this)
      let html
      if ($node.hasClass("deepSearch-highlight")) {
        html = $node.html()
      }
      else if (this.nodeName === "#text") {
        html = this.data
      }
      else {
        html = this.outerHTML
      }
      contents.push(html)
    })
    $parent.html(contents.join(""))
  })
}

我的目标是恢复html到完全它是什么之前,它是用findAndReplaceDOMText转换。在"附加信息"一节中,你可以看到一个更简单的clearMarks函数如何导致文本节点数量的变化。

我的策略是否有我遗漏的安全漏洞?有没有更安全/更优雅/更好的方法来实现我的目标?


附加信息:

  • 我正在使用findAndReplaceDOMText选项preset: "prose",其中:

    忽略非文本元素(例如<script>, <svg>, <optgroup>, '等)

  • 作为题外话,更简单的$(this).replaceWith($(this).html())会导致文本节点数量的爆炸式增长。在上面的示例中,我们将得到:<p>"fo""o "<span>"b""ar"</span></p>(其中文本节点用"表示)。如果你尝试重新使用findAndReplaceDOMText,除了通常很臭之外,还会导致问题。

  • 插入的span元素有一个.deepSearch-highlight类(与上面的例子相反,在em中包装文本。参见下面的完整代码。

.

import $ from "jquery"
import findAndReplaceDomText from "findandreplacedomtext"
import buildRegex from "../../shared/buildRegex"
import scrollToElement from "./scrollToElement"

export default function search(queryParams) {
  const regex = buildRegex(queryParams)
  findAndReplaceDomText($('body')[0], {
    find: regex,
    replace: createHighlight,
    preset: "prose",
    filterElements,
  })
  scrollToElement($(".deepSearch-current-highlight"))
}
function createHighlight(portion, match) {
  var wrapped = document.createElement("span")
  var wrappedClasses = "deepSearch-highlight"
  if (match.index === 0) {
    wrappedClasses += " deepSearch-current-highlight"
  }
  wrapped.setAttribute("class", wrappedClasses)
  wrapped.setAttribute("data-highlight-index", match.index)
  wrapped.appendChild(document.createTextNode(portion.text))
  return wrapped
}
function filterElements(elem) {
  const $elem = $(elem)
  return $elem.is(":visible") && !$elem.attr("aria-hidden")
}

如果您只想删除元素并保留其文本子元素,则不要处理HTML。您应该使用纯DOM api来移动文本和元素节点。使用HTML解析器充其量只能提供次优性能,最坏的情况下还会产生安全漏洞。

说句题外话,简单得多的$(this). replacewith ($(this).html())会导致文本节点数量激增。

这可以通过对祖先应用Node.normalize()来解决。