Skip to content
This repository has been archived by the owner on Apr 13, 2023. It is now read-only.

Commit

Permalink
fix: add optional input validation (#193)
Browse files Browse the repository at this point in the history
  • Loading branch information
ssvegaraju committed Jan 24, 2023
1 parent 480b0ec commit e8d9c8d
Show file tree
Hide file tree
Showing 6 changed files with 165 additions and 8 deletions.
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
"http-errors": "^1.8.0",
"lodash": "^4.17.15",
"mime-types": "^2.1.26",
"sanitize-html": "^2.8.0",
"serverless-http": "^2.3.1",
"uuid": "^3.4.0"
},
Expand All @@ -56,6 +57,7 @@
"@types/mime-types": "^2.1.0",
"@types/mock-req-res": "^1.1.2",
"@types/node": "^12",
"@types/sanitize-html": "^2.8.0",
"@types/uuid": "^3.4.7",
"@typescript-eslint/eslint-plugin": "^4.33.0",
"@typescript-eslint/parser": "^4.33.0",
Expand All @@ -74,7 +76,7 @@
"standard-version": "^9.3.2",
"supertest": "^6.1.6",
"ts-jest": "^26.4.4",
"typescript": "^4.1.3"
"typescript": "^4.9.4"
},
"resolutions": {
"path-parse": "^1.0.7",
Expand Down
30 changes: 30 additions & 0 deletions src/router/handlers/resourceHandler.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import OperationsGenerator from '../operationsGenerator';
import ElasticSearchService from '../__mocks__/elasticSearchService';
import DynamoDbDataService from '../__mocks__/dynamoDbDataService';
import JsonSchemaValidator from '../validation/jsonSchemaValidator';
import { validateXHTMLResource } from './utils';

const enum SEARCH_PAGINATION_PARAMS {
PAGES_OFFSET = '_getpagesoffset',
Expand Down Expand Up @@ -1061,3 +1062,32 @@ describe('Testing history', () => {
});
});
});

