Skip to content

Commit 163e664

Browse files
authored
fix(mongodb): Ensure arbitrary objects can't be passed as MongoDB ids (#3664)
1 parent ddb9b9c commit 163e664

File tree

2 files changed

+62
-0
lines changed

2 files changed

+62
-0
lines changed

packages/mongodb/src/adapter.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,9 @@ export class MongoDbAdapter<
8686
const { $select, $sort, $limit: _limit, $skip = 0, ...query } = (params.query || {}) as AdapterQuery
8787
const $limit = getLimit(_limit, options.paginate)
8888
if (id !== null) {
89+
if (typeof id !== 'string' && typeof id !== 'number' && !(id instanceof ObjectId)) {
90+
throw new BadRequest(`Invalid id '${JSON.stringify(id)}'`)
91+
}
8992
query.$and = (query.$and || []).concat({
9093
[this.id]: this.getObjectId(id)
9194
})

packages/mongodb/test/index.test.ts

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -839,6 +839,65 @@ describe('Feathers MongoDB Service', () => {
839839
})
840840
})
841841

842+
describe('NoSQL injection via object id', () => {
843+
let target: Person
844+
845+
beforeEach(async () => {
846+
target = await app.service('people').create({ name: 'Target' })
847+
})
848+
849+
afterEach(async () => {
850+
try {
851+
await app.service('people').remove(target._id)
852+
} catch (e: unknown) {}
853+
})
854+
855+
it('rejects object as id in get', async () => {
856+
await assert.rejects(
857+
() => app.service('people').get({ $ne: null } as any),
858+
{
859+
name: 'BadRequest'
860+
}
861+
)
862+
})
863+
864+
it('rejects object as id in remove', async () => {
865+
await assert.rejects(
866+
() => app.service('people').remove({ $ne: null } as any),
867+
{
868+
name: 'BadRequest'
869+
}
870+
)
871+
})
872+
873+
it('rejects object as id in update', async () => {
874+
await assert.rejects(
875+
() => app.service('people').update({ $ne: null } as any, { name: 'Hacked' }),
876+
{
877+
name: 'BadRequest'
878+
}
879+
)
880+
})
881+
882+
it('rejects object as id in patch', async () => {
883+
await assert.rejects(
884+
() => app.service('people').patch({ $ne: null } as any, { name: 'Hacked' }),
885+
{
886+
name: 'BadRequest'
887+
}
888+
)
889+
})
890+
891+
it('rejects regex operator as id', async () => {
892+
await assert.rejects(
893+
() => app.service('people').get({ $regex: '^' } as any),
894+
{
895+
name: 'BadRequest'
896+
}
897+
)
898+
})
899+
})
900+
842901
testSuite(app, errors, 'people', '_id')
843902
testSuite(app, errors, 'people-customid', 'customid')
844903
})

0 commit comments

Comments
 (0)