Forráskód Böngészése

Give a redirect exactly one leading slash, and not only at most one

The dispatcher kept the path of a to and cut its leading slashes down to
one.  A to of https:$host has the path $host, with no slash at all, and
the dispatcher kept it as it was.  A browser reads that as a path relative
to the page, but a client that parses it more loosely can read it as a
host.

Now the path gets one slash if it has none, as well as one slash if it has
several.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
troglodyne-bot 1 napja
szülő
commit
a88083467f
2 módosított fájl, 3 hozzáadás és 2 törlés
  1. 2 2
      lib/TCMS.pm
  2. 1 0
      t/TCMS.t

+ 2 - 2
lib/TCMS.pm

@@ -238,8 +238,8 @@ sub build_routes {
             $query->{tpsgi} = $tpsgi;
 
             # Only ever a path on this site, so that no link can send a visitor to
-            # another one.  One slash, because a browser reads two as a host.
-            $query->{to} = ( URI->new( $input->{to} )->path() || '/' ) =~ s{\A/+}{/}r if $input->{to};
+            # another one.  Exactly one slash, because a client can read two, or none, as a host.
+            $query->{to} = ( URI->new( $input->{to} )->path() || '/' ) =~ s{\A/*}{/}r if $input->{to};
 
             # Now that we have firmed up the actual routing, let's validate.
             return $tpsgi->forbidden($query) if exists $query->{dispatcher}{'x-tcms-auth'} && !$active_user;

+ 1 - 0
t/TCMS.t

@@ -127,6 +127,7 @@ subtest 'where a redirect may send you' => sub {
     is( $to->('https://bogus.test'),   '/',           'and another site with no path is the root, not the other site' );
     is( $to->('//bogus.test'),         '/',           'even without a scheme' );
     is( $to->('////bogus.test'),       '/bogus.test', 'and a path that starts with two slashes, which names a site, starts with one' );
+    is( $to->('https:bogus.test'),     '/bogus.test', 'and a path with no slash, which a client can read as a host, starts with one' );
 };
 
 subtest 'the scripts of a route' => sub {