diff --git a/packages/faucet/src/api/requestparser.spec.ts b/packages/faucet/src/api/requestparser.spec.ts index 73512029..aeb53e38 100644 --- a/packages/faucet/src/api/requestparser.spec.ts +++ b/packages/faucet/src/api/requestparser.spec.ts @@ -7,6 +7,18 @@ describe("RequestParser", () => { }); it("throws for invalid credit requests", () => { + // body not a dictionary + { + expect(() => RequestParser.parseCreditBody("foo")).toThrowError(/Request body must be a dictionary./i); + expect(() => RequestParser.parseCreditBody(null)).toThrowError(/Request body must be a dictionary./i); + expect(() => RequestParser.parseCreditBody(42)).toThrowError(/Request body must be a dictionary./i); + expect(() => RequestParser.parseCreditBody([])).toThrowError(/Request body must be a dictionary./i); + expect(() => RequestParser.parseCreditBody(true)).toThrowError(/Request body must be a dictionary./i); + expect(() => RequestParser.parseCreditBody(undefined)).toThrowError( + /Request body must be a dictionary./i, + ); + } + // address unset { const body = { ticker: "TKN" }; diff --git a/packages/faucet/src/api/requestparser.ts b/packages/faucet/src/api/requestparser.ts index db938f73..77dda0f7 100644 --- a/packages/faucet/src/api/requestparser.ts +++ b/packages/faucet/src/api/requestparser.ts @@ -1,3 +1,5 @@ +import { isNonNullObject } from "@cosmjs/utils"; + import { HttpError } from "./httperror"; export interface CreditRequestBodyData { @@ -8,8 +10,12 @@ export interface CreditRequestBodyData { } export class RequestParser { - public static parseCreditBody(body: any): CreditRequestBodyData { - const { address, ticker } = body; + public static parseCreditBody(body: unknown): CreditRequestBodyData { + if (!isNonNullObject(body) || Array.isArray(body)) { + throw new HttpError(400, "Request body must be a dictionary."); + } + + const { address, ticker } = body as any; if (typeof address !== "string") { throw new HttpError(400, "Property 'address' must be a string."); diff --git a/packages/utils/src/typechecks.ts b/packages/utils/src/typechecks.ts index 664fcc53..40faa05d 100644 --- a/packages/utils/src/typechecks.ts +++ b/packages/utils/src/typechecks.ts @@ -1,5 +1,10 @@ /** - * Checks if data is a non-null object (i.e. matches the TypeScript object type) + * Checks if data is a non-null object (i.e. matches the TypeScript object type). + * + * Note: this returns true for arrays, which are objects in JavaScript + * even though array and object are different types in JSON. + * + * @see https://www.typescriptlang.org/docs/handbook/basic-types.html#object */ export function isNonNullObject(data: unknown): data is object { return typeof data === "object" && data !== null; diff --git a/packages/utils/types/typechecks.d.ts b/packages/utils/types/typechecks.d.ts index 3e911797..68c29628 100644 --- a/packages/utils/types/typechecks.d.ts +++ b/packages/utils/types/typechecks.d.ts @@ -1,5 +1,10 @@ /** - * Checks if data is a non-null object (i.e. matches the TypeScript object type) + * Checks if data is a non-null object (i.e. matches the TypeScript object type). + * + * Note: this returns true for arrays, which are objects in JavaScript + * even though array and object are different types in JSON. + * + * @see https://www.typescriptlang.org/docs/handbook/basic-types.html#object */ export declare function isNonNullObject(data: unknown): data is object; /**