From 17c09267ca7572ef8a59a2a4d5b3d217c88eaac7 Mon Sep 17 00:00:00 2001 From: colinlohner Date: Wed, 25 Mar 2020 17:06:21 -0700 Subject: [PATCH 01/12] Update safeHref to remove `data:` protocol, allow custom safe protocols to be added, and to overwrite and allow protocol from component --- src/box.tsx | 15 ++++++++++++--- src/types/box-types.ts | 5 +++++ src/utils/safeHref.ts | 30 ++++++++++++++++++++---------- tools/story.tsx | 4 +++- 4 files changed, 40 insertions(+), 14 deletions(-) diff --git a/src/box.tsx b/src/box.tsx index 3e4d331..a4f07b3 100644 --- a/src/box.tsx +++ b/src/box.tsx @@ -3,9 +3,9 @@ import PropTypes from 'prop-types' import {BoxComponent} from './types/box-types' import {propTypes} from './enhancers' import enhanceProps from './enhance-props' -import {extractAnchorProps, getUseSafeHref} from './utils/safeHref' +import {extractAnchorProps, getUseSafeHref, HrefData} from './utils/safeHref' -const Box: BoxComponent = ({ is = 'div', innerRef, children, allowUnsafeHref, ...props }) => { +const Box: BoxComponent = ({ is = 'div', innerRef, children, allowUnsafeHref, allowProtocol, ...props }) => { // Convert the CSS props to class names (and inject the styles) const {className, enhancedProps: parsedProps} = enhanceProps(props) @@ -22,7 +22,16 @@ const Box: BoxComponent = ({ is = 'div', innerRef, children, allowUnsafeHref, .. */ const safeHrefEnabled = (typeof allowUnsafeHref === 'boolean' ? !allowUnsafeHref : getUseSafeHref()) && is === 'a' && parsedProps.href if (safeHrefEnabled) { - const {safeHref, safeRel} = extractAnchorProps(parsedProps.href, parsedProps.rel) + const hrefData:HrefData = { + href: parsedProps.href, + rel: parsedProps.rel, + } + + if (allowProtocol) { + hrefData.allowProtocol = allowProtocol + } + + const {safeHref, safeRel} = extractAnchorProps(hrefData) parsedProps.href = safeHref parsedProps.rel = safeRel } diff --git a/src/types/box-types.ts b/src/types/box-types.ts index ed7cf67..c1a8d63 100644 --- a/src/types/box-types.ts +++ b/src/types/box-types.ts @@ -59,6 +59,11 @@ export type BoxProps = InheritedProps & * Allows the high level value of safeHref to be overwritten on an individual component basis */ allowUnsafeHref?: boolean + + /** + * Allows an unsafe protocol to be used on an individual component basis + */ + allowProtocol?: boolean } export interface BoxComponent { diff --git a/src/utils/safeHref.ts b/src/utils/safeHref.ts index 74af1fd..f0ac20e 100644 --- a/src/utils/safeHref.ts +++ b/src/utils/safeHref.ts @@ -3,13 +3,21 @@ export interface URLInfo { sameOrigin: boolean } +export interface HrefData { + href: string + rel: string + allowProtocol?: boolean +} + export interface SafeHrefConfigObj { enabled?: boolean origin?: string + additionalProtocols?: string[] } const PROTOCOL_REGEX = /^[a-z]+:/ const ORIGIN_REGEX = /^(?:[a-z]+:?:)?(?:\/\/)?([^\/\?]+)/ +const safeProtocols = ['http:', 'https:', 'mailto:', 'tel:'] let useSafeHref = false let globalOrigin = typeof window !== 'undefined' ? window.location.origin : false @@ -21,25 +29,24 @@ export function configureSafeHref(configObject: SafeHrefConfigObj) { if (configObject.origin) { globalOrigin = configObject.origin } + + if (configObject.additionalProtocols && configObject.additionalProtocols.length) { + safeProtocols.push(...configObject.additionalProtocols) + } } export function getUseSafeHref(): boolean { return useSafeHref } -export function getURLInfo(url: string): URLInfo { - /** - * An array of the safely allowed url protocols - */ - const safeProtocols = ['http:', 'https:', 'mailto:', 'tel:', 'data:'] - +export function getURLInfo(url: string, allowProtocol: boolean): URLInfo { /** * - Find protocol of URL or set to 'relative' * - Find origin of URL * - Determine if sameOrigin * - Determine if protocol of URL is safe */ - const protocolResult = url.match(PROTOCOL_REGEX) + const protocolResult = url.replace(' ', '').match(PROTOCOL_REGEX) const originResult = url.match(ORIGIN_REGEX) const urlProtocol = protocolResult ? protocolResult[0] : 'relative' let sameOrigin = urlProtocol === 'relative' @@ -47,7 +54,7 @@ export function getURLInfo(url: string): URLInfo { sameOrigin = globalOrigin === (originResult && originResult[0]) } - const isSafeProtocol = sameOrigin ? true : safeProtocols.includes(urlProtocol) + const isSafeProtocol = (allowProtocol || sameOrigin) ? true : safeProtocols.includes(urlProtocol) if (!isSafeProtocol) { /** * If the url is unsafe, put a error in the console, and return the URLInfo object @@ -72,11 +79,14 @@ export function getURLInfo(url: string): URLInfo { } } -export function extractAnchorProps(href: string, rel: string) { +export function extractAnchorProps(hrefData: HrefData) { + const {href, rel} = hrefData + const allowProtocol = hrefData.allowProtocol || false + /** * Get url info and update href */ - const urlInfo = getURLInfo(href) + const urlInfo = getURLInfo(href, allowProtocol) const safeHref = urlInfo.url /** diff --git a/tools/story.tsx b/tools/story.tsx index 06abee0..6a3dfa0 100644 --- a/tools/story.tsx +++ b/tools/story.tsx @@ -36,7 +36,7 @@ storiesOf('Box', module) }) .add('safe `href`', () => { configureSafeHref({ - enabled: true + enabled: true, }) return ( @@ -45,6 +45,8 @@ storiesOf('Box', module) Same Origin Link External Link Javascript protocol Link + Data protocol Link + Allow protocol Link Overwride Safe Href ) From 0ce02d706fcea91f873dab2ffd327f89c84d6c65 Mon Sep 17 00:00:00 2001 From: colinlohner Date: Wed, 25 Mar 2020 17:10:48 -0700 Subject: [PATCH 02/12] Update readme to reflect changes to safeHref --- README.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index eb8dc8a..91ca07c 100644 --- a/README.md +++ b/README.md @@ -308,7 +308,7 @@ setClassNamePrefix('📦') ### Safe `href`s -By default `ui-box` does not ensure that urls use safe protocols when passed to an element. But we built this functionality into `ui-box` to protect the end users of the products you are building. You can alter this by using `configureSafeHref({enabled?: boolean, origin?: string})`. This will ensure that only safe protocols are used (`http:`, `https:`, `mailto:`, `tel:`, and `data:`) and that the correct `rel` values are added (`noopener`, `noreferrer`(for external links)). +By default `ui-box` does not ensure that urls use safe protocols when passed to an element. But we built this functionality into `ui-box` to protect the end users of the products you are building. You can alter this by using `configureSafeHref({enabled?: boolean, origin?: string, additionalProtocols?: string[]})`. This will ensure that only safe protocols are used (`http:`, `https:`, `mailto:`, and `tel:`), that the correct `rel` values are added (`noopener`, `noreferrer`(for external links)), and any additional protocols passed are treated as safe. ```js import { configureSafeHref } from 'ui-box' @@ -320,14 +320,16 @@ configureSafeHref({ import { configureSafeHref } from 'ui-box' configureSafeHref({ enabled: true - origin: 'https://app.segmentio.com', + origin: 'https://app.segmentio.com', + additionalProtocols: ['data:'], }) ``` -Additionally you can overwrite the behavoir on an individual component basis using the prop `allowUnsafeHref` +Additionally you can overwrite the behavoir on an individual component basis using the prop `allowUnsafeHref` and `allowProtocol`. Setting `allowUnsafeHref` completely bypasses all safeHref functionality (protocol checks, rel checks) whereas `allowProtocol` only bypasses protocol checks. ```jsx This is unsafe +This is unsafe ``` ### Server side rendering From fa8f3e093b01e02123d2a943bc30584129fcf668 Mon Sep 17 00:00:00 2001 From: colinlohner Date: Mon, 30 Mar 2020 11:54:52 -0700 Subject: [PATCH 03/12] Clean up custom protocol implimentation --- src/utils/safeHref.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/utils/safeHref.ts b/src/utils/safeHref.ts index f0ac20e..519e978 100644 --- a/src/utils/safeHref.ts +++ b/src/utils/safeHref.ts @@ -17,7 +17,8 @@ export interface SafeHrefConfigObj { const PROTOCOL_REGEX = /^[a-z]+:/ const ORIGIN_REGEX = /^(?:[a-z]+:?:)?(?:\/\/)?([^\/\?]+)/ -const safeProtocols = ['http:', 'https:', 'mailto:', 'tel:'] +const safeProtocols:Array = ['http:', 'https:', 'mailto:', 'tel:'] +const customProtocols:Array = [] let useSafeHref = false let globalOrigin = typeof window !== 'undefined' ? window.location.origin : false @@ -31,7 +32,7 @@ export function configureSafeHref(configObject: SafeHrefConfigObj) { } if (configObject.additionalProtocols && configObject.additionalProtocols.length) { - safeProtocols.push(...configObject.additionalProtocols) + customProtocols.push(...configObject.additionalProtocols) } } @@ -54,7 +55,8 @@ export function getURLInfo(url: string, allowProtocol: boolean): URLInfo { sameOrigin = globalOrigin === (originResult && originResult[0]) } - const isSafeProtocol = (allowProtocol || sameOrigin) ? true : safeProtocols.includes(urlProtocol) + const allowedProtocols = [...safeProtocols, ...customProtocols] + const isSafeProtocol = (allowProtocol || sameOrigin) ? true : allowedProtocols.includes(urlProtocol) if (!isSafeProtocol) { /** * If the url is unsafe, put a error in the console, and return the URLInfo object From 08cd4186e1d2c3a1013fbd174eab50e109a80ca0 Mon Sep 17 00:00:00 2001 From: colinlohner Date: Mon, 30 Mar 2020 12:09:11 -0700 Subject: [PATCH 04/12] Change `allowProtocol` -> `allowProtocols` --- README.md | 4 ++-- src/box.tsx | 6 +++--- src/types/box-types.ts | 4 ++-- src/utils/safeHref.ts | 12 ++++++------ tools/story.tsx | 2 +- 5 files changed, 14 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 91ca07c..0165b5d 100644 --- a/README.md +++ b/README.md @@ -325,11 +325,11 @@ configureSafeHref({ }) ``` -Additionally you can overwrite the behavoir on an individual component basis using the prop `allowUnsafeHref` and `allowProtocol`. Setting `allowUnsafeHref` completely bypasses all safeHref functionality (protocol checks, rel checks) whereas `allowProtocol` only bypasses protocol checks. +Additionally you can overwrite the behavoir on an individual component basis using the prop `allowUnsafeHref` and `allowProtocols`. Setting `allowUnsafeHref` completely bypasses all safeHref functionality (protocol checks, rel checks). Setting `allowProtocols` adds the contents of a string array to the allowed protocols. ```jsx This is unsafe -This is unsafe +This is unsafe ``` ### Server side rendering diff --git a/src/box.tsx b/src/box.tsx index a4f07b3..ffe77ad 100644 --- a/src/box.tsx +++ b/src/box.tsx @@ -5,7 +5,7 @@ import {propTypes} from './enhancers' import enhanceProps from './enhance-props' import {extractAnchorProps, getUseSafeHref, HrefData} from './utils/safeHref' -const Box: BoxComponent = ({ is = 'div', innerRef, children, allowUnsafeHref, allowProtocol, ...props }) => { +const Box: BoxComponent = ({ is = 'div', innerRef, children, allowUnsafeHref, allowProtocols, ...props }) => { // Convert the CSS props to class names (and inject the styles) const {className, enhancedProps: parsedProps} = enhanceProps(props) @@ -27,8 +27,8 @@ const Box: BoxComponent = ({ is = 'div', innerRef, children, allowUnsafeHref, al rel: parsedProps.rel, } - if (allowProtocol) { - hrefData.allowProtocol = allowProtocol + if (allowProtocols && allowProtocols.length > 0) { + hrefData.allowProtocols = allowProtocols } const {safeHref, safeRel} = extractAnchorProps(hrefData) diff --git a/src/types/box-types.ts b/src/types/box-types.ts index c1a8d63..71ec8aa 100644 --- a/src/types/box-types.ts +++ b/src/types/box-types.ts @@ -61,9 +61,9 @@ export type BoxProps = InheritedProps & allowUnsafeHref?: boolean /** - * Allows an unsafe protocol to be used on an individual component basis + * Allows additional protocols to be considered safe */ - allowProtocol?: boolean + allowProtocols?: Array } export interface BoxComponent { diff --git a/src/utils/safeHref.ts b/src/utils/safeHref.ts index 519e978..98b911e 100644 --- a/src/utils/safeHref.ts +++ b/src/utils/safeHref.ts @@ -6,7 +6,7 @@ export interface URLInfo { export interface HrefData { href: string rel: string - allowProtocol?: boolean + allowProtocols?: Array } export interface SafeHrefConfigObj { @@ -40,7 +40,7 @@ export function getUseSafeHref(): boolean { return useSafeHref } -export function getURLInfo(url: string, allowProtocol: boolean): URLInfo { +export function getURLInfo(url: string, allowProtocols: Array): URLInfo { /** * - Find protocol of URL or set to 'relative' * - Find origin of URL @@ -55,8 +55,8 @@ export function getURLInfo(url: string, allowProtocol: boolean): URLInfo { sameOrigin = globalOrigin === (originResult && originResult[0]) } - const allowedProtocols = [...safeProtocols, ...customProtocols] - const isSafeProtocol = (allowProtocol || sameOrigin) ? true : allowedProtocols.includes(urlProtocol) + const allowedProtocols = [...safeProtocols, ...customProtocols, ...allowProtocols] + const isSafeProtocol = sameOrigin ? true : allowedProtocols.includes(urlProtocol) if (!isSafeProtocol) { /** * If the url is unsafe, put a error in the console, and return the URLInfo object @@ -83,12 +83,12 @@ export function getURLInfo(url: string, allowProtocol: boolean): URLInfo { export function extractAnchorProps(hrefData: HrefData) { const {href, rel} = hrefData - const allowProtocol = hrefData.allowProtocol || false + const allowProtocols = hrefData.allowProtocols && hrefData.allowProtocols.length ? hrefData.allowProtocols : [] /** * Get url info and update href */ - const urlInfo = getURLInfo(href, allowProtocol) + const urlInfo = getURLInfo(href, allowProtocols) const safeHref = urlInfo.url /** diff --git a/tools/story.tsx b/tools/story.tsx index 6a3dfa0..7fd30b2 100644 --- a/tools/story.tsx +++ b/tools/story.tsx @@ -46,7 +46,7 @@ storiesOf('Box', module) External Link Javascript protocol Link Data protocol Link - Allow protocol Link + Allow protocol Link Overwride Safe Href ) From c243da7504a255c996873a7f4a4c71904d7093f2 Mon Sep 17 00:00:00 2001 From: colinlohner Date: Mon, 30 Mar 2020 12:18:35 -0700 Subject: [PATCH 05/12] Update whitespace checking to be more robust --- src/utils/safeHref.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/utils/safeHref.ts b/src/utils/safeHref.ts index 98b911e..951d39e 100644 --- a/src/utils/safeHref.ts +++ b/src/utils/safeHref.ts @@ -17,6 +17,7 @@ export interface SafeHrefConfigObj { const PROTOCOL_REGEX = /^[a-z]+:/ const ORIGIN_REGEX = /^(?:[a-z]+:?:)?(?:\/\/)?([^\/\?]+)/ +const WHITE_SPACE_REGEX = /^\s+/ const safeProtocols:Array = ['http:', 'https:', 'mailto:', 'tel:'] const customProtocols:Array = [] let useSafeHref = false @@ -47,8 +48,9 @@ export function getURLInfo(url: string, allowProtocols: Array): URLInfo * - Determine if sameOrigin * - Determine if protocol of URL is safe */ - const protocolResult = url.replace(' ', '').match(PROTOCOL_REGEX) - const originResult = url.match(ORIGIN_REGEX) + const cleanedUrl = url.replace(WHITE_SPACE_REGEX, '') + const protocolResult = cleanedUrl.match(PROTOCOL_REGEX) + const originResult = cleanedUrl.match(ORIGIN_REGEX) const urlProtocol = protocolResult ? protocolResult[0] : 'relative' let sameOrigin = urlProtocol === 'relative' if (!sameOrigin && globalOrigin) { @@ -76,7 +78,7 @@ export function getURLInfo(url: string, allowProtocols: Array): URLInfo * If the url is safe, return the url and origin */ return { - url, + url: cleanedUrl, sameOrigin } } From a390a734c7a5c0573de40046f85b2b3e9f647155 Mon Sep 17 00:00:00 2001 From: colinlohner Date: Mon, 30 Mar 2020 12:39:04 -0700 Subject: [PATCH 06/12] Add some testing, and a function to reset custom protocols --- src/utils/safeHref.ts | 6 ++++- test/utils/safeHref.ts | 58 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 test/utils/safeHref.ts diff --git a/src/utils/safeHref.ts b/src/utils/safeHref.ts index 951d39e..bd2aa70 100644 --- a/src/utils/safeHref.ts +++ b/src/utils/safeHref.ts @@ -19,7 +19,7 @@ const PROTOCOL_REGEX = /^[a-z]+:/ const ORIGIN_REGEX = /^(?:[a-z]+:?:)?(?:\/\/)?([^\/\?]+)/ const WHITE_SPACE_REGEX = /^\s+/ const safeProtocols:Array = ['http:', 'https:', 'mailto:', 'tel:'] -const customProtocols:Array = [] +let customProtocols:Array = [] let useSafeHref = false let globalOrigin = typeof window !== 'undefined' ? window.location.origin : false @@ -41,6 +41,10 @@ export function getUseSafeHref(): boolean { return useSafeHref } +export function resetCutomProtocols() { + customProtocols = [] +} + export function getURLInfo(url: string, allowProtocols: Array): URLInfo { /** * - Find protocol of URL or set to 'relative' diff --git a/test/utils/safeHref.ts b/test/utils/safeHref.ts new file mode 100644 index 0000000..d73eebe --- /dev/null +++ b/test/utils/safeHref.ts @@ -0,0 +1,58 @@ +import test from 'ava' +import {extractAnchorProps, configureSafeHref, resetCutomProtocols} from '../../src/utils/safeHref' + +test('Allows safe protocols', t => { + configureSafeHref({ + enabled: true + }) + + const {safeHref} = extractAnchorProps({ + href: 'https://www.apple.com', + rel: '' + }) + + t.assert(safeHref === 'https://www.apple.com') +}) + +test('Rejects unsafe protocols', t => { + const {safeHref} = extractAnchorProps({ + href: 'javascript://www.apple.com', + rel: '' + }) + + t.assert(safeHref === undefined) +}) + +test('Rejects unsafe protocols with whitespace', t => { + const {safeHref} = extractAnchorProps({ + href: ' javascript://www.apple.com', + rel: '' + }) + + t.assert(safeHref === undefined) +}) + +test('Allows custom protocol', t => { + configureSafeHref({ + additionalProtocols: ['data:'] + }) + + const {safeHref} = extractAnchorProps({ + href: 'data:text/html,

Hi

', + rel: '' + }) + + resetCutomProtocols() + + t.assert(safeHref === 'data:text/html,

Hi

') +}) + +test('Allows individual level custom protocol', t => { + const {safeHref} = extractAnchorProps({ + href: 'data:text/html,

Hi

', + rel: '', + allowProtocols: ['data:'] + }) + + t.assert(safeHref === 'data:text/html,

Hi

') +}) From 59aa408e7dbfe79c173a508b3c69603ef255bbf8 Mon Sep 17 00:00:00 2001 From: Colin Lohner Date: Mon, 30 Mar 2020 13:04:12 -0700 Subject: [PATCH 07/12] Change Typing Co-Authored-By: Matt Shwery --- src/utils/safeHref.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/safeHref.ts b/src/utils/safeHref.ts index bd2aa70..62ebf3f 100644 --- a/src/utils/safeHref.ts +++ b/src/utils/safeHref.ts @@ -18,7 +18,7 @@ export interface SafeHrefConfigObj { const PROTOCOL_REGEX = /^[a-z]+:/ const ORIGIN_REGEX = /^(?:[a-z]+:?:)?(?:\/\/)?([^\/\?]+)/ const WHITE_SPACE_REGEX = /^\s+/ -const safeProtocols:Array = ['http:', 'https:', 'mailto:', 'tel:'] +const safeProtocols: string[] = ['http:', 'https:', 'mailto:', 'tel:'] let customProtocols:Array = [] let useSafeHref = false let globalOrigin = typeof window !== 'undefined' ? window.location.origin : false From 70f6dfa21b3fb0d7bf250491165bdfbe5d9e55da Mon Sep 17 00:00:00 2001 From: Colin Lohner Date: Mon, 30 Mar 2020 13:04:30 -0700 Subject: [PATCH 08/12] Change typing Co-Authored-By: Matt Shwery --- src/utils/safeHref.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/safeHref.ts b/src/utils/safeHref.ts index 62ebf3f..f03e3b8 100644 --- a/src/utils/safeHref.ts +++ b/src/utils/safeHref.ts @@ -6,7 +6,7 @@ export interface URLInfo { export interface HrefData { href: string rel: string - allowProtocols?: Array + allowProtocols?: string[] } export interface SafeHrefConfigObj { From df06920f812483d27c3cdcd72306ffb13d25e859 Mon Sep 17 00:00:00 2001 From: colinlohner Date: Mon, 30 Mar 2020 13:05:24 -0700 Subject: [PATCH 09/12] Fix typo --- src/utils/safeHref.ts | 2 +- test/utils/safeHref.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/utils/safeHref.ts b/src/utils/safeHref.ts index f03e3b8..fb9795a 100644 --- a/src/utils/safeHref.ts +++ b/src/utils/safeHref.ts @@ -41,7 +41,7 @@ export function getUseSafeHref(): boolean { return useSafeHref } -export function resetCutomProtocols() { +export function resetCustomProtocols() { customProtocols = [] } diff --git a/test/utils/safeHref.ts b/test/utils/safeHref.ts index d73eebe..28df67a 100644 --- a/test/utils/safeHref.ts +++ b/test/utils/safeHref.ts @@ -1,5 +1,5 @@ import test from 'ava' -import {extractAnchorProps, configureSafeHref, resetCutomProtocols} from '../../src/utils/safeHref' +import {extractAnchorProps, configureSafeHref, resetCustomProtocols} from '../../src/utils/safeHref' test('Allows safe protocols', t => { configureSafeHref({ @@ -42,7 +42,7 @@ test('Allows custom protocol', t => { rel: '' }) - resetCutomProtocols() + resetCustomProtocols() t.assert(safeHref === 'data:text/html,

Hi

') }) From 21ebb43f189cdc6603cf02fbb4997e139e77f900 Mon Sep 17 00:00:00 2001 From: colinlohner Date: Mon, 30 Mar 2020 13:05:56 -0700 Subject: [PATCH 10/12] Update to use `trim` cause im silly --- src/utils/safeHref.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/utils/safeHref.ts b/src/utils/safeHref.ts index fb9795a..c8caf9a 100644 --- a/src/utils/safeHref.ts +++ b/src/utils/safeHref.ts @@ -17,7 +17,6 @@ export interface SafeHrefConfigObj { const PROTOCOL_REGEX = /^[a-z]+:/ const ORIGIN_REGEX = /^(?:[a-z]+:?:)?(?:\/\/)?([^\/\?]+)/ -const WHITE_SPACE_REGEX = /^\s+/ const safeProtocols: string[] = ['http:', 'https:', 'mailto:', 'tel:'] let customProtocols:Array = [] let useSafeHref = false @@ -52,7 +51,7 @@ export function getURLInfo(url: string, allowProtocols: Array): URLInfo * - Determine if sameOrigin * - Determine if protocol of URL is safe */ - const cleanedUrl = url.replace(WHITE_SPACE_REGEX, '') + const cleanedUrl = url.trim() const protocolResult = cleanedUrl.match(PROTOCOL_REGEX) const originResult = cleanedUrl.match(ORIGIN_REGEX) const urlProtocol = protocolResult ? protocolResult[0] : 'relative' From 1e0521323662d562be0cc39ba4243f071ec7bfd8 Mon Sep 17 00:00:00 2001 From: colinlohner Date: Mon, 30 Mar 2020 14:29:59 -0700 Subject: [PATCH 11/12] Minor update to the tests --- test/utils/safeHref.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/utils/safeHref.ts b/test/utils/safeHref.ts index 28df67a..7d2ec19 100644 --- a/test/utils/safeHref.ts +++ b/test/utils/safeHref.ts @@ -16,7 +16,7 @@ test('Allows safe protocols', t => { test('Rejects unsafe protocols', t => { const {safeHref} = extractAnchorProps({ - href: 'javascript://www.apple.com', + href: 'javascript:alert("hi")', rel: '' }) @@ -25,7 +25,7 @@ test('Rejects unsafe protocols', t => { test('Rejects unsafe protocols with whitespace', t => { const {safeHref} = extractAnchorProps({ - href: ' javascript://www.apple.com', + href: ' javascript:alert("hi")', rel: '' }) From 2e63d6bbb411e41d2f3b093075aec0c3e9d3c752 Mon Sep 17 00:00:00 2001 From: colinlohner Date: Mon, 30 Mar 2020 14:32:33 -0700 Subject: [PATCH 12/12] Update console error to match existing error --- src/utils/safeHref.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/safeHref.ts b/src/utils/safeHref.ts index c8caf9a..09a8766 100644 --- a/src/utils/safeHref.ts +++ b/src/utils/safeHref.ts @@ -68,7 +68,7 @@ export function getURLInfo(url: string, allowProtocols: Array): URLInfo * with the value of url being `undefined` */ console.error( - '📦 `href` passed to anchor tag is unsafe. Because of this, the `href` on the element was not set. Please review the safe href documentation if you have questions.', + '📦 ui-box: `href` passed to anchor tag is unsafe. Because of this, the `href` on the element was not set. Please review the safe href documentation if you have questions.', 'https://www.github.com/segmentio/ui-box' ) return {