Skip to content

Commit 2f7a2bf

Browse files
fix(NODE-5289): prevent scram auth from throwing TypeError if saslprep is not a function (#3727)
1 parent 0e1afc0 commit 2f7a2bf

File tree

3 files changed

+70
-124
lines changed

3 files changed

+70
-124
lines changed

src/cmap/auth/scram.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,10 @@ class ScramSHA extends AuthProvider {
3030
if (!credentials) {
3131
return callback(new MongoMissingCredentialsError('AuthContext must provide credentials.'));
3232
}
33-
if (cryptoMethod === 'sha256' && saslprep == null) {
33+
if (
34+
cryptoMethod === 'sha256' &&
35+
('kModuleError' in saslprep || typeof saslprep !== 'function')
36+
) {
3437
emitWarning('Warning: no saslprep library specified. Passwords will not be sanitized');
3538
}
3639

@@ -152,7 +155,8 @@ function continueScramConversation(
152155

153156
let processedPassword;
154157
if (cryptoMethod === 'sha256') {
155-
processedPassword = 'kModuleError' in saslprep ? password : saslprep(password);
158+
processedPassword =
159+
'kModuleError' in saslprep || typeof saslprep !== 'function' ? password : saslprep(password);
156160
} else {
157161
try {
158162
processedPassword = passwordDigest(username, password);

test/integration/auth/scram_sha_256.test.js

Lines changed: 0 additions & 122 deletions
This file was deleted.
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import { expect } from 'chai';
2+
import * as sinon from 'sinon';
3+
4+
// eslint-disable-next-line @typescript-eslint/no-restricted-imports
5+
import * as deps from '../../../src/deps';
6+
import { type MongoClient } from '../../mongodb';
7+
8+
describe('SCRAM_SHA_256', function () {
9+
beforeEach(function () {
10+
if (!this.configuration.parameters.authenticationMechanisms.includes('SCRAM-SHA-256')) {
11+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
12+
this.currentTest!.skipReason = 'Test requires that SCRAM-SHA-256 be enabled on the server.';
13+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
14+
this.currentTest!.skip();
15+
}
16+
});
17+
18+
context('when saslprep is not a function', () => {
19+
let client: MongoClient;
20+
21+
beforeEach(function () {
22+
sinon.stub(deps, 'saslprep').value({});
23+
client = this.configuration.newClient({ authMechanism: 'SCRAM-SHA-256' });
24+
});
25+
26+
afterEach(() => {
27+
sinon.restore();
28+
return client.close();
29+
});
30+
31+
it('does not throw an error', { requires: { auth: 'enabled' } }, async function () {
32+
await client.connect();
33+
});
34+
35+
it('emits a warning', { requires: { auth: 'enabled' } }, async function () {
36+
const warnings: Array<Error> = [];
37+
process.once('warning', w => warnings.push(w));
38+
await client.connect();
39+
expect(warnings).to.have.lengthOf(1);
40+
expect(warnings[0]).to.have.property(
41+
'message',
42+
'Warning: no saslprep library specified. Passwords will not be sanitized'
43+
);
44+
});
45+
});
46+
47+
context('when saslprep is a function', () => {
48+
let client: MongoClient;
49+
50+
beforeEach(function () {
51+
client = this.configuration.newClient({ authMechanism: 'SCRAM-SHA-256' });
52+
});
53+
54+
afterEach(() => client.close());
55+
56+
it('calls saslprep', { requires: { auth: 'enabled' } }, async function () {
57+
const spy = sinon.spy(deps, 'saslprep');
58+
59+
await client.connect();
60+
61+
expect(spy).to.have.been.called;
62+
});
63+
});
64+
});

0 commit comments

Comments
 (0)