mirror of
https://github.com/alexta69/metube.git
synced 2026-07-23 13:22:48 +00:00
fix: fail closed when an SSRF-guarded host cannot be resolved
validate_url() previously returned None (allow) on socket.gaierror, so a host that failed to resolve at check time was passed straight to yt-dlp. A host we cannot resolve is a host we cannot verify as non-internal, and it may resolve differently when yt-dlp fetches it. Reject it instead. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -93,9 +93,10 @@ class AddressResolutionTests(unittest.TestCase):
|
|||||||
# If any resolved address is internal, reject the whole URL.
|
# If any resolved address is internal, reject the whole URL.
|
||||||
self.assertIsNotNone(self._validate_with_addrs("http://mixed/x", "142.250.1.1", "127.0.0.1"))
|
self.assertIsNotNone(self._validate_with_addrs("http://mixed/x", "142.250.1.1", "127.0.0.1"))
|
||||||
|
|
||||||
def test_resolution_failure_defers_to_ytdlp(self):
|
def test_resolution_failure_is_rejected(self):
|
||||||
|
# Fail closed: an unresolvable host cannot be verified as non-internal.
|
||||||
with mock.patch("url_guard.socket.getaddrinfo", side_effect=socket.gaierror):
|
with mock.patch("url_guard.socket.getaddrinfo", side_effect=socket.gaierror):
|
||||||
self.assertIsNone(validate_url("http://does-not-resolve.example/x"))
|
self.assertIsNotNone(validate_url("http://does-not-resolve.example/x"))
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|||||||
+4
-2
@@ -76,8 +76,10 @@ def validate_url(url: str) -> str | None:
|
|||||||
try:
|
try:
|
||||||
addrinfo = socket.getaddrinfo(hostname, parts.port, proto=socket.IPPROTO_TCP)
|
addrinfo = socket.getaddrinfo(hostname, parts.port, proto=socket.IPPROTO_TCP)
|
||||||
except socket.gaierror:
|
except socket.gaierror:
|
||||||
# Let yt-dlp surface a normal resolution error rather than masking it.
|
# Fail closed: a host we cannot resolve is a host we cannot verify as
|
||||||
return None
|
# non-internal, so refuse it rather than letting the download proceed
|
||||||
|
# to a target that may resolve differently at fetch time.
|
||||||
|
return f'Could not resolve host "{hostname}"'
|
||||||
except (UnicodeError, ValueError):
|
except (UnicodeError, ValueError):
|
||||||
return f'Invalid host "{hostname}"'
|
return f'Invalid host "{hostname}"'
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user