From 7f6b658858533bfbc33edbec30d79099aeb0d021 Mon Sep 17 00:00:00 2001 From: Lance Ball Date: Mon, 24 May 2021 14:53:07 -0400 Subject: [PATCH] fix: throw on validation if extensions are improperly named (#420) Also fixes the case where UPPERCASED extension names were silently changed to lowercase and then set as undefined. Even though uppercased extension names are invalid, we should still accept them in incoming messsages and only throw when validating the event. Fixes: https://github.com/cloudevents/sdk-javascript/issues/380 Signed-off-by: Lance Ball --- src/event/spec.ts | 13 ++++++++++--- src/event/validation.ts | 2 +- src/message/http/index.ts | 5 +++-- test/integration/message_test.ts | 20 ++++++++++++++++++++ 4 files changed, 34 insertions(+), 6 deletions(-) diff --git a/src/event/spec.ts b/src/event/spec.ts index ec0bf07..1d308bb 100644 --- a/src/event/spec.ts +++ b/src/event/spec.ts @@ -28,14 +28,21 @@ export function validateCloudEvent(event: CloudEventV03 | CloudEventV1): boolean if (!isValidAgainstSchemaV1(event)) { throw new ValidationError("invalid payload", isValidAgainstSchemaV1.errors); } - return true; } else if (event.specversion === Version.V03) { if (!isValidAgainstSchemaV03(event)) { throw new ValidationError("invalid payload", isValidAgainstSchemaV03.errors); } - return checkDataContentEncoding(event); + checkDataContentEncoding(event); + } else { + return false; } - return false; + // attribute names must all be lowercase + for (const key in event) { + if (key !== key.toLowerCase()) { + throw new ValidationError(`invalid attribute name: ${key}`); + } + } + return true; } function checkDataContentEncoding(event: CloudEventV03): boolean { diff --git a/src/event/validation.ts b/src/event/validation.ts index ca43534..6279cce 100644 --- a/src/event/validation.ts +++ b/src/event/validation.ts @@ -19,7 +19,7 @@ export class ValidationError extends TypeError { // @ts-ignore errors?.reduce( (accum: string, err: Record) => - (accum as string).concat(` + accum.concat(` ${err instanceof Object ? JSON.stringify(err) : err}`), message, ) diff --git a/src/message/http/index.ts b/src/message/http/index.ts index ad6356f..029965e 100644 --- a/src/message/http/index.ts +++ b/src/message/http/index.ts @@ -151,7 +151,7 @@ function getVersion(mode: Mode, headers: Headers, body: string | Record { expect(HTTP.isEvent(message)).to.be.true; }); + it("Respects extension attribute casing (even if against spec)", () => { + // Now create a message that is an event + const message = { + body: `{ "greeting": "hello" }`, + headers: { + [CONSTANTS.CE_HEADERS.ID]: "1234", + [CONSTANTS.CE_HEADERS.SOURCE]: "test", + [CONSTANTS.CE_HEADERS.TYPE]: "test.event", + [CONSTANTS.CE_HEADERS.SPEC_VERSION]: Version.V1, + "ce-LUNCH": "tacos", + }, + }; + expect(HTTP.isEvent(message)).to.be.true; + const event: CloudEvent = HTTP.toEvent(message); + expect(event.LUNCH).to.equal("tacos"); + expect(function () { + event.validate(); + }).to.throw("invalid attribute name: LUNCH"); + }); + it("Can detect CloudEvent binary Messages with weird versions", () => { // Now create a message that is an event const message = {