Skip to content

Commit 39e316a

Browse files
authored
Merge pull request #1965 from oasisprotocol/lw/sanitize-rofl-link
Sanitize URL in metadata['net.oasis.rofl.repository']
2 parents 6165047 + 3d9c061 commit 39e316a

File tree

9 files changed

+19
-16
lines changed

9 files changed

+19
-16
lines changed

.changelog/1965.bugfix.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Sanitize URL in metadata['net.oasis.rofl.repository']

src/app/components/Snapshots/SnapshotCardExternalLink.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { styled } from '@mui/material/styles'
55
import Typography from '@mui/material/Typography'
66
import { SnapshotCard } from '../../components/Snapshots/SnapshotCard'
77
import { COLORS } from '../../../styles/theme/colors'
8-
import { hasValidProtocol } from 'app/utils/url'
8+
import { isUrlSafe } from 'app/utils/url'
99

1010
const StyledBox = styled(Box)(({ theme }) => ({
1111
gap: theme.spacing(5),
@@ -40,7 +40,7 @@ export const SnapshotCardExternalLink: FC<SnapshotCardExternalLinkProps> = ({
4040
>
4141
{description}
4242
</Typography>
43-
{url && hasValidProtocol(url) && (
43+
{url && isUrlSafe(url) && (
4444
<Button href={url} target="_blank" rel="noopener noreferrer" color="secondary" variant="outlined">
4545
{label}
4646
</Button>

src/app/components/Validators/ValidatorImage.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { FC } from 'react'
22
import { styled } from '@mui/material/styles'
33
import ImageNotSupportedIcon from '@mui/icons-material/ImageNotSupported'
4-
import { hasValidProtocol } from '../../utils/url'
4+
import { isUrlSafe } from '../../utils/url'
55
import { COLORS } from 'styles/theme/colors'
66
import { Circle } from '../Circle'
77

@@ -20,7 +20,7 @@ type ValidatorImageProps = {
2020
export const ValidatorImage: FC<ValidatorImageProps> = ({ address, name, logotype }) => {
2121
return (
2222
<>
23-
{logotype && hasValidProtocol(logotype) ? (
23+
{logotype && isUrlSafe(logotype) ? (
2424
<StyledImage alt={name || address} src={logotype} />
2525
) : (
2626
<Circle color={COLORS.grayMedium2} size={5}>

src/app/data/oasis-account-names.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import {
1919
import { hasTextMatch } from '../components/HighlightedText/text-matching'
2020
import * as externalLinks from '../utils/externalLinks'
2121
import { getOasisAddress } from '../utils/helpers'
22-
import { hasValidProtocol } from '../utils/url'
22+
import { isUrlSafe } from '../utils/url'
2323

2424
const dataSources: Record<Network, Partial<Record<Layer, string>>> = {
2525
[Network.mainnet]: {
@@ -57,9 +57,9 @@ const getOasisAccountsMetadata = async (network: Network, layer: Layer): Promise
5757
name: entry.Name,
5858
description: entry.Description,
5959
origin: entry.Origin,
60-
icon: entry.Icon && hasValidProtocol(entry.Icon) ? entry.Icon : undefined,
60+
icon: entry.Icon && isUrlSafe(entry.Icon) ? entry.Icon : undefined,
6161
dapp:
62-
entry.Dapp && hasValidProtocol(entry.Dapp.Url)
62+
entry.Dapp && isUrlSafe(entry.Dapp.Url)
6363
? {
6464
button: entry.Dapp.Button,
6565
description: entry.Dapp.Description,

src/app/pages/NFTInstanceDashboardPage/InstanceImageCard.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import OpenInFullIcon from '@mui/icons-material/OpenInFull'
1212
import { styled } from '@mui/material/styles'
1313
import { EvmNft } from 'oasis-nexus/api'
1414
import { processNftImageUrl } from '../../utils/nft-images'
15-
import { hasValidProtocol } from '../../utils/url'
15+
import { isUrlSafe } from '../../utils/url'
1616
import { COLORS } from '../../../styles/theme/colors'
1717
import { ImagePreview } from '../../components/ImagePreview'
1818
import { NoPreview } from '../../components/NoPreview'
@@ -113,15 +113,15 @@ export const InstanceImageCard: FC<InstanceImageCardProps> = ({ isFetched, isLoa
113113
}}
114114
>
115115
<NoPreview placeholderSize={imageSize} />
116-
{hasValidProtocol(nft.image) && (
116+
{isUrlSafe(nft.image) && (
117117
<Link href={nft.image} rel="noopener noreferrer" target="_blank">
118118
{t('nft.openInNewTab')}
119119
</Link>
120120
)}
121121
</Box>
122122
</Box>
123123
)}
124-
{isFetched && nft && hasValidProtocol(nft.image) && !imageLoadError && (
124+
{isFetched && nft && isUrlSafe(nft.image) && !imageLoadError && (
125125
<>
126126
<Box
127127
sx={{

src/app/pages/RoflAppDetailsPage/MetaDataCard.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import { RoflAppMetadata } from '../../../oasis-nexus/api'
1313
import { COLORS } from '../../../styles/theme/colors'
1414
import { EmptyStateCard } from './EmptyStateCard'
1515
import { GridRow } from './GridRow'
16+
import { isUrlSafe } from '../../utils/url'
1617

1718
export const StyledLink = styled(Link)(() => ({
1819
display: 'inline-flex',
@@ -73,7 +74,7 @@ export const MetaDataCard: FC<MetaDataCardProps> = ({ isFetched, metadata }) =>
7374
/>
7475
}
7576
>
76-
{metadata['net.oasis.rofl.repository'] ? (
77+
{isUrlSafe(metadata['net.oasis.rofl.repository']) ? (
7778
<StyledLink
7879
href={metadata['net.oasis.rofl.repository']}
7980
rel="noopener noreferrer"

src/app/pages/TokenDashboardPage/ImageListItemImage.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import Link from '@mui/material/Link'
66
import OpenInBrowserIcon from '@mui/icons-material/OpenInBrowser'
77
import { styled } from '@mui/material/styles'
88
import { processNftImageUrl } from 'app/utils/nft-images'
9-
import { hasValidProtocol } from 'app/utils/url'
9+
import { isUrlSafe } from 'app/utils/url'
1010
import { NoPreview } from '../../components/NoPreview'
1111
import { getNftInstanceLabel } from '../../utils/nft'
1212
import { EvmNft } from '../../../oasis-nexus/api'
@@ -62,7 +62,7 @@ export const ImageListItemImage: FC<ImageListItemImageProps> = ({ instance, to }
6262

6363
return (
6464
<Link component={RouterLink} to={to} sx={{ display: 'flex', position: 'relative' }}>
65-
{hasValidProtocol(instance.image) && !imageLoadError ? (
65+
{isUrlSafe(instance.image) && !imageLoadError ? (
6666
<StyledImage
6767
onError={() => setImageLoadError(true)}
6868
src={processNftImageUrl(instance.image)}

src/app/utils/nft-images.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import { AppError, AppErrors } from 'types/errors'
22
import { accessIpfsUrl } from './ipfs'
3-
import { hasValidProtocol } from './url'
3+
import { isUrlSafe } from './url'
44

55
export const processNftImageUrl = (url: string | undefined): string => {
6-
if (!url || !hasValidProtocol(url)) {
6+
if (!url || !isUrlSafe(url)) {
77
throw new AppError(AppErrors.InvalidUrl)
88
}
99

src/app/utils/url.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
// `ftp://` is obsolete https://chromestatus.com/feature/6199005675520000
33
const validProtocols = ['http:', 'https:', 'ftp:', 'ipfs:', 'data:', 'mailto:']
44

5-
export const hasValidProtocol = (url: string | undefined): boolean => {
5+
/** Blocks dangerous URLs that start with "javascript:". When we upgrade to React@19 that should block them too. */
6+
export const isUrlSafe = (url: string | undefined): boolean => {
67
if (!url) {
78
return false
89
}

0 commit comments

Comments
 (0)