| 1 | """ |
| 2 | test_xff_spoof_unit |
| 3 | =================== |
| 4 | Regression test for the X-Forwarded-For source-IP spoofing bug in the |
| 5 | registry rate limiter and beacon source_ip attribution. |
| 6 | |
| 7 | Background: _xff_client must return the RIGHTMOST XFF entry (appended by |
| 8 | the directly-connected trusted proxy, e.g. Caddy), never the leftmost. The |
| 9 | leftmost is attacker-controlled because a client may send any XFF header |
| 10 | and the proxy appends rather than replaces. Trusting the leftmost let an |
| 11 | attacker pick their rate-limit bucket and forge the source_ip written into |
| 12 | beacon events and the transparency log. |
| 13 | """ |
| 14 | |
| 15 | from __future__ import annotations |
| 16 | |
| 17 | import sys |
| 18 | from pathlib import Path |
| 19 | |
| 20 | ROOT = Path(__file__).resolve().parent.parent |
| 21 | sys.path.insert(0, str(ROOT)) |
| 22 | |
| 23 | from registry.server import _xff_client |
| 24 | |
| 25 | |
| 26 | def test_xff_ignores_spoofed_left_entries(): |
| 27 | assert _xff_client("1.2.3.4, 9.9.9.9") == "9.9.9.9" |
| 28 | assert _xff_client("fake, fake2, 203.0.113.7") == "203.0.113.7" |
| 29 | |
| 30 | |
| 31 | def test_xff_single_entry_is_returned(): |
| 32 | assert _xff_client("9.9.9.9") == "9.9.9.9" |
| 33 | |
| 34 | |
| 35 | def test_xff_whitespace_only_entries_dropped(): |
| 36 | assert _xff_client(" , , 9.9.9.9") == "9.9.9.9" |
| 37 | |
| 38 | |
| 39 | def test_xff_empty_returns_none(): |
| 40 | assert _xff_client("") is None |
| 41 | assert _xff_client(" ") is None |
| 42 | assert _xff_client(" , ") is None |