From 9ab06046c5e142030a0ab298166bfdef8635e364 Mon Sep 17 00:00:00 2001 From: Serban Stancu Date: Wed, 21 Aug 2024 11:06:24 -0600 Subject: [PATCH] PDCL-12429 Return an empty string when invalid encoded URI components are encountered. --- .../injectAddQueryStringIdentityToPayload.js | 4 +-- .../in-app-message-actions/utils.js | 3 ++- src/utils/decodeUriComponentSafely.js | 19 +++++++++++++ .../utils/decodeUriComponentSafely.spec.js | 27 +++++++++++++++++++ 4 files changed, 50 insertions(+), 3 deletions(-) create mode 100644 src/utils/decodeUriComponentSafely.js create mode 100644 test/unit/specs/utils/decodeUriComponentSafely.spec.js diff --git a/src/components/Identity/injectAddQueryStringIdentityToPayload.js b/src/components/Identity/injectAddQueryStringIdentityToPayload.js index 167457326..a74e67a0f 100644 --- a/src/components/Identity/injectAddQueryStringIdentityToPayload.js +++ b/src/components/Identity/injectAddQueryStringIdentityToPayload.js @@ -15,6 +15,7 @@ governing permissions and limitations under the License. import { queryString } from "../../utils/index.js"; import queryStringIdentityParam from "../../constants/queryStringIdentityParam.js"; import ecidNamespace from "../../constants/ecidNamespace.js"; +import decodeUriComponentSafely from "../../utils/decodeUriComponentSafely.js"; const LINK_TTL_SECONDS = 300; // 5 minute link time to live @@ -46,8 +47,7 @@ export default ({ locationSearch, dateProvider, orgId, logger }) => // We are using MCMID and MCORGID to be compatible with Visitor. const ts = parseInt(properties.TS, 10); const mcmid = properties.MCMID; - const mcorgid = decodeURIComponent(properties.MCORGID); - + const mcorgid = decodeUriComponentSafely(properties.MCORGID); if ( // When TS is not specified or not a number, the following inequality returns false. // All inequalities with NaN variables are false. diff --git a/src/components/Personalization/in-app-message-actions/utils.js b/src/components/Personalization/in-app-message-actions/utils.js index fc3704ddf..31f3976f0 100644 --- a/src/components/Personalization/in-app-message-actions/utils.js +++ b/src/components/Personalization/in-app-message-actions/utils.js @@ -11,6 +11,7 @@ governing permissions and limitations under the License. */ import { isNonEmptyArray, queryString } from "../../../utils/index.js"; import { removeNode, selectNodes } from "../../../utils/dom/index.js"; +import decodeUriComponentSafely from "../../../utils/decodeUriComponentSafely.js"; export const removeElementById = (id) => { const element = selectNodes(`#${id}`, document); @@ -42,7 +43,7 @@ export const parseAnchor = (anchor) => { if (isNonEmptyArray(hrefParts)) { const queryParams = queryString.parse(hrefParts[1]); interaction = queryParams.interaction || ""; - link = decodeURIComponent(queryParams.link || ""); + link = decodeUriComponentSafely(queryParams.link || ""); } return { action, diff --git a/src/utils/decodeUriComponentSafely.js b/src/utils/decodeUriComponentSafely.js new file mode 100644 index 000000000..87b923fb0 --- /dev/null +++ b/src/utils/decodeUriComponentSafely.js @@ -0,0 +1,19 @@ +/* +Copyright 2024 Adobe. All rights reserved. +This file is licensed to you under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. You may obtain a copy +of the License at http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under +the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS +OF ANY KIND, either express or implied. See the License for the specific language +governing permissions and limitations under the License. +*/ + +export default (v) => { + try { + return decodeURIComponent(v); + } catch { + return ""; + } +}; diff --git a/test/unit/specs/utils/decodeUriComponentSafely.spec.js b/test/unit/specs/utils/decodeUriComponentSafely.spec.js new file mode 100644 index 000000000..2f8f64186 --- /dev/null +++ b/test/unit/specs/utils/decodeUriComponentSafely.spec.js @@ -0,0 +1,27 @@ +/* +Copyright 2020 Adobe. All rights reserved. +This file is licensed to you under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. You may obtain a copy +of the License at http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under +the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS +OF ANY KIND, either express or implied. See the License for the specific language +governing permissions and limitations under the License. +*/ + +import decodeUriComponentSafely from "../../../../src/utils/decodeUriComponentSafely.js"; + +describe("decodeUriComponentSafely", () => { + it("decodes a uri encoded string", () => { + expect(decodeUriComponentSafely("%3Fx%3Dtest")).toEqual("?x=test"); + }); + + it("returns an empty string when an invalid encoded URI component is provided", () => { + expect( + decodeUriComponentSafely( + "MCORGID%3D5BFE274A5F6980A50A495C08%2540AdobeOrg%ttt", + ), + ).toEqual(""); + }); +});