typo3/html-sanitizer

HTML 清理器,旨在基于显式允许的标签、属性和值提供 XSS 安全的标记。

v2.2.0 2024-07-12 15:52 UTC

README

tests

TYPO3 HTML 清理器

ℹ️ 常见的 HTML 标签和属性,如 \TYPO3\HtmlSanitizer\Builder\CommonBuilder 中给出的,仍可能进行调整、扩展或重新排列,以适应更具体的构建器。

摘要

typo3/html-sanitizer 包旨在成为一个独立的组件,可以被任何基于 PHP 的项目或库使用。尽管它是在 TYPO3 命名空间中发布的,但它对 TYPO3 CMS 的具体细节是中立的。

  • \TYPO3\HtmlSanitizer\Behavior 包含了特定过程的声明性设置,用于清理 HTML。
  • \TYPO3\HtmlSanitizer\Visitor\VisitorInterface(同时可以存在多个不同的访客)根据声明的 Behavior 实际上执行工作。访客可以修改节点或将它们标记为删除。
  • \TYPO3\HtmlSanitizer\Sanitizer 可以被认为是工作实例,调用访客、解析和序列化 HTML。一般来说,这个实例不包含处理特定节点、属性或值的大量逻辑。
  • \TYPO3\HtmlSanitizer\Builder\BuilderInterface 可以用来创建多个不同的构建器实例——在“预设”的意义上——这些实例结合了声明特定的 Behavior、初始化 VisitorInterface 实例,并最终返回一个可使用的 Sanitizer 实例。

安装

composer req typo3/html-sanitizer

示例 & API

<?php
use TYPO3\HtmlSanitizer\Behavior;
use TYPO3\HtmlSanitizer\Behavior\NodeInterface;
use TYPO3\HtmlSanitizer\Sanitizer;
use TYPO3\HtmlSanitizer\Visitor\CommonVisitor;

require_once 'vendor/autoload.php';

$commonAttrs = [
    new Behavior\Attr('id'),
    new Behavior\Attr('class'),
    new Behavior\Attr('data-', Behavior\Attr::NAME_PREFIX),
];
$hrefAttr = (new Behavior\Attr('href'))
    ->addValues(new Behavior\RegExpAttrValue('#^https?://#'));

// attention: only `Behavior` implementation uses immutability
// (invoking `withFlags()` or `withTags()` returns new instance)
$behavior = (new Behavior())
    ->withFlags(Behavior::ENCODE_INVALID_TAG | Behavior::ENCODE_INVALID_COMMENT)
    ->withoutNodes(new Behavior\Comment())
    ->withNodes(new Behavior\CdataSection())
    ->withTags(
        (new Behavior\Tag('div', Behavior\Tag::ALLOW_CHILDREN))
            ->addAttrs(...$commonAttrs),
        (new Behavior\Tag('a', Behavior\Tag::ALLOW_CHILDREN))
            ->addAttrs(...$commonAttrs)
            ->addAttrs($hrefAttr->withFlags(Behavior\Attr::MANDATORY)),
        (new Behavior\Tag('br'))
    )
    ->withNodes(
        (new Behavior\NodeHandler(
            new Behavior\Tag('typo3'),
            new Behavior\Handler\ClosureHandler(
                static function (NodeInterface $node, ?DOMNode $domNode): ?DOMNode {
                    return $domNode === null
                        ? null
                        : new DOMText(sprintf('%s says: "%s"',
                            strtoupper($domNode->nodeName),
                            $domNode->textContent
                        ));
                }
            )
        ))
    );

$visitors = [new CommonVisitor($behavior)];
$sanitizer = new Sanitizer($behavior, ...$visitors);

$html = <<< EOH
<div id="main">
    <typo3>Inspiring People To Share</typo3>
    <!-- will be encoded, due to Behavior::ENCODE_INVALID_COMMENT -->
    <a class="no-href">invalidated, due to missing mandatory `href` attr</a>
    <a href="https://typo3.org/" data-type="url" wrong-attr="is-removed">TYPO3</a><br>
    (the <span>SPAN, SPAN, SPAN</span> tag shall be encoded to HTML entities)
</div>
EOH;

echo $sanitizer->sanitize($html);

将产生以下清理后的输出

<div id="main">
    TYPO3 says: "Inspiring People To Share"
    &lt;!-- will be encoded, due to Behavior::ENCODE_INVALID_COMMENT --&gt;
    &lt;a class="no-href"&gt;invalidated, due to missing mandatory `href` attr&lt;/a&gt;
    <a href="https://typo3.org/" data-type="url">TYPO3</a><br>
    (the &lt;span&gt;SPAN, SPAN, SPAN&lt;/span&gt; tag shall be encoded to HTML entities)
</div>

ℹ️ 更改

  • v2.1.0 以来,由于向后兼容的原因,新引入的节点 Behavior\CommentBehavior\CdataSection 默认启用,例如,使用 $behavior->withoutNodes(new Behavior\Comment()) 来删除它们(此包的后续版本将不再有此回退)
  • v2.1.0 以来,建议在创建 \TYPO3\HtmlSanitizer\Sanitizer 的新实例时提供 \TYPO3\HtmlSanitizer\Behavior,例如 new Sanitizer($behavior, ...$visitors)

有关所有更改的更多详细信息,请参阅 UPGRADING.md

Behavior 标志

  • Behavior::ENCODE_INVALID_TAG 保留无效的标签,但“解除武装”它们(见示例中的 <span>
  • Behavior::ENCODE_INVALID_ATTR 保留无效的属性,但“解除武装”整个(!)标签
  • Behavior::ENCODE_INVALID_COMMENT 通过完全编码意外 HTML 注释来“解除武装”它们
  • Behavior::ENCODE_INVALID_CDATA_SECTION 通过完全编码意外的 HTML CDATA 区段来“解除武装”它们
  • Behavior::REMOVE_UNEXPECTED_CHILDREN 删除没有显式使用 Tag::ALLOW_CHILDREN 创建的 Tag 实体的子代
  • Behavior::ALLOW_CUSTOM_ELEMENTS 允许使用自定义元素(带有连字符 -)——然而,建议显式命名所有已知和允许的标签,并避免使用此标志

许可证

一般来说,TYPO3 核心在 GNU 通用公共许可证版本 2 或任何更高版本下发布(GPL-2.0-or-later)。为了避免许可问题和不兼容性,此包采用 MIT 许可证。如果您复制或修改源代码,不需要提供信誉,但非常感谢。

本地测试

Composer项目oliverhader/html-sanitizer-demo提供了一个本地开发服务器,以简化对可能存在XSS漏洞的payload的手动测试。

安全联系方式

如果在TYPO3项目或特定此包中发现额外的安全问题,请与TYPO3安全团队联系,或直接通过GitHub报告漏洞