Skip to content

Instantly share code, notes, and snippets.

/xss_escape.diff Secret

Created November 11, 2014 17:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save anonymous/6090186fe3c79c7cc7d4 to your computer and use it in GitHub Desktop.
Save anonymous/6090186fe3c79c7cc7d4 to your computer and use it in GitHub Desktop.
diff --git a/lib/Mojo/Template.pm b/lib/Mojo/Template.pm
index e025c25..78d4407 100644
--- a/lib/Mojo/Template.pm
+++ b/lib/Mojo/Template.pm
@@ -14,7 +14,7 @@ has capture_end => 'end';
has capture_start => 'begin';
has comment_mark => '#';
has encoding => 'UTF-8';
-has escape => sub { \&Mojo::Util::xml_escape };
+has escape => sub { \&Mojo::Util::xss_escape };
has [qw(escape_mark expression_mark trim_mark)] => '=';
has [qw(line_start replace_mark)] => '%';
has name => 'template';
@@ -264,11 +264,7 @@ sub _wrap {
my ($self, $code) = @_;
# Escape function
- my $escape = $self->escape;
- monkey_patch $self->namespace, _escape => sub {
- no warnings 'uninitialized';
- ref $_[0] eq 'Mojo::ByteStream' ? $_[0] : $escape->("$_[0]");
- };
+ monkey_patch $self->namespace, '_escape', $self->escape;
# Wrap lines
my $num = () = $code =~ /\n/g;
@@ -493,7 +489,7 @@ Encoding used for template files.
$mt = $mt->escape(sub {...});
A callback used to escape the results of escaped expressions, defaults to
-L<Mojo::Util/"xml_escape">.
+L<Mojo::Util/"xss_escape">.
$mt->escape(sub {
my $str = shift;
diff --git a/lib/Mojo/Util.pm b/lib/Mojo/Util.pm
index c168f38..4128fc7 100644
--- a/lib/Mojo/Util.pm
+++ b/lib/Mojo/Util.pm
@@ -58,7 +58,7 @@ our @EXPORT_OK = (
qw(md5_sum monkey_patch punycode_decode punycode_encode quote),
qw(secure_compare sha1_bytes sha1_sum slurp split_header spurt squish),
qw(steady_time tablify trim unindent unquote url_escape url_unescape),
- qw(xml_escape xor_encode)
+ qw(xml_escape xor_encode xss_escape)
);
sub b64_decode { decode_base64($_[0]) }
@@ -352,6 +352,11 @@ sub xor_encode {
return $output .= $buffer ^ substr($key, 0, length $buffer, '');
}
+sub xss_escape {
+ no warnings 'uninitialized';
+ ref $_[0] eq 'Mojo::ByteStream' ? $_[0] : xml_escape("$_[0]");
+}
+
sub _adapt {
my ($delta, $numpoints, $firsttime) = @_;
use integer;
@@ -719,6 +724,12 @@ Escape unsafe characters C<&>, C<E<lt>>, C<E<gt>>, C<"> and
XOR encode string with variable length key.
+=head2 xss_escape
+
+ my $output = xml_escape $input;
+
+Same as L</"xml_escape">, but does not escape L<Mojo::ByteStream> objects.
+
=head1 SEE ALSO
L<Mojolicious>, L<Mojolicious::Guides>, L<http://mojolicio.us>.
diff --git a/lib/Mojolicious/Plugin/TagHelpers.pm b/lib/Mojolicious/Plugin/TagHe
index 6ef43ac..7bbba7f 100644
--- a/lib/Mojolicious/Plugin/TagHelpers.pm
+++ b/lib/Mojolicious/Plugin/TagHelpers.pm
@@ -2,7 +2,7 @@ package Mojolicious::Plugin::TagHelpers;
use Mojo::Base 'Mojolicious::Plugin';
use Mojo::ByteStream;
-use Mojo::Util 'xml_escape';
+use Mojo::Util 'xss_escape';
use Scalar::Util 'blessed';
sub register {
@@ -140,7 +140,7 @@ sub _option {
$attrs{selected} = 'selected' if exists $values->{$pair->[1]};
%attrs = (%attrs, @$pair[2 .. $#$pair]);
- return _tag('option', %attrs, sub { xml_escape $pair->[0] });
+ return _tag('option', %attrs, $pair->[0]);
}
sub _password_field {
@@ -212,13 +212,13 @@ sub _tag {
}
delete $attrs{data};
}
- $tag .= qq{ $_="} . xml_escape($attrs{$_} // '') . '"' for sort keys %attrs;
+ $tag .= qq{ $_="} . xss_escape($attrs{$_} // '') . '"' for sort keys %attrs;
# Empty element
unless ($cb || defined $content) { $tag .= ' />' }
# End tag
- else { $tag .= '>' . ($cb ? $cb->() : xml_escape($content)) . "</$name>" }
+ else { $tag .= '>' . ($cb ? $cb->() : xss_escape $content) . "</$name>" }
# Prevent escaping
return Mojo::ByteStream->new($tag);
@@ -234,11 +234,9 @@ sub _tag_with_error {
sub _text_area {
my ($c, $name) = (shift, shift);
- # Make sure content is wrapped
- my $cb = ref $_[-1] eq 'CODE' ? pop : sub {''};
+ my $cb = ref $_[-1] eq 'CODE' ? pop : '';
my $content = @_ % 2 ? shift : undef;
- $cb = sub { xml_escape $content }
- if defined($content = $c->param($name) // $content);
+ $cb = $content if defined($content = $c->param($name) // $content);
return _validation($c, $name, 'textarea', @_, name => $name, $cb);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment