From 8c7bc699072c3c3764d37df8666af0d1732b0ae5 Mon Sep 17 00:00:00 2001 From: Iris Date: Thu, 11 Jun 2026 14:31:41 -0700 Subject: [PATCH 01/14] add srvAllowedHostsSuffix --- .../initial-dns-seedlist-discovery.md | 19 +++++++++++++++---- .../srvAllowedHostsSuffix-mismatch.json | 5 +++++ .../srvAllowedHostsSuffix-mismatch.yml | 4 ++++ .../srvAllowedHostsSuffix-with_dot.json | 11 +++++++++++ .../srvAllowedHostsSuffix-with_dot.yml | 7 +++++++ ...rvAllowedHostsSuffix-without_dot_fail.json | 5 +++++ ...srvAllowedHostsSuffix-without_dot_fail.yml | 3 +++ ...rvAllowedHostsSuffix-without_dot_pass.json | 11 +++++++++++ ...srvAllowedHostsSuffix-without_dot_pass.yml | 7 +++++++ source/uri-options/uri-options.md | 7 +++++-- 10 files changed, 73 insertions(+), 6 deletions(-) create mode 100644 source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-mismatch.json create mode 100644 source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-mismatch.yml create mode 100644 source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-with_dot.json create mode 100644 source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-with_dot.yml create mode 100644 source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-without_dot_fail.json create mode 100644 source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-without_dot_fail.yml create mode 100644 source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-without_dot_pass.json create mode 100644 source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-without_dot_pass.yml diff --git a/source/initial-dns-seedlist-discovery/initial-dns-seedlist-discovery.md b/source/initial-dns-seedlist-discovery/initial-dns-seedlist-discovery.md index 92d4de9e77..7363034088 100644 --- a/source/initial-dns-seedlist-discovery/initial-dns-seedlist-discovery.md +++ b/source/initial-dns-seedlist-discovery/initial-dns-seedlist-discovery.md @@ -37,7 +37,8 @@ mongodb+srv://{hostname}/{options} `{options}` refers to the optional elements from the [Connection String](../connection-string/connection-string-spec.md) specification following the `Host Information`. This includes the `Auth database` and `Connection Options`. -For the purposes of this document, `{hostname}` will be divided using the following terminology. If an SRV `{hostname}` +For the purposes of this document, `{hostname}` will be divided using the following terminology. If +`srvAllowedHostsSuffix` has been configured, then that will act as the `{domainname}`. Otherwise, if an SRV `{hostname}` has: 1. Three or more `.` separated parts, then the left-most part is the `{subdomain}` and the remaining portion is the @@ -65,6 +66,14 @@ Only `{domainname}` is used during SRV record verification and `{subdomain}` is ### MongoClient Configuration +#### srvAllowedHostsSuffix + +This option is used to validate hosts. If present, its value MUST be treated as the domain for DNS validation. For +example, `srvAllowedHostsSuffix=.mydomain.net`. If the value does not begin with a `.`, for example, +`srvAllowedHostsSuffix=mydomain.net`, the `.` MUST be automatically prepended prior to validation. If this option is not +present, the domain MUST be inferred from the hostname. This option MUST only be configurable at the level of a +`MongoClient`. + #### srvMaxHosts This option is used to limit the number of mongos connections that may be created for sharded topologies. This option @@ -84,9 +93,9 @@ requires a string value and defaults to "mongodb". This option MUST only be conf #### URI Validation -The driver MUST report an error if either the `srvServiceName` or `srvMaxHosts` URI options are specified with a non-SRV -URI (i.e. scheme other than `mongodb+srv`). The driver MUST allow specifying the `srvServiceName` and `srvMaxHosts` URI -options with an SRV URI (i.e. `mongodb+srv` scheme). +The driver MUST report an error if any of `srvServiceName`, `srvMaxHosts`, or `srvAllowedHostsSuffix` URI options are +specified with a non-SRV URI (i.e. scheme other than `mongodb+srv`). The driver MUST allow specifying the +`srvServiceName`, `srvMaxHosts`, and `srvAllowedHostsSuffix` URI options with an SRV URI (i.e. `mongodb+srv` scheme). If `srvMaxHosts` is a positive integer, the driver MUST throw an error in the following cases: @@ -283,6 +292,8 @@ In the future we could consider using the priority and weight fields of the SRV ## ChangeLog +- 2026-06-08: Add `srvAllowedHostsSuffix` MongoClient option. + - 2024-09-24: Removed requirement for URI to have three '.' separated parts; these SRVs have stricter parent domain matching requirements for security. Create terminology section. Remove usage of term `{TLD}`. The `{hostname}` now refers to the entire hostname, not just the `{subdomain}`. diff --git a/source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-mismatch.json b/source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-mismatch.json new file mode 100644 index 0000000000..29506579ea --- /dev/null +++ b/source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-mismatch.json @@ -0,0 +1,5 @@ +{ + "uri": "mongodb+srv://test12.test.build.10gen.cc/?srvAllowedHostsSuffix=test.build.10gen.cc", + "seeds": [], + "hosts": [] +} diff --git a/source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-mismatch.yml b/source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-mismatch.yml new file mode 100644 index 0000000000..074b7c1a73 --- /dev/null +++ b/source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-mismatch.yml @@ -0,0 +1,4 @@ +# DNS record for test12.test.build.10gen.cc returns localhost.build.10gen.cc which would not match test.build.10gen.cc +uri: "mongodb+srv://test12.test.build.10gen.cc/?srvAllowedHostsSuffix=test.build.10gen.cc" +seeds: [] +hosts: [] \ No newline at end of file diff --git a/source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-with_dot.json b/source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-with_dot.json new file mode 100644 index 0000000000..8ff14a8958 --- /dev/null +++ b/source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-with_dot.json @@ -0,0 +1,11 @@ +{ + "uri": "mongodb+srv://test12.test.build.10gen.cc/?srvAllowedHostsSuffix=.build.10gen.cc", + "seeds": [ + "localhost.build.10gen.cc:27017" + ], + "options": { + "srvAllowedHostsSuffix": ".build.10gen.cc", + "ssl": true + }, + "ping": false +} diff --git a/source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-with_dot.yml b/source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-with_dot.yml new file mode 100644 index 0000000000..3c0173cc68 --- /dev/null +++ b/source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-with_dot.yml @@ -0,0 +1,7 @@ +uri: "mongodb+srv://test12.test.build.10gen.cc/?srvAllowedHostsSuffix=.build.10gen.cc" +seeds: + - localhost.build.10gen.cc:27017 +options: + srvAllowedHostsSuffix: .build.10gen.cc + ssl: true +ping: false \ No newline at end of file diff --git a/source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-without_dot_fail.json b/source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-without_dot_fail.json new file mode 100644 index 0000000000..78883916af --- /dev/null +++ b/source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-without_dot_fail.json @@ -0,0 +1,5 @@ +{ + "uri": "mongodb+srv://test12.test.build.10gen.cc/?srvAllowedHostsSuffix=uild.10gen.cc", + "seeds": [], + "hosts": [] +} diff --git a/source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-without_dot_fail.yml b/source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-without_dot_fail.yml new file mode 100644 index 0000000000..cf4f5a8fe5 --- /dev/null +++ b/source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-without_dot_fail.yml @@ -0,0 +1,3 @@ +"uri": "mongodb+srv://test12.test.build.10gen.cc/?srvAllowedHostsSuffix=uild.10gen.cc" +seeds: [] +hosts: [] \ No newline at end of file diff --git a/source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-without_dot_pass.json b/source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-without_dot_pass.json new file mode 100644 index 0000000000..3f4c1f1f71 --- /dev/null +++ b/source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-without_dot_pass.json @@ -0,0 +1,11 @@ +{ + "uri": "mongodb+srv://test12.test.build.10gen.cc/?srvAllowedHostsSuffix=build.10gen.cc", + "seeds": [ + "localhost.build.10gen.cc:27017" + ], + "options": { + "srvAllowedHostsSuffix": "build.10gen.cc", + "ssl": true + }, + "ping": false +} diff --git a/source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-without_dot_pass.yml b/source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-without_dot_pass.yml new file mode 100644 index 0000000000..79ccddfaf3 --- /dev/null +++ b/source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-without_dot_pass.yml @@ -0,0 +1,7 @@ +uri: mongodb+srv://test12.test.build.10gen.cc/?srvAllowedHostsSuffix=build.10gen.cc +seeds: + - localhost.build.10gen.cc:27017 +options: + srvAllowedHostsSuffix: .build.10gen.cc + ssl: true +ping: false \ No newline at end of file diff --git a/source/uri-options/uri-options.md b/source/uri-options/uri-options.md index 85a137671c..5a3d70d054 100644 --- a/source/uri-options/uri-options.md +++ b/source/uri-options/uri-options.md @@ -43,9 +43,9 @@ The driver MUST report an error if the `directConnection=true` URI option is spe The driver MUST report an error if the `directConnection=true` URI option is specified with an SRV URI, because the URI may resolve to multiple hosts. The driver MUST allow specifying `directConnection=false` URI option with an SRV URI. -### srvServiceName and srvMaxHosts URI options +### srvServiceName, srvMaxHosts, and srvAllowedHostsSuffix URI options -For URI option validation pertaining to `srvServiceName` and `srvMaxHosts`, please see the +For URI option validation pertaining to `srvServiceName`, `srvMaxHosts`, and `srvAllowedHostsSuffix`, please see the [Initial DNS Seedlist Discovery spec](../initial-dns-seedlist-discovery/initial-dns-seedlist-discovery.md#uri-validation) for details. @@ -104,6 +104,7 @@ to URI options apply here. | serverSelectionTimeoutMS | positive integer; a driver may also accept 0 to be used for a special case, provided that it documents the meaning | defined in [server selection spec](../server-selection/server-selection.md#serverselectiontimeoutms) | no | A timeout in milliseconds to block for server selection before raising an error | | serverSelectionTryOnce | "true" or "false" | defined in [server selection spec](../server-selection/server-selection.md#serverselectiontryonce) | required for single-threaded drivers | Scan the topology only once after a server selection failure instead of repeatedly until the server selection times out | | socketTimeoutMS | non-negative integer; 0 means no timeout | no timeout | no | NOTE: This option is deprecated in favor of [timeoutMS](../client-side-operations-timeout/client-side-operations-timeout.md#timeoutms)

