Skip to content

PYTHON-5814 Configurable DNS domain validation for SRV records - #2868

Open
sleepyStick wants to merge 26 commits into
mongodb:mainfrom
sleepyStick:PYTHON-5814
Open

PYTHON-5814 Configurable DNS domain validation for SRV records#2868
sleepyStick wants to merge 26 commits into
mongodb:mainfrom
sleepyStick:PYTHON-5814

Conversation

@sleepyStick

Copy link
Copy Markdown
Contributor

PYTHON-5814

Changes in this PR

  • add srvAllowedHostsSuffix param

Test Plan

Checklist

Checklist for Author

  • Did you update the changelog (if necessary)?
  • Is there test coverage?
  • Is any followup work tracked in a JIRA ticket? If so, add link(s).

Checklist for Reviewer

  • Does the title of the PR reference a JIRA Ticket?
  • Do you fully understand the implementation? (Would you be comfortable explaining how this code works to someone else?)
  • Is all relevant documentation (README or docstring) updated?

@codecov-commenter

codecov-commenter commented Jun 11, 2026

Copy link
Copy Markdown

@sleepyStick
sleepyStick marked this pull request as ready for review August 27, 2026 17:31
@sleepyStick
sleepyStick requested a review from a team as a code owner August 27, 2026 17:31
@sleepyStick
sleepyStick requested a lite review from Copilot and removed request for Copilot August 27, 2026 17:31
@sleepyStick
sleepyStick requested a review from NoahStapp August 27, 2026 17:31

@NoahStapp NoahStapp left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, just some documentation/clarity questions!

srv|SRV|initial-dns-seedlist-discovery|srv_seedlist)
cpjson initial-dns-seedlist-discovery/tests/ srv_seedlist
# srvAllowedHostsSuffix validation uses the bundled Public Suffix List.
cp_psl

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So this will resync every time there is a change to the Public Suffix List?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it syncs from the spec's copy of the PSL -- which is automatically updated once a month but could be manually triggered (in the specs repo)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(the actual PSL has like an avg of 3 changes per week which is far too much noise to always keep up to date)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And our automated weekly sync will pick up that monthly change in the spec repo?

Comment thread doc/changelog.rst Outdated

PyMongo 4.18 brings a number of changes including:

- Added the ``srvAllowedHostsSuffix`` URI option and :class:`~pymongo.mongo_client.MongoClient`

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We also need an AsyncMongoClient reference here and below.

Comment thread doc/changelog.rst Outdated
keyword argument. When connecting via ``mongodb+srv://``, this option overrides the default
requirement that SRV-returned hosts share the same parent domain as the seed hostname,
allowing hosts under a different domain suffix to be accepted. The suffix must not be a
public suffix (per the Public Suffix List). See the

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should the Public Suffix List be linked here?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lol that'd be a nice thing to do, wouldn't it! (I initially was like ppl can look it up if they need it, they know what to google now LOLOL) done!

Comment thread doc/changelog.rst Outdated
requirement that SRV-returned hosts share the same parent domain as the seed hostname,
allowing hosts under a different domain suffix to be accepted. The suffix must not be a
public suffix (per the Public Suffix List). See the
:class:`~pymongo.mongo_client.MongoClient` documentation for security considerations.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a blog post or non-API doc link we can add here for an example?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not at the moment, will reach out to docs team about this!

Comment thread pymongo/_psl.py
if domain in suffixes:
return True
parts = domain.split(".")
return len(parts) == 1 or (len(parts) > 1 and ".".join(parts[1:]) in wildcards)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add a short comment explaining this line? I'm not following how this results in a suffix being public or not.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i assume "this line" is the return line, and if so, done! lmk if the comment isn't clear tho

Copilot AI lite review requested due to automatic review settings August 27, 2026 19:06
@sleepyStick
sleepyStick requested a review from NoahStapp August 27, 2026 19:09

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds a new SRV-only configuration option, srvAllowedHostsSuffix, to make DNS domain validation for mongodb+srv:// connections configurable while still preventing overly-broad suffixes via Public Suffix List (PSL) checks.

Changes:

  • Adds srvAllowedHostsSuffix to URI parsing and to the (Async)MongoClient keyword/URI option plumbing through to SRV resolution.
  • Introduces a bundled PSL parser (pymongo/_psl.py) and uses it to reject srvAllowedHostsSuffix values that are public suffixes.
  • Adds SRV seedlist spec test fixtures and a connection-string invalid-URI case covering SRV-only enforcement.

Reviewed changes

