You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[Suggestion] Apply operator whitelist option only for "external" provider by default #2445
Could be possible in the next version 5.x or current, to block all non-standard query operators for "external" provider and allow internally?
Migration could be frustrating if on API you use non-standard query operators internally (not client-side). 🥵
I understand that params on find, get, create, patch and remove, receive the provider key can easily identify if is secure allow non-whitelisted query operators.
If I understand your request, you could whitelist the entire set of query operators and then do a nested key search on the query object against a list of blocklist operators.
// given thisletparams={query: {$superSearch: "raw_string",createdAt: {$alt_lt: newDate().getTime()-10000},$or: [{archived: {$ne: true,$loop: [{yes:"no"}]}},{roomId: 2}]}}// a quick function to get all the keys as an arrayconstdeepKeys=(obj)=>{// get the keysreturnObject.keys(obj).reduce((res,el)=>{if(Array.isArray(obj[el])){return[...res,el, ...obj[el].map(deepKeys).flat()]}elseif(typeofobj[el]==='object'&&obj[el]!==null){return[...res,el, ...deepKeys(obj[el])];}return[...res,el];},[]);}// then the hook is a simple checklethook=(options)=>async(ctx)=>{letkeys=deepKeys(ctx.params.query)constfilteredArray=options.blacklist.filter(value=>keys.includes(value));if(filteredArray.length>0){newBadRequest('Invalid Query Parameters',{errors: 'Cannot use query parameters: '+filteredArray.join(" ")});}}hook({blacklist: ["$loop"]})({params})
@jamesvillarrubia sure, thanks for your example, but it's not what I'm referencing, but maybe could help to create a PR.
The current logic allows querying with whitelisted operators inclusive internally and externally, which is in fact a potential vulnerability.
const{ MyService }=require('./my-service.class');constcreateModel=require('../../models/my-service.model');consthooks=require('./my-service.hooks');module.exports=function(app){constoptions={Model: createModel(app),paginate: app.get('paginate'),whitelist: ['$populate','$regex','$options']// <--- Need to add operators to whitelist to use it inclusive for internal query};// Initialize our service with any options it requiresapp.use('/my-service',newMyService(options,app));// Get our initialized service so that we can register hooksconstservice=app.service('my-service');service.hooks(hooks);};
Proposal
So, I'm proposing to apply the service whitelist only to external providers by default, which can get from context.provider.
constoptions={Model: createModel(app),paginate: app.get('paginate'),whitelist: ['$populate','$regex','$options']// <--- Only apply to user request not internal query, ex: context.provider === 'external'};app.use('/my-service',newMyService(options,app));
That's because don't have the sense to apply restrictions to the server-side querying.
Whitelist as a function (extra proposal)
Also, would be cool if can set a function as a value for the whitelist option, where also could pass the context argument like this:
constoptions={Model: createModel(app),paginate: app.get('paginate'),whitelist: context=>{const{ ip }=context.params;if(fromVPC(ip))return['$where'];elsereturn['$populate'];}};app.use('/my-service',newMyService(options,app));
That will allow to customize different whitelist based on IP, or anything that comes in the context.
changed the title [-]Bypass whitelisting rules for non-external "provider"[/-][+][Suggestion] Apply operator whitelist option only for "external" provider by default[/+]on Oct 19, 2021
Activity
jamesvillarrubia commentedon Oct 19, 2021
Can you post an example?
If I understand your request, you could whitelist the entire set of query operators and then do a nested key search on the query object against a list of blocklist operators.
matiaslopezd commentedon Oct 19, 2021
@jamesvillarrubia sure, thanks for your example, but it's not what I'm referencing, but maybe could help to create a PR.
The current logic allows querying with whitelisted operators inclusive internally and externally, which is in fact a potential vulnerability.
Proposal
So, I'm proposing to apply the service whitelist only to
externalproviders by default, which can get fromcontext.provider.That's because don't have the sense to apply restrictions to the server-side querying.
Whitelist as a function (extra proposal)
Also, would be cool if can set a function as a value for the
whitelistoption, where also could pass thecontextargument like this:That will allow to customize different
whitelistbased on IP, or anything that comes in the context.[-]Bypass whitelisting rules for non-external "provider"[/-][+][Suggestion] Apply operator whitelist option only for "external" provider by default[/+]