Amount of time spent attempting to send or receive on a socket before timing out; note that this only applies to application operations, not SDAM. | +| srvAllowedHostsSuffix | a valid DNS hostname suffix (e.g. ".mydomain.net") | none; domain is inferred from the SRV hostname | no | A hostname suffix used to validate hosts returned via SRV lookup, replacing the domain inferred from the SRV hostname. Defined in the [Initial DNS Seedlist Discovery spec](../initial-dns-seedlist-discovery/initial-dns-seedlist-discovery.md#srvallowedhostssuffix). | | srvMaxHosts | non-negative integer; 0 means no maximum | defined in the [Initial DNS Seedlist Discovery spec](../initial-dns-seedlist-discovery/initial-dns-seedlist-discovery.md#srvmaxhosts) | no | The maximum number of SRV results to randomly select when initially populating the seedlist or, during SRV polling, adding new hosts to the topology. | | srvServiceName | a valid SRV service name according to [RFC 6335](https://datatracker.ietf.org/doc/html/rfc6335#section-5.1) | "mongodb" | no | the service name to use for SRV lookup in [initial DNS seedlist discovery](../initial-dns-seedlist-discovery/initial-dns-seedlist-discovery.md#srvservicename) and [SRV polling](../polling-srv-records-for-mongos-discovery/polling-srv-records-for-mongos-discovery.md) | | ssl | "true" or "false" | same as "tls" | no | alias of "tls"; required to ensure that Atlas connection strings continue to work | @@ -184,6 +185,8 @@ changes. ## Changelog +- 2026-06-08: Add `srvAllowedHostsSuffix` option. + - 2024-05-08: Migrated from reStructuredText to Markdown. - 2023-08-21: Add serverMonitoringMode option. From 790505e9b8c570a6ae193f34b2c7a0fb8762d859 Mon Sep 17 00:00:00 2001 From: Iris Date: Mon, 15 Jun 2026 10:41:54 -0700 Subject: [PATCH 02/14] fix yml test --- .../replica-set/srvAllowedHostsSuffix-without_dot_pass.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-without_dot_pass.yml b/source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-without_dot_pass.yml index 79ccddfaf3..ffee59d769 100644 --- a/source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-without_dot_pass.yml +++ b/source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-without_dot_pass.yml @@ -2,6 +2,6 @@ uri: mongodb+srv://test12.test.build.10gen.cc/?srvAllowedHostsSuffix=build.10gen seeds: - localhost.build.10gen.cc:27017 options: - srvAllowedHostsSuffix: .build.10gen.cc + srvAllowedHostsSuffix: build.10gen.cc ssl: true ping: false \ No newline at end of file From 914c830db0bffcc9f1567a0c92217a8df1c9a51b Mon Sep 17 00:00:00 2001 From: Iris Date: Mon, 15 Jun 2026 12:57:43 -0700 Subject: [PATCH 03/14] tests should error --- .../tests/replica-set/srvAllowedHostsSuffix-mismatch.json | 3 ++- .../tests/replica-set/srvAllowedHostsSuffix-mismatch.yml | 3 ++- .../replica-set/srvAllowedHostsSuffix-without_dot_fail.json | 3 ++- .../replica-set/srvAllowedHostsSuffix-without_dot_fail.yml | 3 ++- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-mismatch.json b/source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-mismatch.json index 29506579ea..56e26524c4 100644 --- a/source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-mismatch.json +++ b/source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-mismatch.json @@ -1,5 +1,6 @@ { "uri": "mongodb+srv://test12.test.build.10gen.cc/?srvAllowedHostsSuffix=test.build.10gen.cc", "seeds": [], - "hosts": [] + "hosts": [], + "error": true } diff --git a/source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-mismatch.yml b/source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-mismatch.yml index 074b7c1a73..d4d411097e 100644 --- a/source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-mismatch.yml +++ b/source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-mismatch.yml @@ -1,4 +1,5 @@ # DNS record for test12.test.build.10gen.cc returns localhost.build.10gen.cc which would not match test.build.10gen.cc uri: "mongodb+srv://test12.test.build.10gen.cc/?srvAllowedHostsSuffix=test.build.10gen.cc" seeds: [] -hosts: [] \ No newline at end of file +hosts: [] +error: true \ No newline at end of file diff --git a/source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-without_dot_fail.json b/source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-without_dot_fail.json index 78883916af..b7544b66f2 100644 --- a/source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-without_dot_fail.json +++ b/source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-without_dot_fail.json @@ -1,5 +1,6 @@ { "uri": "mongodb+srv://test12.test.build.10gen.cc/?srvAllowedHostsSuffix=uild.10gen.cc", "seeds": [], - "hosts": [] + "hosts": [], + "error": true } diff --git a/source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-without_dot_fail.yml b/source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-without_dot_fail.yml index cf4f5a8fe5..9864fe3129 100644 --- a/source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-without_dot_fail.yml +++ b/source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-without_dot_fail.yml @@ -1,3 +1,4 @@ "uri": "mongodb+srv://test12.test.build.10gen.cc/?srvAllowedHostsSuffix=uild.10gen.cc" seeds: [] -hosts: [] \ No newline at end of file +hosts: [] +error: true \ No newline at end of file From 529ad3be2760dc94d57575f3bc2a280badce2f62 Mon Sep 17 00:00:00 2001 From: Iris <58442094+sleepyStick@users.noreply.github.com> Date: Mon, 22 Jun 2026 11:40:02 -0700 Subject: [PATCH 04/14] Update source/initial-dns-seedlist-discovery/initial-dns-seedlist-discovery.md Co-authored-by: Matt Dale <9760375+matthewdale@users.noreply.github.com> --- .../initial-dns-seedlist-discovery.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/initial-dns-seedlist-discovery/initial-dns-seedlist-discovery.md b/source/initial-dns-seedlist-discovery/initial-dns-seedlist-discovery.md index 7363034088..7d8ed96a67 100644 --- a/source/initial-dns-seedlist-discovery/initial-dns-seedlist-discovery.md +++ b/source/initial-dns-seedlist-discovery/initial-dns-seedlist-discovery.md @@ -68,7 +68,7 @@ Only `{domainname}` is used during SRV record verification and `{subdomain}` is #### srvAllowedHostsSuffix -This option is used to validate hosts. If present, its value MUST be treated as the domain for DNS validation. For +This option is used to validate hosts. If present, its value MUST be treated as the `{domainname}` for DNS validation. For example, `srvAllowedHostsSuffix=.mydomain.net`. If the value does not begin with a `.`, for example, `srvAllowedHostsSuffix=mydomain.net`, the `.` MUST be automatically prepended prior to validation. If this option is not present, the domain MUST be inferred from the hostname. This option MUST only be configurable at the level of a From 6556c3054c82d775344498795280c40b3bb8d902 Mon Sep 17 00:00:00 2001 From: Iris <58442094+sleepyStick@users.noreply.github.com> Date: Mon, 22 Jun 2026 11:40:13 -0700 Subject: [PATCH 05/14] Update source/initial-dns-seedlist-discovery/initial-dns-seedlist-discovery.md Co-authored-by: Matt Dale <9760375+matthewdale@users.noreply.github.com> --- .../initial-dns-seedlist-discovery.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/initial-dns-seedlist-discovery/initial-dns-seedlist-discovery.md b/source/initial-dns-seedlist-discovery/initial-dns-seedlist-discovery.md index 7d8ed96a67..a5b5fb9dbe 100644 --- a/source/initial-dns-seedlist-discovery/initial-dns-seedlist-discovery.md +++ b/source/initial-dns-seedlist-discovery/initial-dns-seedlist-discovery.md @@ -71,7 +71,7 @@ Only `{domainname}` is used during SRV record verification and `{subdomain}` is This option is used to validate hosts. If present, its value MUST be treated as the `{domainname}` for DNS validation. For example, `srvAllowedHostsSuffix=.mydomain.net`. If the value does not begin with a `.`, for example, `srvAllowedHostsSuffix=mydomain.net`, the `.` MUST be automatically prepended prior to validation. If this option is not -present, the domain MUST be inferred from the hostname. This option MUST only be configurable at the level of a +present, the`{domainname}` MUST be inferred from the `{hostname}` (as described in [Connection String Format](#connection-string-format)). This option MUST only be configurable at the level of a `MongoClient`. #### srvMaxHosts From 871c812e7812a2364e834e38c8bf19252a0bf695 Mon Sep 17 00:00:00 2001 From: Iris Date: Mon, 22 Jun 2026 11:49:20 -0700 Subject: [PATCH 06/14] address MD feedback --- .../initial-dns-seedlist-discovery.md | 9 +++++---- .../srvAllowedHostsSuffix-without_dot_fail.yml | 1 + 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/source/initial-dns-seedlist-discovery/initial-dns-seedlist-discovery.md b/source/initial-dns-seedlist-discovery/initial-dns-seedlist-discovery.md index a5b5fb9dbe..0920fd5711 100644 --- a/source/initial-dns-seedlist-discovery/initial-dns-seedlist-discovery.md +++ b/source/initial-dns-seedlist-discovery/initial-dns-seedlist-discovery.md @@ -68,10 +68,11 @@ Only `{domainname}` is used during SRV record verification and `{subdomain}` is #### srvAllowedHostsSuffix -This option is used to validate hosts. If present, its value MUST be treated as the `{domainname}` for DNS validation. For -example, `srvAllowedHostsSuffix=.mydomain.net`. If the value does not begin with a `.`, for example, -`srvAllowedHostsSuffix=mydomain.net`, the `.` MUST be automatically prepended prior to validation. If this option is not -present, the`{domainname}` MUST be inferred from the `{hostname}` (as described in [Connection String Format](#connection-string-format)). This option MUST only be configurable at the level of a +This option is used to validate hosts. If present, its value MUST be treated as the `{domainname}` for +[DNS validation](#querying-dns). For example, `srvAllowedHostsSuffix=.mydomain.net`. If the value does not begin with a +`.`, for example, `srvAllowedHostsSuffix=mydomain.net`, the `.` MUST be automatically prepended prior to validation. If +this option is not present, the`{domainname}` MUST be inferred from the `{hostname}` (as described in +[Connection String Format](#connection-string-format)). This option MUST only be configurable at the level of a `MongoClient`. #### srvMaxHosts diff --git a/source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-without_dot_fail.yml b/source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-without_dot_fail.yml index 9864fe3129..7be3101f0a 100644 --- a/source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-without_dot_fail.yml +++ b/source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-without_dot_fail.yml @@ -1,3 +1,4 @@ +# dot should be prepended causing the host to be .uild.10gen.cc "uri": "mongodb+srv://test12.test.build.10gen.cc/?srvAllowedHostsSuffix=uild.10gen.cc" seeds: [] hosts: [] From c3f590c786366a70e91c47b2d0886f5c356c07a1 Mon Sep 17 00:00:00 2001 From: Iris Date: Mon, 22 Jun 2026 11:55:43 -0700 Subject: [PATCH 07/14] edit comment on yml test --- .../replica-set/srvAllowedHostsSuffix-without_dot_fail.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-without_dot_fail.yml b/source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-without_dot_fail.yml index 7be3101f0a..637a44e917 100644 --- a/source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-without_dot_fail.yml +++ b/source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-without_dot_fail.yml @@ -1,4 +1,4 @@ -# dot should be prepended causing the host to be .uild.10gen.cc +# dot should be prepended to srvAllowedHostsSuffix causing the host to be .uild.10gen.cc which should not match any available DNS records "uri": "mongodb+srv://test12.test.build.10gen.cc/?srvAllowedHostsSuffix=uild.10gen.cc" seeds: [] hosts: [] From 2dd89df8d258e8284e87330093c267fc2cbc1d91 Mon Sep 17 00:00:00 2001 From: Iris Date: Mon, 22 Jun 2026 12:03:51 -0700 Subject: [PATCH 08/14] minor edit to comment again haha --- .../replica-set/srvAllowedHostsSuffix-without_dot_fail.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-without_dot_fail.yml b/source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-without_dot_fail.yml index 637a44e917..cd81ca7528 100644 --- a/source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-without_dot_fail.yml +++ b/source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-without_dot_fail.yml @@ -1,4 +1,4 @@ -# dot should be prepended to srvAllowedHostsSuffix causing the host to be .uild.10gen.cc which should not match any available DNS records +# dot should be prepended to `srvAllowedHostsSuffix` causing the host to be .uild.10gen.cc which does not match any available DNS records "uri": "mongodb+srv://test12.test.build.10gen.cc/?srvAllowedHostsSuffix=uild.10gen.cc" seeds: [] hosts: [] From 86d16333261d13226a210353ee740b64d8b5ecdb Mon Sep 17 00:00:00 2001 From: Iris Date: Wed, 24 Jun 2026 11:24:07 -0700 Subject: [PATCH 09/14] AC feedback --- .../initial-dns-seedlist-discovery.md | 2 +- .../tests/replica-set/srvAllowedHostsSuffix-mismatch.yml | 2 +- .../tests/replica-set/srvAllowedHostsSuffix-with_dot.yml | 2 +- .../replica-set/srvAllowedHostsSuffix-without_dot_fail.yml | 4 ++-- .../replica-set/srvAllowedHostsSuffix-without_dot_pass.yml | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/source/initial-dns-seedlist-discovery/initial-dns-seedlist-discovery.md b/source/initial-dns-seedlist-discovery/initial-dns-seedlist-discovery.md index 0920fd5711..124dc271b3 100644 --- a/source/initial-dns-seedlist-discovery/initial-dns-seedlist-discovery.md +++ b/source/initial-dns-seedlist-discovery/initial-dns-seedlist-discovery.md @@ -71,7 +71,7 @@ Only `{domainname}` is used during SRV record verification and `{subdomain}` is This option is used to validate hosts. If present, its value MUST be treated as the `{domainname}` for [DNS validation](#querying-dns). For example, `srvAllowedHostsSuffix=.mydomain.net`. If the value does not begin with a `.`, for example, `srvAllowedHostsSuffix=mydomain.net`, the `.` MUST be automatically prepended prior to validation. If -this option is not present, the`{domainname}` MUST be inferred from the `{hostname}` (as described in +this option is not present, the `{domainname}` MUST be inferred from the `{hostname}` (as described in [Connection String Format](#connection-string-format)). This option MUST only be configurable at the level of a `MongoClient`. diff --git a/source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-mismatch.yml b/source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-mismatch.yml index d4d411097e..db6ee9811b 100644 --- a/source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-mismatch.yml +++ b/source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-mismatch.yml @@ -2,4 +2,4 @@ uri: "mongodb+srv://test12.test.build.10gen.cc/?srvAllowedHostsSuffix=test.build.10gen.cc" seeds: [] hosts: [] -error: true \ No newline at end of file +error: true diff --git a/source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-with_dot.yml b/source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-with_dot.yml index 3c0173cc68..69549b1869 100644 --- a/source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-with_dot.yml +++ b/source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-with_dot.yml @@ -4,4 +4,4 @@ seeds: options: srvAllowedHostsSuffix: .build.10gen.cc ssl: true -ping: false \ No newline at end of file +ping: false diff --git a/source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-without_dot_fail.yml b/source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-without_dot_fail.yml index cd81ca7528..57fab7a570 100644 --- a/source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-without_dot_fail.yml +++ b/source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-without_dot_fail.yml @@ -1,5 +1,5 @@ # dot should be prepended to `srvAllowedHostsSuffix` causing the host to be .uild.10gen.cc which does not match any available DNS records -"uri": "mongodb+srv://test12.test.build.10gen.cc/?srvAllowedHostsSuffix=uild.10gen.cc" +uri: "mongodb+srv://test12.test.build.10gen.cc/?srvAllowedHostsSuffix=uild.10gen.cc" seeds: [] hosts: [] -error: true \ No newline at end of file +error: true diff --git a/source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-without_dot_pass.yml b/source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-without_dot_pass.yml index ffee59d769..982eec2a36 100644 --- a/source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-without_dot_pass.yml +++ b/source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-without_dot_pass.yml @@ -4,4 +4,4 @@ seeds: options: srvAllowedHostsSuffix: build.10gen.cc ssl: true -ping: false \ No newline at end of file +ping: false From 013594b636cd2f1574d137e3e93f429bde3e2897 Mon Sep 17 00:00:00 2001 From: Iris Date: Mon, 29 Jun 2026 01:01:06 -0700 Subject: [PATCH 10/14] add tests --- source/connection-string/tests/invalid-uris.json | 9 +++++++++ source/connection-string/tests/invalid-uris.yml | 8 ++++++++ .../srvAllowedHostsSuffix-case-insensitive.json | 11 +++++++++++ .../srvAllowedHostsSuffix-case-insensitive.yml | 9 +++++++++ .../replica-set/srvAllowedHostsSuffix-tld-only.json | 6 ++++++ .../replica-set/srvAllowedHostsSuffix-tld-only.yml | 9 +++++++++ .../replica-set/srvAllowedHostsSuffix-with_dot.yml | 2 ++ 7 files changed, 54 insertions(+) create mode 100644 source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-case-insensitive.json create mode 100644 source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-case-insensitive.yml create mode 100644 source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-tld-only.json create mode 100644 source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-tld-only.yml diff --git a/source/connection-string/tests/invalid-uris.json b/source/connection-string/tests/invalid-uris.json index a7accbd27d..b01ca487d3 100644 --- a/source/connection-string/tests/invalid-uris.json +++ b/source/connection-string/tests/invalid-uris.json @@ -252,6 +252,15 @@ "auth": null, "options": null }, + { + "description": "srvAllowedHostsSuffix with non-SRV URI", + "uri": "mongodb://localhost:27017/?srvAllowedHostsSuffix=.mongodb.net", + "valid": false, + "warning": null, + "hosts": null, + "auth": null, + "options": null + }, { "description": "Username with password containing an unescaped percent sign", "uri": "mongodb://alice%foo:bar@127.0.0.1", diff --git a/source/connection-string/tests/invalid-uris.yml b/source/connection-string/tests/invalid-uris.yml index dd4d4ce31c..bd9daf9c22 100644 --- a/source/connection-string/tests/invalid-uris.yml +++ b/source/connection-string/tests/invalid-uris.yml @@ -223,6 +223,14 @@ tests: hosts: ~ auth: ~ options: ~ + - + description: "srvAllowedHostsSuffix with non-SRV URI" + uri: "mongodb://localhost:27017/?srvAllowedHostsSuffix=.mongodb.net" + valid: false + warning: ~ + hosts: ~ + auth: ~ + options: ~ - description: "Username with password containing an unescaped percent sign" uri: "mongodb://alice%foo:bar@127.0.0.1" diff --git a/source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-case-insensitive.json b/source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-case-insensitive.json new file mode 100644 index 0000000000..64ec6b92f4 --- /dev/null +++ b/source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-case-insensitive.json @@ -0,0 +1,11 @@ +{ + "uri": "mongodb+srv://test12.test.build.10gen.cc/?srvAllowedHostsSuffix=.BUILD.10GEN.CC", + "seeds": [ + "localhost.build.10gen.cc:27017" + ], + "options": { + "srvAllowedHostsSuffix": ".BUILD.10GEN.CC", + "ssl": true + }, + "ping": false +} diff --git a/source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-case-insensitive.yml b/source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-case-insensitive.yml new file mode 100644 index 0000000000..bcfdd720ea --- /dev/null +++ b/source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-case-insensitive.yml @@ -0,0 +1,9 @@ +# Tests that srvAllowedHostsSuffix comparison is case-insensitive (ASCII case folding per RFC 4343). +# The suffix .BUILD.10GEN.CC is uppercase but should match the returned host localhost.build.10gen.cc. +uri: "mongodb+srv://test12.test.build.10gen.cc/?srvAllowedHostsSuffix=.BUILD.10GEN.CC" +seeds: + - localhost.build.10gen.cc:27017 +options: + srvAllowedHostsSuffix: .BUILD.10GEN.CC + ssl: true +ping: false diff --git a/source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-tld-only.json b/source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-tld-only.json new file mode 100644 index 0000000000..12098dbf5e --- /dev/null +++ b/source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-tld-only.json @@ -0,0 +1,6 @@ +{ + "uri": "mongodb+srv://test1.test.build.10gen.cc/?srvAllowedHostsSuffix=.cc", + "seeds": [], + "hosts": [], + "error": true +} diff --git a/source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-tld-only.yml b/source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-tld-only.yml new file mode 100644 index 0000000000..287fc0a0b1 --- /dev/null +++ b/source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-tld-only.yml @@ -0,0 +1,9 @@ +# srvAllowedHostsSuffix must contain at least two labels. A value of .cc (TLD only) +# has only one label after the leading dot and MUST raise an error. +# Note: .cc is used (rather than an unrelated TLD) because the DNS records return +# hosts ending in .cc, ensuring the test fails only due to TLD validation and not +# a host mismatch. +uri: "mongodb+srv://test1.test.build.10gen.cc/?srvAllowedHostsSuffix=.cc" +seeds: [] +hosts: [] +error: true diff --git a/source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-with_dot.yml b/source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-with_dot.yml index 69549b1869..9daec9f6e6 100644 --- a/source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-with_dot.yml +++ b/source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-with_dot.yml @@ -1,3 +1,5 @@ +# Also tests trailing dot normalization: DNS returns targets with a trailing dot +# (localhost.build.10gen.cc.) which must be stripped before suffix comparison. uri: "mongodb+srv://test12.test.build.10gen.cc/?srvAllowedHostsSuffix=.build.10gen.cc" seeds: - localhost.build.10gen.cc:27017 From 8122297530c2b6b144b754d135eb597d43e8a1cd Mon Sep 17 00:00:00 2001 From: Iris Date: Wed, 1 Jul 2026 14:23:40 -0700 Subject: [PATCH 11/14] add tests + better param parsing specifications --- .../initial-dns-seedlist-discovery.md | 22 +++++++++++++++---- .../srvAllowedHostsSuffix-trailing-dot.json | 11 ++++++++++ .../srvAllowedHostsSuffix-trailing-dot.yml | 9 ++++++++ 3 files changed, 38 insertions(+), 4 deletions(-) create mode 100644 source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-trailing-dot.json create mode 100644 source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-trailing-dot.yml diff --git a/source/initial-dns-seedlist-discovery/initial-dns-seedlist-discovery.md b/source/initial-dns-seedlist-discovery/initial-dns-seedlist-discovery.md index 124dc271b3..8510e2e395 100644 --- a/source/initial-dns-seedlist-discovery/initial-dns-seedlist-discovery.md +++ b/source/initial-dns-seedlist-discovery/initial-dns-seedlist-discovery.md @@ -69,9 +69,18 @@ Only `{domainname}` is used during SRV record verification and `{subdomain}` is #### srvAllowedHostsSuffix This option is used to validate hosts. If present, its value MUST be treated as the `{domainname}` for -[DNS validation](#querying-dns). For example, `srvAllowedHostsSuffix=.mydomain.net`. If the value does not begin with a -`.`, for example, `srvAllowedHostsSuffix=mydomain.net`, the `.` MUST be automatically prepended prior to validation. If -this option is not present, the `{domainname}` MUST be inferred from the `{hostname}` (as described in +[DNS validation](#querying-dns) and +[SRV polling](../polling-srv-records-for-mongos-discovery/polling-srv-records-for-mongos-discovery.md). For example, +`srvAllowedHostsSuffix=.mydomain.net`. Drivers MUST apply the following normalization and validation to the value before +use: + +- If the value does not begin with a `.`, a `.` MUST be automatically prepended. For example, + `srvAllowedHostsSuffix=mydomain.net` is treated as `.mydomain.net`. +- The value MUST contain at least two dot-separated labels (i.e. the portion after the leading `.` must itself contain a + `.`). For example, `srvAllowedHostsSuffix=.net` MUST raise an error. +- The value MUST be normalized to lowercase using ASCII case folding before comparison. + +If this option is not present, the `{domainname}` MUST be inferred from the `{hostname}` (as described in [Connection String Format](#connection-string-format)). This option MUST only be configurable at the level of a `MongoClient`. @@ -134,6 +143,11 @@ If the DNS result returns no SRV records, or no records at all, or a DNS error h indicating that the URI could not be used to find hostnames. The error SHALL include the reason why they could not be found. +Before validating returned hostnames, drivers MUST normalize them as follows: + +- Trailing dots MUST be stripped (e.g. `host.example.com.` becomes `host.example.com`). +- Hostnames MUST be normalized to lowercase using ASCII case folding. + A driver MUST verify that the host names returned through SRV records share the original SRV's `{domainname}`. In addition, SRV records with fewer than three `.` separated parts, the returned hostname MUST have at least one more domain level than the SRV record hostname. Drivers MUST raise an error and MUST NOT initiate a connection to any @@ -293,7 +307,7 @@ In the future we could consider using the priority and weight fields of the SRV ## ChangeLog -- 2026-06-08: Add `srvAllowedHostsSuffix` MongoClient option. +- 2026-01-01: Add `srvAllowedHostsSuffix` MongoClient option. - 2024-09-24: Removed requirement for URI to have three '.' separated parts; these SRVs have stricter parent domain matching requirements for security. Create terminology section. Remove usage of term `{TLD}`. The `{hostname}` now diff --git a/source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-trailing-dot.json b/source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-trailing-dot.json new file mode 100644 index 0000000000..006f7cc22c --- /dev/null +++ b/source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-trailing-dot.json @@ -0,0 +1,11 @@ +{ + "uri": "mongodb+srv://test12.test.build.10gen.cc/?srvAllowedHostsSuffix=.build.10gen.cc.", + "seeds": [ + "localhost.build.10gen.cc:27017" + ], + "options": { + "srvAllowedHostsSuffix": ".build.10gen.cc.", + "ssl": true + }, + "ping": false +} diff --git a/source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-trailing-dot.yml b/source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-trailing-dot.yml new file mode 100644 index 0000000000..b688cbd320 --- /dev/null +++ b/source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-trailing-dot.yml @@ -0,0 +1,9 @@ +# A trailing dot in srvAllowedHostsSuffix must be stripped before comparison, +# so ".build.10gen.cc." is equivalent to ".build.10gen.cc". +uri: "mongodb+srv://test12.test.build.10gen.cc/?srvAllowedHostsSuffix=.build.10gen.cc." +seeds: + - localhost.build.10gen.cc:27017 +options: + srvAllowedHostsSuffix: .build.10gen.cc. + ssl: true +ping: false From 78ff51548fbcae22d672b47d8da266345b2fca80 Mon Sep 17 00:00:00 2001 From: Iris Date: Mon, 24 Aug 2026 09:39:40 -0700 Subject: [PATCH 12/14] reference psl from drivers-3568 and update date in changelog --- .../initial-dns-seedlist-discovery.md | 5 ++--- source/uri-options/uri-options.md | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/source/initial-dns-seedlist-discovery/initial-dns-seedlist-discovery.md b/source/initial-dns-seedlist-discovery/initial-dns-seedlist-discovery.md index 8510e2e395..91a5f188e3 100644 --- a/source/initial-dns-seedlist-discovery/initial-dns-seedlist-discovery.md +++ b/source/initial-dns-seedlist-discovery/initial-dns-seedlist-discovery.md @@ -76,8 +76,7 @@ use: - If the value does not begin with a `.`, a `.` MUST be automatically prepended. For example, `srvAllowedHostsSuffix=mydomain.net` is treated as `.mydomain.net`. -- The value MUST contain at least two dot-separated labels (i.e. the portion after the leading `.` must itself contain a - `.`). For example, `srvAllowedHostsSuffix=.net` MUST raise an error. +- The value MUST NOT be a public suffix, per the algorithm in (../public-suffix-list/public-suffix-list.md) - The value MUST be normalized to lowercase using ASCII case folding before comparison. If this option is not present, the `{domainname}` MUST be inferred from the `{hostname}` (as described in @@ -307,7 +306,7 @@ In the future we could consider using the priority and weight fields of the SRV ## ChangeLog -- 2026-01-01: Add `srvAllowedHostsSuffix` MongoClient option. +- 2026-08-24: Add `srvAllowedHostsSuffix` MongoClient option. - 2024-09-24: Removed requirement for URI to have three '.' separated parts; these SRVs have stricter parent domain matching requirements for security. Create terminology section. Remove usage of term `{TLD}`. The `{hostname}` now diff --git a/source/uri-options/uri-options.md b/source/uri-options/uri-options.md index 5a3d70d054..27710d8d84 100644 --- a/source/uri-options/uri-options.md +++ b/source/uri-options/uri-options.md @@ -185,7 +185,7 @@ changes. ## Changelog -- 2026-06-08: Add `srvAllowedHostsSuffix` option. +- 2026-08-24: Add `srvAllowedHostsSuffix` option. - 2024-05-08: Migrated from reStructuredText to Markdown. From fde06d6702ed77a502b51540511d8a8292d7ae0a Mon Sep 17 00:00:00 2001 From: Iris <58442094+sleepyStick@users.noreply.github.com> Date: Mon, 24 Aug 2026 17:50:35 -0700 Subject: [PATCH 13/14] Update source/initial-dns-seedlist-discovery/initial-dns-seedlist-discovery.md Co-authored-by: Adelin Owona <51498470+adelinowona@users.noreply.github.com> --- .../initial-dns-seedlist-discovery.md | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/source/initial-dns-seedlist-discovery/initial-dns-seedlist-discovery.md b/source/initial-dns-seedlist-discovery/initial-dns-seedlist-discovery.md index 91a5f188e3..a5fede94fc 100644 --- a/source/initial-dns-seedlist-discovery/initial-dns-seedlist-discovery.md +++ b/source/initial-dns-seedlist-discovery/initial-dns-seedlist-discovery.md @@ -71,13 +71,12 @@ Only `{domainname}` is used during SRV record verification and `{subdomain}` is This option is used to validate hosts. If present, its value MUST be treated as the `{domainname}` for [DNS validation](#querying-dns) and [SRV polling](../polling-srv-records-for-mongos-discovery/polling-srv-records-for-mongos-discovery.md). For example, -`srvAllowedHostsSuffix=.mydomain.net`. Drivers MUST apply the following normalization and validation to the value before -use: - -- If the value does not begin with a `.`, a `.` MUST be automatically prepended. For example, - `srvAllowedHostsSuffix=mydomain.net` is treated as `.mydomain.net`. -- The value MUST NOT be a public suffix, per the algorithm in (../public-suffix-list/public-suffix-list.md) -- The value MUST be normalized to lowercase using ASCII case folding before comparison. +`srvAllowedHostsSuffix=.mydomain.net`. Drivers MUST apply the following normalization and validation to the value, in this order: +1. Any trailing `.` MUST be stripped. For example, `srvAllowedHostsSuffix=.mydomain.net.` is treated as `.mydomain.net`. +2. The value MUST be converted to its A-label (Punycode) form, so that it is comparable against the A-label hostnames returned by DNS. +3. The value MUST be normalized to lowercase using ASCII case folding. +4. The resulting value, with any leading `.` removed, MUST NOT be a public suffix, per the algorithm in [Public Suffix List](../public-suffix-list/public-suffix-list.md). +5. If the value does not begin with a `.`, a `.` MUST be prepended. For example, `srvAllowedHostsSuffix=mydomain.net` is treated as `.mydomain.net`. If this option is not present, the `{domainname}` MUST be inferred from the `{hostname}` (as described in [Connection String Format](#connection-string-format)). This option MUST only be configurable at the level of a From d2731ceb4b7619cb6a0ab727337afe9cbc3c5ff7 Mon Sep 17 00:00:00 2001 From: Iris Date: Mon, 24 Aug 2026 19:40:52 -0700 Subject: [PATCH 14/14] add rationale and update language in other specs --- .../initial-dns-seedlist-discovery.md | 53 ++++++++++++++++--- .../srvAllowedHostsSuffix-tld-only.yml | 10 ++-- ...olling-srv-records-for-mongos-discovery.md | 13 +++-- 3 files changed, 61 insertions(+), 15 deletions(-) diff --git a/source/initial-dns-seedlist-discovery/initial-dns-seedlist-discovery.md b/source/initial-dns-seedlist-discovery/initial-dns-seedlist-discovery.md index a5fede94fc..57164dd39e 100644 --- a/source/initial-dns-seedlist-discovery/initial-dns-seedlist-discovery.md +++ b/source/initial-dns-seedlist-discovery/initial-dns-seedlist-discovery.md @@ -71,12 +71,17 @@ Only `{domainname}` is used during SRV record verification and `{subdomain}` is This option is used to validate hosts. If present, its value MUST be treated as the `{domainname}` for [DNS validation](#querying-dns) and [SRV polling](../polling-srv-records-for-mongos-discovery/polling-srv-records-for-mongos-discovery.md). For example, -`srvAllowedHostsSuffix=.mydomain.net`. Drivers MUST apply the following normalization and validation to the value, in this order: +`srvAllowedHostsSuffix=.mydomain.net`. Drivers MUST apply the following normalization and validation to the value, in +this order: + 1. Any trailing `.` MUST be stripped. For example, `srvAllowedHostsSuffix=.mydomain.net.` is treated as `.mydomain.net`. -2. The value MUST be converted to its A-label (Punycode) form, so that it is comparable against the A-label hostnames returned by DNS. +2. The value MUST be converted to its A-label (Punycode) form, so that it is comparable against the A-label hostnames + returned by DNS. 3. The value MUST be normalized to lowercase using ASCII case folding. -4. The resulting value, with any leading `.` removed, MUST NOT be a public suffix, per the algorithm in [Public Suffix List](../public-suffix-list/public-suffix-list.md). -5. If the value does not begin with a `.`, a `.` MUST be prepended. For example, `srvAllowedHostsSuffix=mydomain.net` is treated as `.mydomain.net`. +4. The resulting value, with any leading `.` removed, MUST NOT be a public suffix, per the algorithm in + [Public Suffix List](../public-suffix-list/public-suffix-list.md). +5. If the value does not begin with a `.`, a `.` MUST be prepended. For example, `srvAllowedHostsSuffix=mydomain.net` is + treated as `.mydomain.net`. If this option is not present, the `{domainname}` MUST be inferred from the `{hostname}` (as described in [Connection String Format](#connection-string-format)). This option MUST only be configurable at the level of a @@ -147,9 +152,10 @@ Before validating returned hostnames, drivers MUST normalize them as follows: - Hostnames MUST be normalized to lowercase using ASCII case folding. A driver MUST verify that the host names returned through SRV records share the original SRV's `{domainname}`. In -addition, SRV records with fewer than three `.` separated parts, the returned hostname MUST have at least one more -domain level than the SRV record hostname. Drivers MUST raise an error and MUST NOT initiate a connection to any -returned hostname which does not fulfill these requirements. +addition, when `srvAllowedHostsSuffix` is not configured and the SRV record hostname has fewer than three `.` separated +parts, the returned hostname MUST have at least one more domain level than the SRV record hostname. Drivers MUST raise +an error and MUST NOT initiate a connection to any returned hostname which does not fulfill these requirements. This +additional requirement does not apply when `srvAllowedHostsSuffix` is configured. The driver MUST NOT attempt to connect to any hosts until the DNS query has returned its results. @@ -269,6 +275,39 @@ Several of our users have asked for this through tickets: The design specifically calls for a pre-processing stage of the processing of connection URLs to minimize the impact on existing functionality. +### Rationale for `srvAllowedHostsSuffix` + +By default, the parent domain that returned host names are checked against is inferred from the seed by treating its +leftmost label as the `{subdomain}`. A seed of `mongodb.mydomain.net` results in `mongodb1.us-east-1.mydomain.net` being +rejected, even when both are owned by the same user. `srvAllowedHostsSuffix` allows users to work around this limitation +by letting the user state the parent domain directly instead, admitting such nested names and hosts in a different +domain altogether. + +Note that nothing requires the `{hostname}` itself to end with the configured suffix. For example, +`mongodb+srv://cluster.example.org/?srvAllowedHostsSuffix=.hosts.example.net` is valid, even though +`cluster.example.org` does not end with `.hosts.example.net`. This is intentional: the option exists so the user can +state the allowed parent domain explicitly, rather than having it inferred from the connection string. Requiring the two +to match would restore that coupling, and would rule out arrangements such as a vanity alias in one organization's +domain resolving to hosts in a provider's domain. + +Because it replaces that default requirement, this option relaxes a DNS spoofing safeguard. An attacker able to forge +SRV responses is otherwise confined to host names under the seed's `{domainname}`; with the option set, they are +confined to host names under the configured suffix instead. The broader that suffix, the more hosts a forged response +can direct a driver to. + +Requiring that the value not be a public suffix bounds how broad it can get. It rules out values such as `.com` or +`.co.uk`, which would place no meaningful limit on a forged response. It does not, however, make a given configuration +safe: `.example.com` is not a public suffix, but it still admits every host in a large organization's domain. + +Users should be encouraged to configure the narrowest suffix that covers their deployment, and drivers should say so +wherever the option is documented. For a seed hostname of `cluster.test.internal.example.com`, prefer the second of +these: + +```text +mongodb+srv://cluster.test.internal.example.com/?srvAllowedHostsSuffix=.example.com +mongodb+srv://cluster.test.internal.example.com/?srvAllowedHostsSuffix=.internal.example.com +``` + ## Justifications ### Why Are Multiple Key-Value Pairs Allowed in One TXT Record? diff --git a/source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-tld-only.yml b/source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-tld-only.yml index 287fc0a0b1..c4eddfe803 100644 --- a/source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-tld-only.yml +++ b/source/initial-dns-seedlist-discovery/tests/replica-set/srvAllowedHostsSuffix-tld-only.yml @@ -1,8 +1,8 @@ -# srvAllowedHostsSuffix must contain at least two labels. A value of .cc (TLD only) -# has only one label after the leading dot and MUST raise an error. -# Note: .cc is used (rather than an unrelated TLD) because the DNS records return -# hosts ending in .cc, ensuring the test fails only due to TLD validation and not -# a host mismatch. +# srvAllowedHostsSuffix MUST NOT be a public suffix. "cc" is an ordinary rule in the +# Public Suffix List, so ".cc" is a public suffix and MUST raise an error. +# Note: .cc is used (rather than an unrelated public suffix) because the DNS records +# return hosts ending in .cc, so the host suffix check passes and the public suffix +# check is the only thing that can fail here. uri: "mongodb+srv://test1.test.build.10gen.cc/?srvAllowedHostsSuffix=.cc" seeds: [] hosts: [] diff --git a/source/polling-srv-records-for-mongos-discovery/polling-srv-records-for-mongos-discovery.md b/source/polling-srv-records-for-mongos-discovery/polling-srv-records-for-mongos-discovery.md index 2805a9c23c..e9b28a6b8e 100644 --- a/source/polling-srv-records-for-mongos-discovery/polling-srv-records-for-mongos-discovery.md +++ b/source/polling-srv-records-for-mongos-discovery/polling-srv-records-for-mongos-discovery.md @@ -53,9 +53,14 @@ initial seedlist discovery. Periodic scan MUST follow these rules: and protocol. The SRV service name is provided in the [srvServiceName](../initial-dns-seedlist-discovery/initial-dns-seedlist-discovery.md#srvservicename) URI option and defaults to `mongodb`. The protocol is always `tcp`. After prefixing, the URI should look like: - `_{srvServiceName}._tcp.{hostname}.{domainname}`. -- A driver MUST verify that the host names returned through SRV records have the same parent `{domainname}`. When this - verification fails, a driver: + `_{srvServiceName}._tcp.{hostname}.{domainname}`. Here `{hostname}.{domainname}` is the host from the connection + string, and is not affected by + [srvAllowedHostsSuffix](../initial-dns-seedlist-discovery/initial-dns-seedlist-discovery.md#srvallowedhostssuffix): + that option changes which parent domain returned host names are verified against, not which records are queried. +- A driver MUST verify that the host names returned through SRV records have the same parent `{domainname}`. When + [srvAllowedHostsSuffix](../initial-dns-seedlist-discovery/initial-dns-seedlist-discovery.md#srvallowedhostssuffix) + is configured, its value is the parent domain used for this verification instead of the `{domainname}` derived from + the connection string. When this verification fails, a driver: - MUST NOT add such a non-compliant host name to the topology - MUST NOT raise an error - SHOULD log the non-compliance, including the host name @@ -165,6 +170,8 @@ No future work is expected. ## Changelog +- 2026-08-24: Account for the `srvAllowedHostsSuffix` MongoClient option when verifying returned host names. + - 2024-08-22: Migrated from reStructuredText to Markdown. - 2022-10-05: Revise spec front matter and reformat changelog.