Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 20 additions & 4 deletions source/auth/auth.md
Original file line number Diff line number Diff line change
Expand Up @@ -634,8 +634,12 @@ that this be as secure and truly random as possible. For instance, Java provides
SecureRandom class. SecureRandom is cryptographically generated while Random is just a pseudo-random generator with
predictable outcomes.

Additionally, drivers MUST enforce a minimum iteration count of 4096 and MUST error if the authentication conversation
specifies a lower count. This mitigates downgrade attacks by a man-in-the-middle attacker.
Drivers MUST enforce a minimum iteration count of 4096 and MUST error if the authentication conversation specifies a
lower count. This mitigates downgrade attacks by a man-in-the-middle attacker.

Drivers MUST enforce a maximum iteration count, defined by the `maxScramIterations` connection string option (default:

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.

Opinion: I would rather avoid a new URI option unless there is an expected need. I expect the vast majority of users will not need to set maxScramIterations. The iteration count appears not configurable in Atlas.

OTOH the server changes also appear to make this value configurable: https://github.com/10gen/mongo/pull/55863. Consider asking in #server-security if there is any known need for iteration counts beyond, say, 100000 (or maybe some other high arbitrary limit). If there is no known need, I would be more inclined to drop the URI option.

@connorsmacd connorsmacd Jun 30, 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.

I agree the URI option is unlikely to be needed by most users. However, I felt it was still appropriate to provide the URI option for a few reasons:

  • Existing systems that expect higher iteration counts would otherwise have no reasonable workaround.
  • The defensive strength of an iteration count depends on the HMAC function. For example, in the context of password storage, OWASP recommends 1.4M iterations for SHA1, but only 600K iterations for SHA256.
  • This is more of a philosophical issue, but the idea of drivers dictating what is a "high enough" iteration count feels perhaps overly opinionated.

If we do decide to get rid of the URI option in favor of a hard cap, then we may want to consider revising the number. I don't know how much the recommended values for password storage apply here, but the OWASP cheatsheet I mentioned above is at least some hint that 100K may not be sufficiently high for a hard cap.

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.

#server-security

See slack thread.

Existing systems that expect higher iteration counts would otherwise have no reasonable workaround.

Agreed. A too-low cap risks preventing auth with no workaround (very bad). A too-high cap might not address the original issue, and might not be practical to evaluate.

Plus, recommendations vary by time and standard. From CLAUDE:

10k (2019-01) => 500k (2019-05) => 310k (2021-03) => 600k (2023-01)

And from NIST Special Publication 800-132:

an iteration count of 10,000,000 may be appropriate

After further wavering: I am in favor of an option rather than a non-configurable cap. Regardless: I'd request adding to the "Q & A" section to document the rationale.

100000), and MUST error if the authentication conversation specifies a higher count. This mitigates client-side denial

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.

Suggested change
100000), and MUST error if the authentication conversation specifies a higher count. This mitigates client-side denial
600000), and MUST error if the authentication conversation specifies a higher count. This mitigates client-side denial

Suggest using a default to match the current OWASP recommendation:

If FIPS-140 compliance is required, use PBKDF2 with a work factor of 600,000 or more and set with an internal hash function of HMAC-SHA-256.

MongoDB also documents FIPS-140 compliance instructions. So this may reduce the chance of users receiving errors on upgrade (and 600,000 still seems low enough to not be a cause of concern).

of service attacks in which a malicious server causes CPU exhaustion by specifying an extremely high iteration count.

Drivers MUST NOT advertise support for channel binding, as the server does not support it and legacy servers may fail
authentication if drivers advertise support. I.e. the client-first-message MUST start with `n,`.
Expand Down Expand Up @@ -703,8 +707,12 @@ The MongoDB SCRAM-SHA-256 mechanism works similarly to the SCRAM-SHA-1 mechanism
- Passwords MUST be prepared with SASLprep, per RFC 5802. Passwords are used directly for key derivation ; they MUST NOT
be digested as they are in SCRAM-SHA-1.

Additionally, drivers MUST enforce a minimum iteration count of 4096 and MUST error if the authentication conversation
specifies a lower count. This mitigates downgrade attacks by a man-in-the-middle attacker.
Drivers MUST enforce a minimum iteration count of 4096 and MUST error if the authentication conversation specifies a
lower count. This mitigates downgrade attacks by a man-in-the-middle attacker.

Drivers MUST enforce a maximum iteration count, defined by the `maxScramIterations` connection string option (default:
100000), and MUST error if the authentication conversation specifies a higher count. This mitigates client-side denial
of service attacks in which a malicious server causes CPU exhaustion by specifying an extremely high iteration count.

