test_url_safety.py 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. """Unit tests for the shared SSRF-data primitives (#1333).
  2. These primitives are imported by both ``_spoolman_helpers.assert_safe_spoolman_url``
  3. and ``_oidc_helpers.assert_safe_public_https_url``. Test them in isolation
  4. so a future change to one consumer doesn't accidentally drift the data.
  5. """
  6. import ipaddress
  7. import pytest
  8. from backend.app.api.routes._url_safety import (
  9. CLOUD_METADATA_IPS,
  10. is_numeric_encoded_ip,
  11. unwrap_ipv4_mapped,
  12. )
  13. def test_cloud_metadata_set_contains_known_endpoints():
  14. # Both v4 and v6 IMDS endpoints, plus Alibaba's variant.
  15. assert ipaddress.ip_address("169.254.169.254") in CLOUD_METADATA_IPS
  16. assert ipaddress.ip_address("100.100.100.200") in CLOUD_METADATA_IPS
  17. assert ipaddress.ip_address("fd00:ec2::254") in CLOUD_METADATA_IPS
  18. def test_cloud_metadata_set_is_frozen():
  19. # frozenset is the right immutable container — protects against
  20. # accidental mutation in tests/imports.
  21. assert isinstance(CLOUD_METADATA_IPS, frozenset)
  22. @pytest.mark.parametrize(
  23. "candidate",
  24. [
  25. "2130706433", # decimal-encoded 127.0.0.1
  26. "0x7f000001", # hex-encoded 127.0.0.1
  27. "0xFFFFFFFF", # uppercase hex
  28. "0",
  29. "4294967295", # max uint32
  30. "0xa9.0xfe.0xa9.0xfe", # dotted hex
  31. "169.254.43518", # short form
  32. "0251.0376.0251.0376", # dotted octal
  33. "0169.254.169.254", # a leading zero
  34. ],
  35. )
  36. def test_numeric_encoded_forms_are_recognised(candidate):
  37. assert is_numeric_encoded_ip(candidate) is True
  38. @pytest.mark.parametrize(
  39. "candidate",
  40. [
  41. "127.0.0.1", # dotted-decimal — not "numeric-encoded"
  42. "example.com",
  43. "spoolman.lan",
  44. "::1",
  45. "localhost",
  46. "3dprinter.lan",
  47. "node-01",
  48. ],
  49. )
  50. def test_normal_forms_are_not_numeric_encoded(candidate):
  51. assert is_numeric_encoded_ip(candidate) is False
  52. def test_unwrap_ipv4_mapped_unwraps_mapped_address():
  53. mapped = ipaddress.ip_address("::ffff:127.0.0.1")
  54. result = unwrap_ipv4_mapped(mapped)
  55. assert result == ipaddress.ip_address("127.0.0.1")
  56. assert isinstance(result, ipaddress.IPv4Address)
  57. def test_unwrap_ipv4_mapped_passes_through_pure_ipv4():
  58. addr = ipaddress.ip_address("8.8.8.8")
  59. assert unwrap_ipv4_mapped(addr) is addr
  60. def test_unwrap_ipv4_mapped_passes_through_pure_ipv6():
  61. addr = ipaddress.ip_address("2001:db8::1")
  62. assert unwrap_ipv4_mapped(addr) is addr
  63. def test_unwrap_drops_a_zone_id():
  64. """Ignored on connect to an address that is not link-local: the address
  65. reached is the one without it."""
  66. result = unwrap_ipv4_mapped(ipaddress.ip_address("fd00:ec2::254%251"))
  67. assert result == ipaddress.ip_address("fd00:ec2::254")
  68. assert result in CLOUD_METADATA_IPS