From e32f45d1a31b3ea3abc544182768e34ae33a9bdb Mon Sep 17 00:00:00 2001 From: Chris Date: Wed, 4 Dec 2024 09:57:45 -0800 Subject: [PATCH 1/3] fix(urltranslator.ts): gracefully catch malformed uri errors --- .../src/Translators/Url/UrlTranslator.ts | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/packages/snap-url-manager/src/Translators/Url/UrlTranslator.ts b/packages/snap-url-manager/src/Translators/Url/UrlTranslator.ts index 778404948..ec2bf556b 100644 --- a/packages/snap-url-manager/src/Translators/Url/UrlTranslator.ts +++ b/packages/snap-url-manager/src/Translators/Url/UrlTranslator.ts @@ -148,13 +148,18 @@ export class UrlTranslator implements Translator { .split('&') .filter((v) => v) .map((kvPair) => { - const [key, value] = kvPair.split('=').map((v) => decodeURIComponent(v.replace(/\+/g, ' '))); - return { key: key.split('.'), value, type: ParamLocationType.query }; + try { + const [key, value] = kvPair.split('=').map((v) => decodeURIComponent(v.replace(/\+/g, ' '))); + return { key: key.split('.'), value, type: ParamLocationType.query }; + } catch (err) { + console.error('Uncaught URIError: URI malformed', kvPair); + return { key: ['ss__delete'], value: 'ss__delete', type: ParamLocationType.query }; + } }) .filter((param) => { // remove core fields that do not contain a value const isCoreField = this.reverseMapping[param.key[0]]; - return !isCoreField || (isCoreField && param.value); + return param.value !== 'ss__delete' ? !isCoreField || (isCoreField && param.value) : ''; }); } From b17963316fc8a14676f4a23fa18b527703187351 Mon Sep 17 00:00:00 2001 From: Chris Date: Thu, 5 Dec 2024 13:12:40 -0800 Subject: [PATCH 2/3] refactor(urltranslator.ts): add safety try catch aroun hash & query param decoding --- .../src/Translators/Url/UrlTranslator.test.ts | 23 +++++++++++++++++++ .../src/Translators/Url/UrlTranslator.ts | 13 +++++++---- 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/packages/snap-url-manager/src/Translators/Url/UrlTranslator.test.ts b/packages/snap-url-manager/src/Translators/Url/UrlTranslator.test.ts index 081b40729..6653cb0d1 100644 --- a/packages/snap-url-manager/src/Translators/Url/UrlTranslator.test.ts +++ b/packages/snap-url-manager/src/Translators/Url/UrlTranslator.test.ts @@ -16,6 +16,29 @@ describe('UrlTranslator', () => { expect(urlTranslator.serialize({})).toBe('/'); }); + it('gracefully fails with malformed uri in hash', () => { + const url = 'http://example.com#/valid:true/utm_campaign:BFCM%2020%OFF%20Perfumes%20TEST%20(28.11.24)%20(clone)/valid2:truueee'; + const urlTranslator = new UrlTranslator(); + // @ts-ignore + expect(urlTranslator.parseHashString(url)).toStrictEqual([ + { key: ['http'], type: 'hash', value: '' }, + { key: ['example.com'], type: 'hash', value: '' }, + { key: ['valid'], type: 'hash', value: 'true' }, + { key: ['valid2'], type: 'hash', value: 'truueee' }, + ]); + }); + + it('gracefully fails with malformed uri in query', () => { + const url = 'http://example.com?valid=true&utm_campaign=BFCM:%2020%OFF%20Perfumes%20TEST%20(28.11.24)%20(clone)&valid2=truueee'; + const urlTranslator = new UrlTranslator(); + + // @ts-ignore + expect(urlTranslator.parseQueryString(url)).toStrictEqual([ + { key: ['valid'], type: 'query', value: 'true' }, + { key: ['valid2'], type: 'query', value: 'truueee' }, + ]); + }); + it('prepends urlRoot when provided', () => { const url = 'http://example.com?bar=baz'; class customTranslator extends UrlTranslator { diff --git a/packages/snap-url-manager/src/Translators/Url/UrlTranslator.ts b/packages/snap-url-manager/src/Translators/Url/UrlTranslator.ts index ec2bf556b..307fcc225 100644 --- a/packages/snap-url-manager/src/Translators/Url/UrlTranslator.ts +++ b/packages/snap-url-manager/src/Translators/Url/UrlTranslator.ts @@ -152,12 +152,12 @@ export class UrlTranslator implements Translator { const [key, value] = kvPair.split('=').map((v) => decodeURIComponent(v.replace(/\+/g, ' '))); return { key: key.split('.'), value, type: ParamLocationType.query }; } catch (err) { - console.error('Uncaught URIError: URI malformed', kvPair); + console.warn('Snap UrlTranslator: URI malformed - ignoring parameter', kvPair); return { key: ['ss__delete'], value: 'ss__delete', type: ParamLocationType.query }; } }) .filter((param) => { - // remove core fields that do not contain a value + // remove core fields that do not contain a value or had malformed data const isCoreField = this.reverseMapping[param.key[0]]; return param.value !== 'ss__delete' ? !isCoreField || (isCoreField && param.value) : ''; }); @@ -170,10 +170,15 @@ export class UrlTranslator implements Translator { .split('/') .filter((v) => v) .map((hashEntries) => { - return hashEntries.split(':').map((v) => decodeHashComponent(v)); + try { + return hashEntries.split(':').map((v) => decodeHashComponent(v)); + } catch (err) { + console.warn('Snap UrlTranslator: URI malformed - ignoring parameter', hashEntries); + return []; + } }) .filter((param) => { - // remove core fields that do not contain a value + // remove core fields that do not contain a value or had malformed data const [key, value] = param; const isCoreField = this.reverseMapping[key]; return !isCoreField || (isCoreField && value); From 02ea1497c9d0b4868e872941337445435aeeeec0 Mon Sep 17 00:00:00 2001 From: Chris Date: Mon, 9 Dec 2024 09:12:50 -0800 Subject: [PATCH 3/3] fix(urltranslator.ts): pop dont join in parseHashString --- .../snap-url-manager/src/Translators/Url/UrlTranslator.test.ts | 2 -- packages/snap-url-manager/src/Translators/Url/UrlTranslator.ts | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/snap-url-manager/src/Translators/Url/UrlTranslator.test.ts b/packages/snap-url-manager/src/Translators/Url/UrlTranslator.test.ts index 6653cb0d1..4a215aa23 100644 --- a/packages/snap-url-manager/src/Translators/Url/UrlTranslator.test.ts +++ b/packages/snap-url-manager/src/Translators/Url/UrlTranslator.test.ts @@ -21,8 +21,6 @@ describe('UrlTranslator', () => { const urlTranslator = new UrlTranslator(); // @ts-ignore expect(urlTranslator.parseHashString(url)).toStrictEqual([ - { key: ['http'], type: 'hash', value: '' }, - { key: ['example.com'], type: 'hash', value: '' }, { key: ['valid'], type: 'hash', value: 'true' }, { key: ['valid2'], type: 'hash', value: 'truueee' }, ]); diff --git a/packages/snap-url-manager/src/Translators/Url/UrlTranslator.ts b/packages/snap-url-manager/src/Translators/Url/UrlTranslator.ts index 307fcc225..999faaff1 100644 --- a/packages/snap-url-manager/src/Translators/Url/UrlTranslator.ts +++ b/packages/snap-url-manager/src/Translators/Url/UrlTranslator.ts @@ -165,7 +165,7 @@ export class UrlTranslator implements Translator { protected parseHashString(hashString: string): Array { const params: Array = []; - const justHashString = hashString.split('#').join('/') || ''; + const justHashString = hashString.split('#').pop() || ''; justHashString .split('/') .filter((v) => v)