Skip to content

Commit 237c9ab

Browse files
fix(NODE-7477): OIDC host allowlist fix (#4896)
1 parent fa11559 commit 237c9ab

File tree

3 files changed

+50
-7
lines changed

3 files changed

+50
-7
lines changed

.github/workflows/codeql.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@ name: "CodeQL"
22

33
on:
44
push:
5-
branches: [ "main", "5.x" ]
5+
branches: [ "main", "v7.1.x" ]
66
pull_request:
7-
branches: [ "main", "5.x" ]
7+
branches: [ "main", "v7.1.x" ]
88

99
jobs:
1010
analyze:

src/utils.ts

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -83,13 +83,27 @@ export function isUint8Array(value: unknown): value is Uint8Array {
8383
*/
8484
export function hostMatchesWildcards(host: string, wildcards: string[]): boolean {
8585
for (const wildcard of wildcards) {
86-
if (
87-
host === wildcard ||
88-
(wildcard.startsWith('*.') && host?.endsWith(wildcard.substring(2, wildcard.length))) ||
89-
(wildcard.startsWith('*/') && host?.endsWith(wildcard.substring(2, wildcard.length)))
90-
) {
86+
// Exact match always wins
87+
if (host === wildcard) {
9188
return true;
9289
}
90+
91+
// Wildcard match with leading *.
92+
if (wildcard.startsWith('*.')) {
93+
const suffix = wildcard.substring(2);
94+
// Exact match or strict subdomain match
95+
if (host === suffix || host.endsWith(`.${suffix}`)) {
96+
return true;
97+
}
98+
}
99+
// Wildcard match with leading */
100+
if (wildcard.startsWith('*/')) {
101+
const suffix = wildcard.substring(2);
102+
// Exact match or strict subpath match
103+
if (host === suffix || host.endsWith(`/${suffix}`)) {
104+
return true;
105+
}
106+
}
93107
}
94108
return false;
95109
}

test/unit/utils.test.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { ObjectId } from 'bson';
44
import { expect } from 'chai';
55
import * as sinon from 'sinon';
66

7+
import { DEFAULT_ALLOWED_HOSTS } from '../../src/cmap/auth/mongo_credentials';
78
import { LEGACY_HELLO_COMMAND } from '../../src/constants';
89
import { MongoInvalidArgumentError, MongoRuntimeError } from '../../src/error';
910
import { decorateWithExplain, Explain } from '../../src/explain';
@@ -148,6 +149,26 @@ describe('driver utils', function () {
148149
});
149150
});
150151

152+
context('when the wildcard starts with *.', function () {
153+
it('returns false', function () {
154+
expect(hostMatchesWildcards('test-mongodb.com', ['*.mongodb.com', 'test2'])).to.be
155+
.false;
156+
});
157+
});
158+
159+
context('when using default allowed hosts', function () {
160+
it('returns false', function () {
161+
for (const host of DEFAULT_ALLOWED_HOSTS) {
162+
// Only test the wildcard hosts, the non-wildcard hosts are tested in other test cases
163+
if (!host.startsWith('*.')) {
164+
continue;
165+
}
166+
const wrongHost = host.replace('*.', 'test-');
167+
expect(hostMatchesWildcards(wrongHost, DEFAULT_ALLOWED_HOSTS)).to.be.false;
168+
}
169+
});
170+
});
171+
151172
context('when the host matches a FQDN', function () {
152173
it('returns true', function () {
153174
expect(hostMatchesWildcards('mongodb.net', ['*.mongodb.net', 'other'])).to.be.true;
@@ -221,6 +242,14 @@ describe('driver utils', function () {
221242
.to.be.false;
222243
});
223244
});
245+
246+
context('when the host does not match partial matches', function () {
247+
it('returns false', function () {
248+
expect(
249+
hostMatchesWildcards('/tmp/test-mongodb-27017.sock', ['*/mongodb-27017.sock', 'test2'])
250+
).to.be.false;
251+
});
252+
});
224253
});
225254
});
226255

0 commit comments

Comments
 (0)