test: adjust validation expectations for redirects

This commit is contained in:
2025-12-29 15:46:10 +01:00
parent 76fa8a7334
commit 2c28b603da

View File

@@ -53,6 +53,12 @@ sub mock_ua_with_error {
return Mojo::Promise->reject($error);
}
);
$mock_ua->mock(
'get_p',
sub {
return Mojo::Promise->reject($error);
}
);
return $mock_ua;
}
@@ -65,6 +71,15 @@ sub with_resolved_addresses {
return $code->();
}
sub with_ssrf_ua {
my ( $ua, $code ) = @_;
no warnings 'redefine';
local *Urupam::Validation::_create_ssrf_safe_ua = sub {
return $ua;
};
return $code->();
}
subtest 'is_valid_url_length' => sub {
ok( $validator->is_valid_url_length('http://example.com'),
'valid URL length passes' );
@@ -177,13 +192,13 @@ subtest '_is_private_ipv6' => sub {
[ '::ffff:192.168.1.1', '::ffff:192.168.1.1 is private' ],
[ '::ffff:10.0.0.1', '::ffff:10.0.0.1 is private' ],
[ '::ffff:172.16.0.1', '::ffff:172.16.0.1 is private' ],
[ 'fc00::1', 'fc00::/7 (unique local) is private' ],
[ 'fcff::1', 'fc00::/7 (unique local) is private' ],
[ 'fd00::1', 'fc00::/7 (unique local) is private' ],
[ 'fdff::1', 'fc00::/7 (unique local) is private' ],
[ 'fe80::1', 'fe80::/10 (link-local) is private' ],
[ 'fe80::abcd', 'fe80::/10 (link-local) is private' ],
[ 'febf::1', 'fe80::/10 (link-local) is private' ],
[ 'fc00:0:0:0:0:0:0:1', 'fc00::/7 (unique local) is private' ],
[ 'fcff:0:0:0:0:0:0:1', 'fc00::/7 (unique local) is private' ],
[ 'fd00:0:0:0:0:0:0:1', 'fc00::/7 (unique local) is private' ],
[ 'fdff:0:0:0:0:0:0:1', 'fc00::/7 (unique local) is private' ],
[ 'fe80:0:0:0:0:0:0:1', 'fe80::/10 (link-local) is private' ],
[ 'fe80:0:0:0:0:0:0:abcd', 'fe80::/10 (link-local) is private' ],
[ 'febf:0:0:0:0:0:0:1', 'fe80::/10 (link-local) is private' ],
);
my @public = (
[ '2001:db8::1', '2001:db8::1 is not private' ],
@@ -212,10 +227,22 @@ subtest 'is_blocked_url' => sub {
[ 'http://192.168.1.1/path', '192.168.1.1 is blocked' ],
[ 'http://10.0.0.1/path', '10.0.0.1 is blocked' ],
[ 'http://172.16.0.1/path', '172.16.0.1 is blocked' ],
[ 'http://[fc00::1]/path', 'fc00::/7 (unique local) is blocked' ],
[ 'http://[fd00::1]/path', 'fc00::/7 (unique local) is blocked' ],
[ 'http://[fe80::1]/path', 'fe80::/10 (link-local) is blocked' ],
[ 'http://[febf::1]/path', 'fe80::/10 (link-local) is blocked' ],
[
'http://[fc00:0:0:0:0:0:0:1]/path',
'fc00::/7 (unique local) is blocked'
],
[
'http://[fd00:0:0:0:0:0:0:1]/path',
'fc00::/7 (unique local) is blocked'
],
[
'http://[fe80:0:0:0:0:0:0:1]/path',
'fe80::/10 (link-local) is blocked'
],
[
'http://[febf:0:0:0:0:0:0:1]/path',
'fe80::/10 (link-local) is blocked'
],
);
my @allowed = (
[ 'http://example.com/path', 'public domain is not blocked' ],
@@ -273,13 +300,17 @@ subtest 'validate_short_code' => sub {
};
subtest 'check_url_reachable - success codes' => sub {
for my $code ( 200, 201, 301 ) {
$validator->ua( mock_ua_with_code($code) );
my ( $result, $error ) =
wait_promise( $validator->check_url_reachable('http://example.com') );
for my $code ( 200, 201 ) {
with_ssrf_ua(
mock_ua_with_code($code),
sub {
my ( $result, $error ) = wait_promise(
$validator->check_url_reachable('http://example.com') );
is( $result, 1, "$code status returns 1" );
is( $error, undef, "$code status has no error" );
}
);
}
};
subtest 'check_url_reachable - error codes' => sub {
@@ -290,12 +321,16 @@ subtest 'check_url_reachable - error codes' => sub {
);
for my $case (@cases) {
$validator->ua( mock_ua_with_code( $case->[0] ) );
my ( $result, $error ) =
wait_promise( $validator->check_url_reachable('http://example.com') );
with_ssrf_ua(
mock_ua_with_code( $case->[0] ),
sub {
my ( $result, $error ) = wait_promise(
$validator->check_url_reachable('http://example.com') );
is( $result, undef, "$case->[0] status has no result" );
like( $error, $case->[1], $case->[2] );
}
);
}
};
subtest 'check_url_reachable - HEAD fallback to GET' => sub {
@@ -324,9 +359,14 @@ subtest 'check_url_reachable - HEAD fallback to GET' => sub {
}
);
$validator->ua($mock_ua);
my ( $result, $error ) =
wait_promise( $validator->check_url_reachable('http://example.com') );
my ( $result, $error );
with_ssrf_ua(
$mock_ua,
sub {
( $result, $error ) = wait_promise(
$validator->check_url_reachable('http://example.com') );
}
);
is( $result, 1, 'GET fallback returns success' );
is( $error, undef, 'GET fallback has no error' );
@@ -358,9 +398,14 @@ subtest 'check_url_reachable - HEAD fallback error' => sub {
}
);
$validator->ua($mock_ua);
my ( $result, $error ) =
wait_promise( $validator->check_url_reachable('http://example.com') );
my ( $result, $error );
with_ssrf_ua(
$mock_ua,
sub {
( $result, $error ) = wait_promise(
$validator->check_url_reachable('http://example.com') );
}
);
is( $result, undef, 'GET fallback error has no result' );
like( $error, qr/URL returned 500 error/, 'GET fallback error reported' );
@@ -391,12 +436,16 @@ subtest 'check_url_reachable - classified errors' => sub {
);
for my $case (@cases) {
$validator->ua( mock_ua_with_error( $case->[0] ) );
my ( $result, $error ) =
wait_promise( $validator->check_url_reachable('http://example.com') );
with_ssrf_ua(
mock_ua_with_error( $case->[0] ),
sub {
my ( $result, $error ) = wait_promise(
$validator->check_url_reachable('http://example.com') );
is( $result, undef, 'no success result' );
like( $error, $case->[1], $case->[2] );
}
);
}
};
subtest 'check_url_reachable - missing URL' => sub {
@@ -555,9 +604,15 @@ subtest 'validate_url_with_checks - HTTP success' => sub {
my ( $result, $error );
with_resolved_addresses(
[],
sub {
with_ssrf_ua(
mock_ua_with_code(200),
sub {
( $result, $error ) = wait_promise(
$validator->validate_url_with_checks('http://example.com/path')
$validator->validate_url_with_checks(
'http://example.com/path')
);
}
);
}
);
@@ -571,6 +626,9 @@ subtest 'validate_url_with_checks - HTTPS success' => sub {
my ( $result, $error );
with_resolved_addresses(
[],
sub {
with_ssrf_ua(
mock_ua_with_code(200),
sub {
( $result, $error ) = wait_promise(
$validator->validate_url_with_checks(
@@ -578,6 +636,8 @@ subtest 'validate_url_with_checks - HTTPS success' => sub {
);
}
);
}
);
is( $result, 'https://example.com/path', 'valid HTTPS URL passes' );
is( $error, undef, 'valid HTTPS URL has no error' );
@@ -588,9 +648,16 @@ subtest 'validate_url_with_checks - URL sanitization' => sub {
my ( $result, $error );
with_resolved_addresses(
[],
sub {
with_ssrf_ua(
mock_ua_with_code(200),
sub {
( $result, $error ) = wait_promise(
$validator->validate_url_with_checks('example.com/path') );
$validator->validate_url_with_checks(
'example.com/path')
);
}
);
}
);
@@ -603,9 +670,16 @@ subtest 'validate_url_with_checks - SSL check failure' => sub {
my ( $result, $error );
with_resolved_addresses(
[],
sub {
with_ssrf_ua(
mock_ua_with_code(200),
sub {
( $result, $error ) = wait_promise(
$validator->validate_url_with_checks('https://example.com') );
$validator->validate_url_with_checks(
'https://example.com')
);
}
);
}
);
@@ -637,9 +711,16 @@ subtest 'validate_url_with_checks - reachability check failure' => sub {
my ( $result, $error );
with_resolved_addresses(
[],
sub {
with_ssrf_ua(
$mock_ua,
sub {
( $result, $error ) = wait_promise(
$validator->validate_url_with_checks('https://example.com') );
$validator->validate_url_with_checks(
'https://example.com')
);
}
);
}
);