Javascript 如何解析带有前导不可打印控制字符的URL?

Javascript 如何解析带有前导不可打印控制字符的URL?,javascript,perl,url,Javascript,Perl,Url,我将在的上下文中研究Perl(和)中的几个URL解析器。我想解决的问题是,在某些情况下,我希望能够剥离URL。例如,在过滤HTML时,我可能希望允许相对URL,但不允许JavaScript 我遇到了以下问题: #!/usr/bin/env perl use strict; use warnings; use feature qw( say ); use Mojo::URL (); my $js_url = 'javascript:alert(1);'; my $mojo = Mojo::

我将在的上下文中研究Perl(和)中的几个URL解析器。我想解决的问题是,在某些情况下,我希望能够剥离URL。例如,在过滤HTML时,我可能希望允许相对URL,但不允许JavaScript

我遇到了以下问题:

#!/usr/bin/env perl

use strict;
use warnings;
use feature qw( say );

use Mojo::URL ();

my $js_url = 'javascript:alert(1);';

my $mojo = Mojo::URL->new($js_url);
say 'scheme: ' . $mojo->scheme . " in $js_url";

for my $i ( 1 .. 8, 14 .. 31 ) {
    my $bad_url = "&#$i;" . $js_url;
    my $mojo    = Mojo::URL->new($bad_url);
    say $mojo->scheme ? 'scheme is ' . $mojo->scheme : 'no scheme found in ' . $bad_url;
}
这将产生以下输出:

scheme: javascript in javascript:alert(1);
no scheme found in javascript:alert(1);
no scheme found in javascript:alert(1);
no scheme found in javascript:alert(1);
no scheme found in javascript:alert(1);
no scheme found in javascript:alert(1);
no scheme found in javascript:alert(1);
no scheme found in javascript:alert(1);
no scheme found in javascript:alert(1);
no scheme found in javascript:alert(1);
no scheme found in javascript:alert(1);
no scheme found in javascript:alert(1);
no scheme found in javascript:alert(1);
no scheme found in javascript:alert(1);
no scheme found in javascript:alert(1);
no scheme found in javascript:alert(1);
no scheme found in javascript:alert(1);
no scheme found in javascript:alert(1);
no scheme found in javascript:alert(1);
no scheme found in javascript:alert(1);
no scheme found in javascript:alert(1);
no scheme found in javascript:alert(1);
no scheme found in javascript:alert(1);
no scheme found in javascript:alert(1);
no scheme found in javascript:alert(1);
no scheme found in javascript:alert(1);
no scheme found in javascript:alert(1);
在上面的URL中,没有找到该方案,我只能假设它是一个相对URL。但是,如果我在
href
标记中使用上述URL,则在单击时,Chrome、Firefox和Safari都会弹出一个JavaScript警报框:

<a href="&#1;javascript:alert(1);">1</a>
<a href="&#2;javascript:alert(1);">2</a>
<a href="&#3;javascript:alert(1);">3</a>
<a href="&#4;javascript:alert(1);">4</a>
<a href="&#5;javascript:alert(1);">5</a>
<a href="&#6;javascript:alert(1);">6</a>
<a href="&#7;javascript:alert(1);">7</a>
<a href="&#8;javascript:alert(1);">8</a>
<a href="&#14;javascript:alert(1);">14</a>
<a href="&#15;javascript:alert(1);">15</a>
<a href="&#16;javascript:alert(1);">16</a>
<a href="&#17;javascript:alert(1);">17</a>
<a href="&#18;javascript:alert(1);">18</a>
<a href="&#19;javascript:alert(1);">19</a>
<a href="&#20;javascript:alert(1);">20</a>
<a href="&#21;javascript:alert(1);">21</a>
<a href="&#22;javascript:alert(1);">22</a>
<a href="&#23;javascript:alert(1);">23</a>
<a href="&#24;javascript:alert(1);">24</a>
<a href="&#25;javascript:alert(1);">25</a>
<a href="&#26;javascript:alert(1);">26</a>
<a href="&#27;javascript:alert(1);">27</a>
<a href="&#28;javascript:alert(1);">28</a>
<a href="&#29;javascript:alert(1);">29</a>
<a href="&#30;javascript:alert(1);">30</a>
<a href="&#31;javascript:alert(1);">31</a>

我在示例中使用了
Mojo::URL
,但是
URI
具有相同的行为。我收集到的信息是,在这两种情况下,解析器都不会去除不可打印的控制字符,因此,不会识别URL中存在JavaScript。Web浏览器(有帮助吗?)认识到控件字符不可打印,并允许在单击时执行URL中的JavaScript


这是怎么回事?解析器和浏览器是否都正常工作?在解析URL之前,是否由我来去除不可打印的控制字符?

至少表明这些URL是“无效”的URL,不幸的是,似乎用户代理会清除它们。对于清理/剥离HTML,我想您应该遵循UAs实现的内容,而不是规范中所说的内容……除此之外,您将普通URL与HTML上下文中编码的URL混为一谈。您添加的字符(即
;
)不是不可打印的,但它们会在href中被解释为HTML编码的字符(即作为一个字符
\x01
),因为这是HTML上下文。如果您只是在Perl中使用它们而没有显式的HTML解码,那么它们将被逐字记录(
;
-4个字符)。@SteffenUllrich主要问题是HTML::Restrict应该能够处理用户提供的任何内容(恶意或其他内容)。在这种情况下,HTML编码的内容能够击败HTML::Restrict,因为URI找不到方案。我想要的是正确的方法和正确的地点来处理这个问题。也许在解析URL之前从URL中剥离HTML编码的字符?是引发此问题的原因。@SteffenUllrich我说不可打印,因为有问题的字符范围是ASCII控制字符。逐字逐句地说,是的,它们可以由Perl打印,但浏览器不会呈现它们。@oalders:规范在前面说“如果输入包含任何前导或尾随的C0控件或空格,则验证错误。”。基于中使用的上下文HTML::Restrict,我认为它不应该依赖URI来返回经过清理的数据,而应该将此类输入视为无效并将其删除。