Skip to content

DRIVERS-3472 enforce client-side maximum SCRAM iteration count#1959

Open
connorsmacd wants to merge 3 commits into
mongodb:masterfrom
connorsmacd:scram-max-iterations.DRIVERS-3472
Open

DRIVERS-3472 enforce client-side maximum SCRAM iteration count#1959
connorsmacd wants to merge 3 commits into
mongodb:masterfrom
connorsmacd:scram-max-iterations.DRIVERS-3472

Conversation

@connorsmacd

@connorsmacd connorsmacd commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

Please complete the following before merging:

  • Is the relevant DRIVERS ticket in the PR title?
  • Update changelog.
  • Test changes in at least one language driver. C Driver.
  • Test these changes against all server versions and topologies (including standalone, replica set, and sharded
    clusters).

Summary

This PR makes changes to the Auth Spec to enforce a maximum client-side SCRAM iteration count. The changes here closely match what was suggested in the JIRA issue.

  • Add URI option maxScramIterations.
    • Default value of 100000: This is ultimately arbitrary, but the 100K value suggested in the JIRA issue is the same value proposed for the server. I also found 100K to be a common choice for other projects that support SCRAM, e.g., node-postgres.
    • Ignored if less than 4096: Since the minimum iteration count is 4096, in only makes sense to mandate the maximum iteration count be greater than or equal to 4096.
  • Update Auth Spec to enforce a maximum iteration count with testing requirements similar to the what was done for the minimum iteration count.

@connorsmacd
connorsmacd requested a review from kevinAlbs June 29, 2026 18:47
@connorsmacd
connorsmacd marked this pull request as ready for review June 29, 2026 18:47
@connorsmacd
connorsmacd requested review from a team as code owners June 29, 2026 18:47
@codeowners-service-app
codeowners-service-app Bot requested a review from tadjik1 June 29, 2026 18:52
@codeowners-service-app

Copy link
Copy Markdown

Assigned tadjik1 for team dbx-spec-maintainers-auth because rozza is out of office.

Comment thread source/uri-options/uri-options.md
Comment thread source/uri-options/tests/auth-options.yml
Comment thread source/auth/auth.md
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.

Comment thread source/auth/auth.md
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.

#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.

Comment thread source/auth/auth.md
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))

Comment thread source/auth/auth.md
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

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).

@connorsmacd
connorsmacd force-pushed the scram-max-iterations.DRIVERS-3472 branch from 05a249e to 752a65d Compare July 10, 2026 18:19
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.

2 participants