Copilot reviewed 30 out of 31 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
test/test_dns.py Adds PSL parsing unit tests (sync suite).
test/asynchronous/test_dns.py Adds PSL parsing unit tests (async suite).
test/srv_seedlist/replica-set/srvAllowedHostsSuffix-without_dot_pass.json SRV seedlist fixture validating suffix matching without a leading dot.
test/srv_seedlist/replica-set/srvAllowedHostsSuffix-without_dot_fail.json SRV seedlist fixture validating mismatch failure without a leading dot.
test/srv_seedlist/replica-set/srvAllowedHostsSuffix-with_dot.json SRV seedlist fixture validating suffix matching with a leading dot.
test/srv_seedlist/replica-set/srvAllowedHostsSuffix-trailing-dot.json SRV seedlist fixture validating suffix normalization with trailing dot.
test/srv_seedlist/replica-set/srvAllowedHostsSuffix-tld-only.json SRV seedlist fixture rejecting TLD-only suffix.
test/srv_seedlist/replica-set/srvAllowedHostsSuffix-psl-public-suffix.json SRV seedlist fixture rejecting a PSL public suffix.
test/srv_seedlist/replica-set/srvAllowedHostsSuffix-psl-public-suffix-capitalized.json SRV seedlist fixture rejecting a capitalized PSL public suffix.
test/srv_seedlist/replica-set/srvAllowedHostsSuffix-psl-not-public-suffix.json SRV seedlist fixture accepting a non-public suffix.
test/srv_seedlist/replica-set/srvAllowedHostsSuffix-period-only.json SRV seedlist fixture rejecting a period-only suffix.
test/srv_seedlist/replica-set/srvAllowedHostsSuffix-mismatch.json SRV seedlist fixture rejecting a suffix that doesn’t match returned hosts.
test/srv_seedlist/replica-set/srvAllowedHostsSuffix-case-insensitive.json SRV seedlist fixture validating case-insensitive suffix matching.
test/connection_string/test/invalid-uris.json Adds invalid case for srvAllowedHostsSuffix used with non-SRV URIs.
pymongo/uri_parser_shared.py Allows the new option in URI option validation and enforces SRV-only usage.
pymongo/common.py Adds option validator entry for srvallowedhostssuffix.
pymongo/asynchronous/uri_parser.py Plumbs srvAllowedHostsSuffix into async SRV parsing and resolver construction.
pymongo/asynchronous/srv_resolver.py Implements suffix-based SRV host validation + PSL restriction (async).
pymongo/asynchronous/settings.py Stores/exposes srv_allowed_hosts_suffix in async topology settings.
pymongo/asynchronous/monitor.py Passes srv_allowed_hosts_suffix into SRV resolution in the async monitor.
pymongo/asynchronous/mongo_client.py Adds keyword/docs + wires option into TopologySettings construction (async).
pymongo/synchronous/uri_parser.py Plumbs srvAllowedHostsSuffix into sync SRV parsing and resolver construction.
pymongo/synchronous/srv_resolver.py Implements suffix-based SRV host validation + PSL restriction (sync).
pymongo/synchronous/settings.py Stores/exposes srv_allowed_hosts_suffix in sync topology settings.
pymongo/synchronous/monitor.py Passes srv_allowed_hosts_suffix into SRV resolution in the sync monitor.
pymongo/synchronous/mongo_client.py Adds keyword/docs + wires option into TopologySettings construction (sync).
pymongo/_psl.py Adds PSL loading/parsing utility used to validate srvAllowedHostsSuffix.
doc/changelog.rst Documents the new option and its security implications.
.pre-commit-config.yaml Excludes the PSL data file from codespell.
.evergreen/resync-specs.sh Adds logic to pull PSL data from the specs repo during resync.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread pymongo/uri_parser_shared.py
Comment thread pymongo/_psl.py
Comment on lines +41 to +49
return suffixes, wildcards, exceptions


def is_public_suffix(domain: str) -> bool:
"""Return True if domain is a public suffix per the bundled Public Suffix List."""
global _PUBLIC_SUFFIXES # noqa: PLW0603
if _PUBLIC_SUFFIXES is None:
_PUBLIC_SUFFIXES = _load_public_suffixes()
suffixes, wildcards, exceptions = _PUBLIC_SUFFIXES

@sleepyStick sleepyStick Aug 27, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

on the other hand, it feels silly to load the list if the user might not use the list,,?
idk i can be convinced either way,, no strong opinions on this,,

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

@NoahStapp NoahStapp left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants