diff --git a/src/webresource-handler/index.ts b/src/webresource-handler/index.ts index bd0fc5972..8f4cba539 100644 --- a/src/webresource-handler/index.ts +++ b/src/webresource-handler/index.ts @@ -67,6 +67,7 @@ export const getWebresourceHandler = (): WebResourceHandler | undefined => { const isFileInValidPath = async ( fieldname: string, req: Express.Request, + odataRequest: uriParser.ParsedODataRequest, ): Promise => { if (req.method !== 'POST' && req.method !== 'PATCH') { return false; @@ -77,10 +78,6 @@ const isFileInValidPath = async ( return false; } const model = getModel(apiRoot); - const odataRequest = uriParser.parseOData({ - url: req.url, - method: req.method, - }); const sqlResourceName = sbvrUtils.resolveSynonym(odataRequest); const table = model.abstractSql.tables[sqlResourceName]; @@ -124,6 +121,15 @@ export const getUploaderMiddlware = ( const bb = busboy({ headers: req.headers }); let isAborting = false; + const parsedOdataRequest = uriParser.parseOData({ + url: req.url, + method: req.method, + }); + const webResourcesFieldNames = getWebResourceFields( + parsedOdataRequest, + false, + ); + const finishFileUpload = () => { req.unpipe(bb); req.on('readable', req.read.bind(req)); @@ -151,7 +157,9 @@ export const getUploaderMiddlware = ( completeUploads.push( (async () => { try { - if (!(await isFileInValidPath(fieldname, req))) { + if ( + !(await isFileInValidPath(fieldname, req, parsedOdataRequest)) + ) { filestream.resume(); return; } @@ -183,6 +191,14 @@ export const getUploaderMiddlware = ( // This receives the form fields and transforms them into a standard JSON body // This is a similar behavior as previous multer library did bb.on('field', (name, val) => { + if (webResourcesFieldNames.includes(name)) { + isAborting = true; + bb.emit( + 'error', + new errors.BadRequestError('WebResource field must be a blob.'), + ); + return; + } req.body[name] = val; }); @@ -207,17 +223,17 @@ export const getUploaderMiddlware = ( } }); - bb.on('error', async (err) => { + bb.on('error', async (err: Error) => { await clearFiles(); finishFileUpload(); - next(err); + sbvrUtils.handleHttpErrors(req, res, err); }); req.pipe(bb); }; }; const getWebResourceFields = ( - request: uriParser.ODataRequest, + request: uriParser.ODataRequest | uriParser.ParsedODataRequest, useTranslations = true, ): string[] => { // Translations will use modifyFields(translated) rather than fields(original) so we need to diff --git a/test/06-webresource.test.ts b/test/06-webresource.test.ts index ad222ee5c..4b4497cf9 100644 --- a/test/06-webresource.test.ts +++ b/test/06-webresource.test.ts @@ -484,6 +484,16 @@ describe('06 webresources tests', function () { expect(await isEventuallyDeleted(uniqueFilename)).to.be.true; }); + it('should not accept webresource payload that is not a blob', async () => { + const res = await supertest(testLocalServer) + .post(`/${resourceName}/organization`) + .field('name', 'John') + .field(resourcePath, 'not a blob') + .expect(400); + + expect(res.body).to.equal('WebResource field must be a blob.'); + }); + it('should not accept webresource payload on application/json requests', async () => { const uniqueFilename = `${randomUUID()}_${filename}`;