-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Icon] Use img tag instead of inlining svgs #926
Conversation
We noticed that this PR either modifies or introduces usage of the dangerouslySetInnerHTML attribute, which can cause cross-site scripting (XSS) vulnerabilities. Our team will take a look soon, but for now we recommend reviewing your code to ensure that this is what you intended to use and that there is not a safe alternative available. Docs are available here. |
👋 Thanks for opening your first pull request. A contributor should give feedback soon. If you haven’t already, please check out the contributing guidelines. You can also join #polaris on the Shopify Partners Slack. |
966cf15
to
52690a7
Compare
b37bea2
to
a16559e
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good, a few questions and suggestions
src/components/Icon/Icon.tsx
Outdated
@@ -188,6 +193,7 @@ function Icon({ | |||
color, | |||
backdrop, | |||
accessibilityLabel, | |||
untrusted, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do you think of adding a default value of false here? I think it would reduce ambiguity and make typing a bit easier
aria-hidden="true" | ||
/> | ||
); | ||
} else if (isBundledIcon(source)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nice change 👍
); | ||
} | ||
|
||
function isUntrustedSVG(source: IconSource): source is UntrustedSVG { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do you think of moving this check inline instead of in a function? It's a really simple check, so I don't want to inspire undue confidence in it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think keeping it a separate function is okay because it's clear what the conditional is doing through the function name. If we use typeof source === 'string'
above, it's not as clear what we are testing. The function also ensures source is UntrustedSVG
though type guarding.
/// base. | ||
/// @return {List} The filter list. | ||
|
||
@function filter($hue, $value: base) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did you write this or did you copy it from somewhere else?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I copied the color
function and modified it to use the filter map instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add an entry to UNRELEASED.md
and this is good to go imo
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh actually I forgot one thing, can you add a simple example under the Examples
section in the README.md file? That will make sure that this gets tested as part of our visual regression testing so we don't break it accidentally, and document usage
@amrocha Are you talking about this readme? https://github.com/Shopify/polaris-react/blob/master/src/components/Icon/README.md |
contentMarkup = ( | ||
<img | ||
className={styles.Img} | ||
src={`data:image/svg+xml;base64,${btoa(source)}`} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think if you omit the base64
, then you can output your source as-is without running it through btoa()
`data:image/svg+xml;${source}`
@theodoretan yep that's the one |
a16559e
to
d6faf7b
Compare
d6faf7b
to
9f92b42
Compare
🎉 Thanks for your contribution to Polaris React! |
WHY are these changes introduced?
Part of #885
Inlining svgs is potentially dangerous as scripts can be executed if they are in the svg.
WHAT is this pull request doing?
If the user provides an svg, we will display it in an
img
tag instead. Since we can't use fill on img tag we need to use a filter from the polaris-tokens to get the correct colour that we want.This is adding a
untrusted
prop to Icon that a user will have to manually set in order to render a svg string. This is temporary as we wait for the work on SVGR to be completed.white
black
skyLighter
skyLight
sky
skyDark
inkLightest
inkLighter
inkLight
ink
blueLighter
blueLight
blue
blueDark
blueDarker
indigoLighter
indigoLight
indigo
indigoDark
indigoDarker
tealLighter
tealLight
teal
tealDark
tealDarker
greenLighter
green
greenDark
yellowLighter
yellow
yellowDark
orange
orangeDark
redLighter
red
redDark
purple
How to 🎩
🖥 Local development instructions
🗒 General tophatting guidelines
📄 Changelog guidelines
Copy-paste this code in
playground/Playground.tsx
:🎩 checklist
cc @ragalie