describe('Testing xhtml validation', () => {
test('valid patient resource is not affected', () => {
// BUILD & OPERATE
const validatedPatient = validateXHTMLResource(validPatient);

// CHECK
expect(validatedPatient).toBe(true);
});

test('invalid patient resource is filtered', () => {
// BUILD
const scriptedPatient = {
...validPatient,
name: [
{
family: '<script>alert(123);</script>Levin',
given: ['Henry'],
},
],
};
scriptedPatient.name[0].family = '<script>alert(123);</script>Levin';
// OPERATE
const validatedPatient = validateXHTMLResource(scriptedPatient);

// CHECK
expect(validatedPatient).toBe(false);
});
});
13 changes: 11 additions & 2 deletions src/router/handlers/resourceHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,14 +47,23 @@ export default class ResourceHandler implements CrudHandlerInterface {
async create(resourceType: string, resource: any, tenantId?: string) {
await validateResource(this.validators, resourceType, resource, { tenantId, typeOperation: 'create' });

const createResponse = await this.dataService.createResource({ resourceType, resource, tenantId });
const createResponse = await this.dataService.createResource({
resourceType,
resource,
tenantId,
});
return createResponse.resource;
}

async update(resourceType: string, id: string, resource: any, tenantId?: string) {
await validateResource(this.validators, resourceType, resource, { tenantId, typeOperation: 'update' });

const updateResponse = await this.dataService.updateResource({ resourceType, id, resource, tenantId });
const updateResponse = await this.dataService.updateResource({
resourceType,
id,
resource,
tenantId,
});
return updateResponse.resource;
}

Expand Down
16 changes: 15 additions & 1 deletion src/router/handlers/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,19 @@
*/

import { createHash } from 'crypto';
import sanitizeHTML, { defaults } from 'sanitize-html';

export const hash = (o: any): string => createHash('sha256').update(JSON.stringify(o)).digest('hex');
export const hash = (o: any): any => createHash('sha256').update(JSON.stringify(o)).digest('hex');

export const validateXHTMLResource = (resource: any): boolean => {
// we want to ignore the text field as it requires unencoded html as per the FHIR spec
// https://www.hl7.org/fhir/datatypes-definitions.html#HumanName.text (for example)
const originalResource = JSON.stringify({ ...resource, text: {} });
const validatedResource = sanitizeHTML(originalResource, {
allowedAttributes: {
...defaults.allowedAttributes,
div: ['xmlns'],
},
});
return originalResource === validatedResource;
};
4 changes: 4 additions & 0 deletions src/router/validation/validationUtilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
*/

import { InvalidResourceError, TypeOperation, Validator } from 'fhir-works-on-aws-interface';
import { validateXHTMLResource } from '../handlers/utils';

export async function validateResource(
validators: Validator[],
Expand All @@ -14,6 +15,9 @@ export async function validateResource(
if (resourceType !== resource.resourceType) {
throw new InvalidResourceError(`not a valid '${resourceType}'`);
}
if (process.env.VALIDATE_XHTML === 'true' && !validateXHTMLResource(resource)) {
throw new InvalidResourceError(`invalid resource html present in ${resourceType}`);
}
for (let i = 0; i < validators.length; i += 1) {
// eslint-disable-next-line no-await-in-loop
await validators[i].validate(resource, params);
Expand Down
106 changes: 102 additions & 4 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -839,6 +839,13 @@
resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.4.tgz#cd667bcfdd025213aafb7ca5915a932590acdcdc"
integrity sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==

"@types/sanitize-html@^2.8.0":
version "2.8.0"
resolved "https://registry.yarnpkg.com/@types/sanitize-html/-/sanitize-html-2.8.0.tgz#c53d3114d832734fc299568a3458a49f9edc1eef"
integrity sha512-Uih6caOm3DsBYnVGOYn0A9NoTNe1c4aPStmHC/YA2JrpP9kx//jzaRcIklFvSpvVQEcpl/ZCr4DgISSf/YxTvg==
dependencies:
htmlparser2 "^8.0.0"

"@types/serve-static@*":
version "1.13.10"
resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.13.10.tgz#f5e0ce8797d2d7cc5ebeda48a52c96c4fa47a8d9"
Expand Down Expand Up @@ -2084,13 +2091,43 @@ doctrine@^3.0.0:
dependencies:
esutils "^2.0.2"

dom-serializer@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-2.0.0.tgz#e41b802e1eedf9f6cae183ce5e622d789d7d8e53"
integrity sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==
dependencies:
domelementtype "^2.3.0"
domhandler "^5.0.2"
entities "^4.2.0"

domelementtype@^2.3.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.3.0.tgz#5c45e8e869952626331d7aab326d01daf65d589d"
integrity sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==

domexception@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/domexception/-/domexception-2.0.1.tgz#fb44aefba793e1574b0af6aed2801d057529f304"
integrity sha512-yxJ2mFy/sibVQlu5qHjOkf9J3K6zgmCxgJ94u2EdvDOV09H+32LtRswEcUsmUWN72pVLOEnTSRaIVVzVQgS0dg==
dependencies:
webidl-conversions "^5.0.0"

domhandler@^5.0.1, domhandler@^5.0.2:
version "5.0.3"
resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-5.0.3.tgz#cc385f7f751f1d1fc650c21374804254538c7d31"
integrity sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==
dependencies:
domelementtype "^2.3.0"

domutils@^3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/domutils/-/domutils-3.0.1.tgz#696b3875238338cb186b6c0612bd4901c89a4f1c"
integrity sha512-z08c1l761iKhDFtfXO04C7kTdPBLi41zwOZl00WS8b5eiaebNpY00HKbztwBq+e3vyqWNwWF3mP9YLUeqIrF+Q==
dependencies:
dom-serializer "^2.0.0"
domelementtype "^2.3.0"
domhandler "^5.0.1"

dot-prop@^5.1.0:
version "5.3.0"
resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-5.3.0.tgz#90ccce708cd9cd82cc4dc8c3ddd9abdd55b20e88"
Expand Down Expand Up @@ -2157,6 +2194,11 @@ enquirer@^2.3.5:
dependencies:
ansi-colors "^4.1.1"

entities@^4.2.0, entities@^4.3.0:
version "4.4.0"
resolved "https://registry.yarnpkg.com/entities/-/entities-4.4.0.tgz#97bdaba170339446495e653cfd2db78962900174"
integrity sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA==

error-ex@^1.3.1:
version "1.3.2"
resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf"
Expand Down Expand Up @@ -3038,6 +3080,16 @@ html-escaper@^2.0.0:
resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453"
integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==

htmlparser2@^8.0.0:
version "8.0.1"
resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-8.0.1.tgz#abaa985474fcefe269bc761a779b544d7196d010"
integrity sha512-4lVbmc1diZC7GUJQtRQ5yBAeUCL1exyMwmForWkRLnwyzWBFxN633SALPMGYaWZvKe9j1pRZJpauvmxENSp/EA==
dependencies:
domelementtype "^2.3.0"
domhandler "^5.0.2"
domutils "^3.0.1"
entities "^4.3.0"

http-errors@1.8.1:
version "1.8.1"
resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.8.1.tgz#7c3f28577cbc8a207388455dbd62295ed07bd68c"
Expand Down Expand Up @@ -3356,6 +3408,11 @@ is-plain-object@^2.0.4:
dependencies:
isobject "^3.0.1"

is-plain-object@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-5.0.0.tgz#4427f50ab3429e9025ea7d52e9043a9ef4159344"
integrity sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==

is-potential-custom-element-name@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz#171ed6f19e3ac554394edf78caa05784a45bebb5"
Expand Down Expand Up @@ -4344,6 +4401,11 @@ ms@2.1.3, ms@^2.1.1:
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==

nanoid@^3.3.4:
version "3.3.4"
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.4.tgz#730b67e3cd09e2deacf03c027c81c9d9dbc5e8ab"
integrity sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==

nanomatch@^1.2.9:
version "1.2.13"
resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119"
Expand Down Expand Up @@ -4698,6 +4760,11 @@ parse-json@^5.0.0:
json-parse-even-better-errors "^2.3.0"
lines-and-columns "^1.1.6"

parse-srcset@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/parse-srcset/-/parse-srcset-1.0.2.tgz#f2bd221f6cc970a938d88556abc589caaaa2bde1"
integrity sha512-/2qh0lav6CmI15FzA3i/2Bzk2zCgQhGMkvhOhKNcBVQ1ldgpbfiNTVslmooUmWJcADi1f1kIeynbDRVzNlfR6Q==

parse5@6.0.1:
version "6.0.1"
resolved "https://registry.yarnpkg.com/parse5/-/parse5-6.0.1.tgz#e1a1c085c569b3dc08321184f19a39cc27f7c30b"
Expand Down Expand Up @@ -4793,6 +4860,11 @@ picocolors@^0.2.1:
resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-0.2.1.tgz#570670f793646851d1ba135996962abad587859f"
integrity sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==

picocolors@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c"
integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==

picomatch@^2.0.4, picomatch@^2.2.3:
version "2.3.0"
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.0.tgz#f1f061de8f6a4bf022892e2d128234fb98302972"
Expand Down Expand Up @@ -4841,6 +4913,15 @@ posix-character-classes@^0.1.0:
resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab"
integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=

postcss@^8.3.11:
version "8.4.21"
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.21.tgz#c639b719a57efc3187b13a1d765675485f4134f4"
integrity sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg==
dependencies:
nanoid "^3.3.4"
picocolors "^1.0.0"
source-map-js "^1.0.2"

postgres-array@~2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/postgres-array/-/postgres-array-2.0.0.tgz#48f8fce054fbc69671999329b8834b772652d82e"
Expand Down Expand Up @@ -5201,6 +5282,18 @@ sane@^4.0.3:
minimist "^1.1.1"
walker "~1.0.5"

sanitize-html@^2.8.0:
version "2.8.1"
resolved "https://registry.yarnpkg.com/sanitize-html/-/sanitize-html-2.8.1.tgz#319c4fdba67e1edf35b1fd6d9362210044826d47"
integrity sha512-qK5neD0SaMxGwVv5txOYv05huC3o6ZAA4h5+7nJJgWMNFUNRjcjLO6FpwAtKzfKCZ0jrG6xTk6eVFskbvOGblg==
dependencies:
deepmerge "^4.2.2"
escape-string-regexp "^4.0.0"
htmlparser2 "^8.0.0"
is-plain-object "^5.0.0"
parse-srcset "^1.0.2"
postcss "^8.3.11"

sax@1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.1.tgz#7b8e656190b228e81a66aea748480d828cd2d37a"
Expand Down Expand Up @@ -5417,6 +5510,11 @@ snapdragon@^0.8.1:
source-map-resolve "^0.5.0"
use "^3.1.0"

source-map-js@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c"
integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==

source-map-resolve@^0.5.0:
version "0.5.3"
resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a"
Expand Down Expand Up @@ -5961,10 +6059,10 @@ typedarray@^0.0.6:
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=

typescript@^4.1.3:
version "4.4.3"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.4.3.tgz#bdc5407caa2b109efd4f82fe130656f977a29324"
integrity sha512-4xfscpisVgqqDfPaJo5vkd+Qd/ItkoagnHpufr+i2QCHBsNYp+G7UAoyFl8aPtx879u38wPV65rZ8qbGZijalA==
typescript@^4.9.4:
version "4.9.4"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.9.4.tgz#a2a3d2756c079abda241d75f149df9d561091e78"
integrity sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg==

uglify-js@^3.1.4:
version "3.14.3"
Expand Down

0 comments on commit e8d9c8d

Please sign in to comment.