编辑 2 经过更多研究,这实际上是由 OP 提到的浏览器的 XSS 检测引起的(与任何 WordPress 特定的功能相反)。仅当您单击 WordPress 中的 Preview 按钮时才会出现问题,并且仅在初始页面加载时出现。显然 WordPress 会在请求标头中发送一些 HTML,这会触发浏览器中的 XSS 功能。如果加载预览,然后刷新页面,XSS 问题就会消失,javascript: 链接会在保存时显示。查看实际站点时,发布页面后,从未遇到过此 XSS 问题。
编辑 经过一些更深入的研究(与@gnarf 合作),事实证明,实际问题归结为WordPress 在其预览功能中处理javascript: 链接的方式。似乎 WordPress 有一些自定义 Javascript 可以运行并将所有 javascript: 链接转换为 javascript:void(0) 链接(剥离任何自定义代码),但前提是您正在预览页面。发布页面后,javascript: 链接正确呈现。
原始帖子(描述了如何阻止 WordPress 在将帖子保存为非管理员用户时删除 javascript: 链接,我认为这可能是最初的问题)
看起来 WordPress 去除了 content_save_pre 过滤器中的 HTML。具体来说就是调用wp-includes\kses.php中的wp_kses_bad_protocol方法:
/**
* Sanitize string from bad protocols.
*
* This function removes all non-allowed protocols from the beginning of
* $string. It ignores whitespace and the case of the letters, and it does
* understand HTML entities. It does its work in a while loop, so it won't be
* fooled by a string like "javascript:javascript:alert(57)".
*
* @since 1.0.0
*
* @param string $string Content to filter bad protocols from
* @param array $allowed_protocols Allowed protocols to keep
* @return string Filtered content
*/
function wp_kses_bad_protocol($string, $allowed_protocols) {
$string = wp_kses_no_null($string);
$iterations = 0;
do {
$original_string = $string;
$string = wp_kses_bad_protocol_once($string, $allowed_protocols);
} while ( $original_string != $string && ++$iterations < 6 );
if ( $original_string != $string )
return '';
return $string;
}
$allowed_protocols 参数通过wp_allowed_protocols() 方法检索,该方法将kses_allowed_protocols 过滤器应用于协议列表。
有了这些信息,您应该能够绑定到kses_allowed_protocols 过滤器以将javascript 添加为有效的过滤器(请注意,这当然会引发安全问题):
add_filter( 'kses_allowed_protocols', function ($protocols) {
$protocols[] = 'javascript';
return $protocols;
});
增强此方法安全性的一种方法是添加对特定用户或特定角色的检查(默认情况下,此过滤器看起来实际上不在管理帐户上运行,所以在允许javascript 协议之前,您可以以管理员身份使用javascript: 链接到您的心脏内容。