fix(caldav): disable redirects on the sync/write-back DAVClient (SSRF) (#2663)

validate_caldav_url resolves and vets the initial host, but caldav's
niquests session follows 3xx redirects by default, so a validated public
URL can be redirected at request time to loopback/link-local/private
space, re-opening the SSRF the host check closes. The existing redirect
guard only covered the settings test-connection path.

Add a shared _build_dav_client helper that pins the session to zero
redirects (any 3xx then raises instead of silently following an
attacker-chosen Location), and route both the pull (_sync_blocking) and
write-back (_writeback_blocking) paths through it. Mirrors the
follow_redirects=False already used on the test-connection path.

Tests exercise the real DAVClient request path (a 302 toward an internal
host is refused, the sink is never contacted; the PROPFIND is asserted to
reach the public server first so the check can't pass vacuously), confirm
the helper disables redirects on the installed client, guard against a
raw DAVClient creeping back in, cover mixed public/internal DNS results
in both orderings, and add the resolves-to-no-usable-records fail-closed
branch.
This commit is contained in:
Joeseph Grey
2026-06-06 22:05:24 -06:00
committed by GitHub
parent 95c2dca4b5
commit f78539ba15
5 changed files with 172 additions and 4 deletions
@@ -83,6 +83,9 @@ class _FakePrincipal:
class _FakeClient:
def __init__(self, url=None, username=None, password=None):
self.url = url
# Mirror the real DAVClient: _build_dav_client sets
# session.max_redirects = 0 right after construction.
self.session = types.SimpleNamespace(max_redirects=30)
def principal(self):
return _FakePrincipal()