mirror of
https://github.com/clash-verge-rev/clash-verge-rev.git
synced 2026-11-04 22:52:23 +08:00
fix(security): restrict external URL opening
Close: 7800
This commit is contained in:
@@ -25,8 +25,9 @@ import { useTranslation } from 'react-i18next'
|
||||
import { useNavigate } from 'react-router'
|
||||
|
||||
import { useAppRefreshers } from '@/providers/app-data-context'
|
||||
import { openWebUrl, updateProfile } from '@/services/cmds'
|
||||
import { updateProfile } from '@/services/cmds'
|
||||
import { showNotice } from '@/services/notice-service'
|
||||
import { openExternalUrl } from '@/utils/open-external-url'
|
||||
import parseTraffic from '@/utils/parse-traffic'
|
||||
|
||||
import { EnhancedCard } from './enhanced-card'
|
||||
@@ -49,6 +50,10 @@ const parseExpire = (expire?: number) => {
|
||||
return dayjs(expire * 1000).format('YYYY-MM-DD')
|
||||
}
|
||||
|
||||
const openProfileHome = (url: string) => {
|
||||
void openExternalUrl(url).catch(showNotice.error)
|
||||
}
|
||||
|
||||
// 使用类型定义,而不是导入
|
||||
interface ProfileExtra {
|
||||
upload: number
|
||||
@@ -115,7 +120,7 @@ const ProfileDetails = ({
|
||||
{current.home ? (
|
||||
<Link
|
||||
component="button"
|
||||
onClick={() => current.home && openWebUrl(current.home)}
|
||||
onClick={() => current.home && openProfileHome(current.home)}
|
||||
sx={{
|
||||
display: 'inline-flex',
|
||||
alignItems: 'center',
|
||||
@@ -318,7 +323,7 @@ export const HomeProfileCard = ({
|
||||
<Link
|
||||
component="button"
|
||||
variant="h6"
|
||||
onClick={() => current.home && openWebUrl(current.home)}
|
||||
onClick={() => current.home && openProfileHome(current.home)}
|
||||
sx={{
|
||||
color: 'inherit',
|
||||
textDecoration: 'none',
|
||||
|
||||
@@ -18,7 +18,6 @@ import {
|
||||
MenuItem,
|
||||
Typography,
|
||||
} from '@mui/material'
|
||||
import { open } from '@tauri-apps/plugin-shell'
|
||||
import { useLockFn } from 'ahooks'
|
||||
import dayjs from 'dayjs'
|
||||
import {
|
||||
@@ -47,6 +46,7 @@ import { showNotice } from '@/services/notice-service'
|
||||
import { useLoadingCache, useSetLoadingCache } from '@/services/states'
|
||||
import type { TranslationKey } from '@/types/generated/i18n-keys'
|
||||
import { debugLog } from '@/utils/debug'
|
||||
import { openExternalUrl } from '@/utils/open-external-url'
|
||||
import parseTraffic from '@/utils/parse-traffic'
|
||||
|
||||
import { ProfileBox } from './profile-box'
|
||||
@@ -316,7 +316,8 @@ const ProfileItemBase = (props: ProfileItemProps) => {
|
||||
|
||||
const onOpenHome = () => {
|
||||
setAnchorEl(null)
|
||||
open(itemData.home ?? '')
|
||||
if (!itemData.home) return
|
||||
void openExternalUrl(itemData.home).catch(showNotice.error)
|
||||
}
|
||||
|
||||
const onEditInfo = () => {
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { alpha, Box, Button, LinearProgress } from '@mui/material'
|
||||
import { open as openUrl } from '@tauri-apps/plugin-shell'
|
||||
import type { DownloadEvent } from '@tauri-apps/plugin-updater'
|
||||
import { useLockFn } from 'ahooks'
|
||||
import type { Ref } from 'react'
|
||||
@@ -19,6 +18,7 @@ import { useUpdate } from '@/hooks/use-update'
|
||||
import { restartApp } from '@/services/cmds'
|
||||
import { showNotice } from '@/services/notice-service'
|
||||
import { useSetUpdateState, useUpdateState } from '@/services/states'
|
||||
import { openExternalUrl } from '@/utils/open-external-url'
|
||||
|
||||
type MarkdownNode = {
|
||||
type: string
|
||||
@@ -151,6 +151,10 @@ export function UpdateViewer({ ref }: { ref?: Ref<DialogRef> }) {
|
||||
const downloadedRef = useRef(0)
|
||||
const totalRef = useRef(0)
|
||||
|
||||
const openUrlWithNotice = (url: string) => {
|
||||
void openExternalUrl(url).catch(showNotice.error)
|
||||
}
|
||||
|
||||
const progress = useMemo(() => {
|
||||
if (total <= 0) return 0
|
||||
return Math.min((downloaded / total) * 100, 100)
|
||||
@@ -276,7 +280,7 @@ export function UpdateViewer({ ref }: { ref?: Ref<DialogRef> }) {
|
||||
size="small"
|
||||
sx={{ whiteSpace: 'nowrap' }}
|
||||
onClick={() => {
|
||||
openUrl(
|
||||
openUrlWithNotice(
|
||||
`https://github.com/clash-verge-rev/clash-verge-rev/releases/tag/v${updateInfo?.version}`,
|
||||
)
|
||||
}}
|
||||
@@ -420,10 +424,25 @@ export function UpdateViewer({ ref }: { ref?: Ref<DialogRef> }) {
|
||||
<LazyReactMarkdown
|
||||
remarkPlugins={[remarkGitHubAlertsPlugin]}
|
||||
components={{
|
||||
a: ({ ...props }) => {
|
||||
const { children } = props
|
||||
a: ({ href, children, ...props }) => {
|
||||
return (
|
||||
<a {...props} target="_blank" rel="noreferrer">
|
||||
<a
|
||||
{...props}
|
||||
href={href ? '#' : undefined}
|
||||
target={undefined}
|
||||
rel={undefined}
|
||||
onClick={(event) => {
|
||||
event.preventDefault()
|
||||
if (!href) return
|
||||
openUrlWithNotice(href)
|
||||
}}
|
||||
onAuxClick={(event) => {
|
||||
event.preventDefault()
|
||||
if (event.button === 1 && href) {
|
||||
openUrlWithNotice(href)
|
||||
}
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</a>
|
||||
)
|
||||
|
||||
@@ -7,8 +7,8 @@ import { useTranslation } from 'react-i18next'
|
||||
import { BaseDialog, BaseEmpty, DialogRef } from '@/components/base'
|
||||
import { useClashInfo } from '@/hooks/use-clash'
|
||||
import { useVerge } from '@/hooks/use-verge'
|
||||
import { openWebUrl } from '@/services/cmds'
|
||||
import { showNotice } from '@/services/notice-service'
|
||||
import { openExternalUrl } from '@/utils/open-external-url'
|
||||
|
||||
import { WebUIItem } from './web-ui-item'
|
||||
|
||||
@@ -98,7 +98,7 @@ export function WebUIViewer({ ref }: { ref?: Ref<DialogRef> }) {
|
||||
)
|
||||
}
|
||||
|
||||
await openWebUrl(url)
|
||||
await openExternalUrl(url)
|
||||
} catch (e: any) {
|
||||
showNotice.error('settings.modals.webUI.errors.openFailed', e)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user