From ebcfe577bc3ff76db37ca20ee64b3c96094d8cf5 Mon Sep 17 00:00:00 2001 From: Alex Shnitman Date: Mon, 20 Jul 2026 23:45:08 +0300 Subject: [PATCH] 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 --- app/tests/test_url_guard.py | 5 +++-- app/url_guard.py | 6 ++++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/app/tests/test_url_guard.py b/app/tests/test_url_guard.py index 1808f3e..3cd1460 100644 --- a/app/tests/test_url_guard.py +++ b/app/tests/test_url_guard.py @@ -93,9 +93,10 @@ class AddressResolutionTests(unittest.TestCase): # 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")) - 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): - self.assertIsNone(validate_url("http://does-not-resolve.example/x")) + self.assertIsNotNone(validate_url("http://does-not-resolve.example/x")) if __name__ == "__main__": diff --git a/app/url_guard.py b/app/url_guard.py index 9d5adc7..e75ec0b 100644 --- a/app/url_guard.py +++ b/app/url_guard.py @@ -76,8 +76,10 @@ def validate_url(url: str) -> str | None: try: addrinfo = socket.getaddrinfo(hostname, parts.port, proto=socket.IPPROTO_TCP) except socket.gaierror: - # Let yt-dlp surface a normal resolution error rather than masking it. - return None + # Fail closed: a host we cannot resolve is a host we cannot verify as + # 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): return f'Invalid host "{hostname}"'