Drivers MUST add a top-level `options` field to the saslStart command, whose value is a document containing a field
named `skipEmptyExchange` whose value is true. Older servers will ignore the `options` field and continue with the
Expand Down Expand Up @@ -2034,6 +2042,12 @@ See the speculative authentication section in the [MongoDB Handshake spec](../mo
For SCRAM-SHA-1 and SCRAM-SHA-256, test that the minimum iteration count is respected. This may be done via unit testing
of an underlying SCRAM library.

### Maximum iteration count

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.

This test is similar to the "Minimum iteration count". I expect the "Minimum iteration count" cannot be tested as easily end-to-end, since the server rejects attempts to set too-low iteration counts:

client["admin"].command({"setParameter": 1, "scramSHA256IterationCount": 1000})
# Server error: "1000 is not greater than or equal to 5000"

But I expect testing higher iteration counts are rejected by the client should be possible end-to-end. Suggest replacing this test with an end-to-end test like the following:

# Test SCRAM-SHA-256:
scramSHA256IterationCount = test_client()["admin"].command({"getParameter": 1, "scramSHA256IterationCount": 1})["scramSHA256IterationCount"]
expect_error(test_client(mech="SCRAM-SHA-256", max_iterations=scramSHA256IterationCount - 1))
expect_ok(test_client(mech="SCRAM-SHA-256", max_iterations=scramSHA256IterationCount))

# Test SCRAM-SHA-1:
scramIterationCount = test_client()["admin"].command({"getParameter": 1, "scramIterationCount": 1})["scramIterationCount"]
expect_error(test_client(mech="SCRAM-SHA-1", max_iterations=scramIterationCount - 1))
expect_ok(test_client(mech="SCRAM-SHA-1", max_iterations=scramIterationCount))


For SCRAM-SHA-1 and SCRAM-SHA-256, test that the maximum iteration count is respected. This may be done via unit testing
of an underlying SCRAM library. Ensure drivers use the `maxScramIterations` connection string option when set and fall
back to 100000 when unset.

## Backwards Compatibility

Drivers may need to remove support for association of more than one credential with a MongoClient, including
Expand Down Expand Up @@ -2143,6 +2157,8 @@ practice to avoid this. (See

## Changelog

- 2026-06-29: Require SCRAM-SHA-1 and SCRAM-SHA-256 to enforce a maximum iteration count

- 2025-11-25: Remove redundant `*.mongodbgov.net` on `ALLOWED_HOSTS`

- 2025-11-19: Extend `ALLOWED_HOSTS` with `*.mongo.com` and `*.mongodbgov.net`
Expand Down
20 changes: 20 additions & 0 deletions source/uri-options/tests/auth-options.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 17 additions & 0 deletions source/uri-options/tests/auth-options.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,20 @@ tests:
options:
authMechanism: "SCRAM-SHA-1"
authSource: "authSourceDB"
-
description: "maxScramIterations is parsed correctly"
uri: "mongodb://example.com/?maxScramIterations=123456"
valid: true
warning: false
hosts: ~
auth: ~
options:
maxScramIterations: 123456
-
description: "maxScramIterations with value less than 4096 causes a warning"
uri: "mongodb://example.com/?maxScramIterations=4095"
valid: true
warning: true
Comment thread
connorsmacd marked this conversation as resolved.
hosts: ~
auth: ~
options: ~
3 changes: 3 additions & 0 deletions source/uri-options/uri-options.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ to URI options apply here.
| authMechanism | any string; valid values are defined in the [auth spec](../auth/auth.md#supported-authentication-methods) | None; default values for authentication exist for constructing authentication credentials per the [auth spec](../auth/auth.md#supported-authentication-methods), but there is no default for the URI option itself. | no | The authentication mechanism method to use for connection to the server |
| authMechanismProperties | comma separated key:value pairs, e.g. "opt1:val1,opt2:val2" | no properties specified | no | Additional options provided for authentication (e.g. to enable hostname canonicalization for GSSAPI) |
| authSource | any string | None; default values for authentication exist for constructing authentication credentials per the [auth spec](../auth/auth.md#supported-authentication-methods), but there is no default for the URI option itself. | no | The database that connections should authenticate against |
| maxScramIterations | integer greater than or equal to 4096 | 100000 | no | The maximum number of iterations permitted in SCRAM PBKDF2 |
Comment thread
kevinAlbs marked this conversation as resolved.
| compressors | comma separated list of strings, e.g. "snappy,zlib" | defined in [compression spec](../compression/OP_COMPRESSED.md#compressors) | no | The list of allowed compression types for wire protocol messages sent or received from the server |
| connectTimeoutMS | non-negative integer; 0 means "no timeout" | 10,000 ms (unless a driver already has a different default) | no | Amount of time to wait for a single TCP socket connection to the server to be established before erroring; note that this applies to [SDAM hello and legacy hello operations](../mongodb-handshake/handshake.md) |
| directConnection | "true" or "false" | defined in [SDAM spec](../server-discovery-and-monitoring/server-discovery-and-monitoring.md#initial-topologytype) | no | Whether to connect to the deployment in Single topology. |
Expand Down Expand Up @@ -184,6 +185,8 @@ changes.

## Changelog

- 2026-06-29: Add `maxScramIterations` URI option.

- 2024-05-08: Migrated from reStructuredText to Markdown.

- 2023-08-21: Add serverMonitoringMode option.
Expand Down
Loading