"""Tests for SSRF protection in safe_source.validate_image_url.""" import pytest from fastapi import HTTPException from ledgrab.utils.safe_source import validate_image_url @pytest.mark.parametrize( "url", [ "http://127.0.0.1/", "http://127.0.0.1:8080/x.png", "http://[::1]/", "http://169.254.169.254/latest/meta-data/", "http://10.0.0.1/", "http://192.168.1.1/x.png", "http://172.16.0.5/", "http://0.0.0.0/", "http://224.0.0.1/", # multicast "ftp://example.com/", "file:///etc/passwd", "gopher://example.com/", "http:///no-host", ], ) def test_validate_image_url_rejects_dangerous_targets(url): with pytest.raises(HTTPException) as exc: validate_image_url(url) assert exc.value.status_code == 400 def test_validate_image_url_accepts_public(monkeypatch): """Accept a public host whose DNS resolves to a non-private IP.""" import ledgrab.utils.safe_source as ss def fake_getaddrinfo(host, _port): # Pretend example.com resolves to a public IP return [(0, 0, 0, "", ("93.184.216.34", 0))] monkeypatch.setattr(ss.socket, "getaddrinfo", fake_getaddrinfo) # Should not raise validate_image_url("https://example.com/image.png") def test_validate_image_url_blocks_dns_to_private(monkeypatch): """Hostname that resolves to a private IP must be rejected.""" import ledgrab.utils.safe_source as ss def fake_getaddrinfo(host, _port): return [(0, 0, 0, "", ("10.0.0.5", 0))] monkeypatch.setattr(ss.socket, "getaddrinfo", fake_getaddrinfo) with pytest.raises(HTTPException) as exc: validate_image_url("http://internal.example.com/") assert exc.value.status_code == 400