Переглянути джерело

fix: frontend security risk (#2355)

Joel 1 рік тому
батько
коміт
a667d04e53
32 змінених файлів з 59 додано та 53 видалено
  1. 1 1
      web/app/(commonLayout)/apps/NewAppDialog.tsx
  2. 2 2
      web/app/(commonLayout)/apps/page.tsx
  3. 2 2
      web/app/(commonLayout)/datasets/(datasetDetailLayout)/[datasetId]/layout.tsx
  4. 2 2
      web/app/(commonLayout)/datasets/DatasetFooter.tsx
  5. 1 1
      web/app/components/app/configuration/config-prompt/conversation-histroy/history-panel.tsx
  6. 2 2
      web/app/components/app/configuration/dataset-config/settings-modal/index.tsx
  7. 1 1
      web/app/components/app/configuration/prompt-mode/advanced-mode-waring.tsx
  8. 2 2
      web/app/components/app/configuration/toolbox/moderation/moderation-setting-modal.tsx
  9. 1 1
      web/app/components/app/configuration/tools/external-data-tool-modal.tsx
  10. 1 1
      web/app/components/app/log/index.tsx
  11. 1 1
      web/app/components/app/overview/apikey-info-panel/index.tsx
  12. 5 6
      web/app/components/app/overview/customize/index.tsx
  13. 1 1
      web/app/components/app/overview/settings/index.tsx
  14. 1 1
      web/app/components/billing/billing-page/index.tsx
  15. 1 1
      web/app/components/custom/custom-page/index.tsx
  16. 2 2
      web/app/components/custom/custom-web-app-brand/index.tsx
  17. 1 1
      web/app/components/datasets/create/step-two/index.tsx
  18. 1 1
      web/app/components/datasets/hit-testing/modify-retrieval-modal.tsx
  19. 2 2
      web/app/components/datasets/settings/form/index.tsx
  20. 5 5
      web/app/components/header/account-about/index.tsx
  21. 4 4
      web/app/components/header/account-dropdown/index.tsx
  22. 1 1
      web/app/components/header/account-setting/api-based-extension-page/empty.tsx
  23. 2 2
      web/app/components/header/account-setting/api-based-extension-page/modal.tsx
  24. 1 1
      web/app/components/header/account-setting/model-provider-page/model-modal/index.tsx
  25. 1 1
      web/app/components/header/github-star/index.tsx
  26. 1 1
      web/app/components/share/chat/welcome/index.tsx
  27. 1 1
      web/app/components/share/chatbot/welcome/index.tsx
  28. 1 1
      web/app/components/share/text-generation/index.tsx
  29. 1 1
      web/app/components/tools/contribute.tsx
  30. 1 1
      web/app/components/tools/edit-custom-collection-modal/index.tsx
  31. 3 3
      web/app/signin/normalForm.tsx
  32. 7 0
      web/utils/index.ts

+ 1 - 1
web/app/(commonLayout)/apps/NewAppDialog.tsx

@@ -157,7 +157,7 @@ const NewAppDialog = ({ show, onSuccess, onClose }: NewAppDialogProps) => {
                   </div>
                   <div className={`${style.listItemDescription} ${style.noClip}`}>{t('app.newApp.chatAppIntro')}</div>
                   {/* <div className={classNames(style.listItemFooter, 'justify-end')}>
-                    <a className={style.listItemLink} href='https://udify.app/chat/7CQBa5yyvYLSkZtx' target='_blank'>{t('app.newApp.previewDemo')}<span className={classNames(style.linkIcon, style.grayLinkIcon)} /></a>
+                    <a className={style.listItemLink} href='https://udify.app/chat/7CQBa5yyvYLSkZtx' target='_blank' rel='noopener noreferrer'>{t('app.newApp.previewDemo')}<span className={classNames(style.linkIcon, style.grayLinkIcon)} /></a>
                   </div> */}
                 </li>
                 <li

+ 2 - 2
web/app/(commonLayout)/apps/page.tsx

@@ -15,8 +15,8 @@ const AppList = async () => {
         <h3 className='text-xl font-semibold leading-tight text-gradient'>{t('join')}</h3>
         <p className='mt-1 text-sm font-normal leading-tight text-gray-700'>{t('communityIntro')}</p>
         <div className='flex items-center gap-2 mt-3'>
-          <a className={style.socialMediaLink} target='_blank' href='https://github.com/langgenius/dify'><span className={classNames(style.socialMediaIcon, style.githubIcon)} /></a>
-          <a className={style.socialMediaLink} target='_blank' href='https://discord.gg/FngNHpbcY7'><span className={classNames(style.socialMediaIcon, style.discordIcon)} /></a>
+          <a className={style.socialMediaLink} target='_blank' rel='noopener noreferrer' href='https://github.com/langgenius/dify'><span className={classNames(style.socialMediaIcon, style.githubIcon)} /></a>
+          <a className={style.socialMediaLink} target='_blank' rel='noopener noreferrer' href='https://discord.gg/FngNHpbcY7'><span className={classNames(style.socialMediaIcon, style.discordIcon)} /></a>
         </div>
       </footer>
     </div >

+ 2 - 2
web/app/(commonLayout)/datasets/(datasetDetailLayout)/[datasetId]/layout.tsx

@@ -58,7 +58,7 @@ const LikedItem = ({
   return (
     <Link className={classNames(s.itemWrapper, 'px-0', isMobile && 'justify-center')} href={`/app/${detail?.id}/overview`}>
       <div className={classNames(s.iconWrapper, 'mr-0')}>
-        <AppIcon size='tiny' icon={detail?.icon} background={detail?.icon_background}/>
+        <AppIcon size='tiny' icon={detail?.icon} background={detail?.icon_background} />
         {type === 'app' && (
           <div className={s.statusPoint}>
             <Indicator color={appStatus ? 'green' : 'gray'} />
@@ -154,7 +154,7 @@ const ExtraInfo = ({ isMobile, relatedApps }: IExtraInfoProps) => {
                 ? 'https://docs.dify.ai/v/zh-hans/guides/application-design/prompt-engineering'
                 : 'https://docs.dify.ai/user-guide/creating-dify-apps/prompt-engineering'
             }
-            target='_blank'
+            target='_blank' rel='noopener noreferrer'
           >
             <BookOpenIcon className='mr-1' />
             {t('common.datasetMenus.viewDoc')}

+ 2 - 2
web/app/(commonLayout)/datasets/DatasetFooter.tsx

@@ -9,8 +9,8 @@ const DatasetFooter = () => {
     <footer className='px-12 py-6 grow-0 shrink-0'>
       <h3 className='text-xl font-semibold leading-tight text-gradient'>{t('dataset.didYouKnow')}</h3>
       <p className='mt-1 text-sm font-normal leading-tight text-gray-700'>
-        {t('dataset.intro1')}<a className='inline-flex items-center gap-1 link' target='_blank' href='/'>{t('dataset.intro2')}</a>{t('dataset.intro3')}<br />
-        {t('dataset.intro4')}<a className='inline-flex items-center gap-1 link' target='_blank' href='/'>{t('dataset.intro5')}</a>{t('dataset.intro6')}
+        {t('dataset.intro1')}<a className='inline-flex items-center gap-1 link' target='_blank' rel='noopener noreferrer' href='/'>{t('dataset.intro2')}</a>{t('dataset.intro3')}<br />
+        {t('dataset.intro4')}<a className='inline-flex items-center gap-1 link' target='_blank' rel='noopener noreferrer' href='/'>{t('dataset.intro5')}</a>{t('dataset.intro6')}
       </p>
     </footer>
   )

+ 1 - 1
web/app/components/app/configuration/config-prompt/conversation-histroy/history-panel.tsx

@@ -49,7 +49,7 @@ const HistoryPanel: FC<Props> = ({
             <a href={`${language === LanguagesSupported[1]
               ? 'https://docs.dify.ai/v/zh-hans/guides/application-design/prompt-engineering'
               : 'https://docs.dify.ai/features/prompt-engineering'}`}
-            target='_blank'
+            target='_blank' rel='noopener noreferrer'
             className='text-[#155EEF]'>{t('appDebug.feature.conversationHistory.learnMore')}
             </a>
           </div>

+ 2 - 2
web/app/components/app/configuration/dataset-config/settings-modal/index.tsx

@@ -163,7 +163,7 @@ const SettingsModal: FC<SettingsModalProps> = ({
               className='block px-3 py-2 w-full h-[88px] rounded-lg bg-gray-100 text-sm outline-none appearance-none resize-none'
               placeholder={t('datasetSettings.form.descPlaceholder') || ''}
             />
-            <a className='mt-2 flex items-center h-[18px] px-3 text-xs text-gray-500' href="https://docs.dify.ai/features/datasets#how-to-write-a-good-dataset-description" target='_blank'>
+            <a className='mt-2 flex items-center h-[18px] px-3 text-xs text-gray-500' href="https://docs.dify.ai/features/datasets#how-to-write-a-good-dataset-description" target='_blank' rel='noopener noreferrer'>
               <BookOpenIcon className='w-3 h-[18px] mr-1' />
               {t('datasetSettings.form.descWrite')}
             </a>
@@ -226,7 +226,7 @@ const SettingsModal: FC<SettingsModalProps> = ({
             <div>
               <div>{t('datasetSettings.form.retrievalSetting.title')}</div>
               <div className='leading-[18px] text-xs font-normal text-gray-500'>
-                <a target='_blank' href='https://docs.dify.ai/features/retrieval-augment' className='text-[#155eef]'>{t('datasetSettings.form.retrievalSetting.learnMore')}</a>
+                <a target='_blank' rel='noopener noreferrer' href='https://docs.dify.ai/features/retrieval-augment' className='text-[#155eef]'>{t('datasetSettings.form.retrievalSetting.learnMore')}</a>
                 {t('datasetSettings.form.retrievalSetting.description')}
               </div>
             </div>

+ 1 - 1
web/app/components/app/configuration/prompt-mode/advanced-mode-waring.tsx

@@ -28,7 +28,7 @@ const AdvancedModeWarning: FC<Props> = ({
           <a
             className='font-medium text-[#155EEF]'
             href={`https://docs.dify.ai/${language === LanguagesSupported[1] ? 'v/zh-hans/guides/application-design/prompt-engineering' : 'features/prompt-engineering'}`}
-            target='_blank'
+            target='_blank' rel='noopener noreferrer'
           >
             {t('appDebug.promptMode.advancedWarning.learnMore')}
           </a>

+ 2 - 2
web/app/components/app/configuration/toolbox/moderation/moderation-setting-modal.tsx

@@ -237,7 +237,7 @@ const ModerationSettingModal: FC<ModerationSettingModalProps> = ({
   return (
     <Modal
       isShow
-      onClose={() => {}}
+      onClose={() => { }}
       className='!p-8 !pb-6 !mt-14 !max-w-none !w-[640px]'
     >
       <div className='mb-2 text-xl font-semibold text-[#1D2939]'>
@@ -311,7 +311,7 @@ const ModerationSettingModal: FC<ModerationSettingModalProps> = ({
               <div className='text-sm font-medium text-gray-900'>{t('common.apiBasedExtension.selector.title')}</div>
               <a
                 href={t('common.apiBasedExtension.linkUrl') || '/'}
-                target='_blank'
+                target='_blank' rel='noopener noreferrer'
                 className='group flex items-center text-xs text-gray-500 hover:text-primary-600'
               >
                 <BookOpen01 className='mr-1 w-3 h-3 text-gray-500 group-hover:text-primary-600' />

+ 1 - 1
web/app/components/app/configuration/tools/external-data-tool-modal.tsx

@@ -245,7 +245,7 @@ const ExternalDataToolModal: FC<ExternalDataToolModalProps> = ({
               {t('common.apiBasedExtension.selector.title')}
               <a
                 href={t('common.apiBasedExtension.linkUrl') || '/'}
-                target='_blank'
+                target='_blank' rel='noopener noreferrer'
                 className='group flex items-center text-xs font-normal text-gray-500 hover:text-primary-600'
               >
                 <BookOpen01 className='mr-1 w-3 h-3 text-gray-500 group-hover:text-primary-600' />

+ 1 - 1
web/app/components/app/log/index.tsx

@@ -43,7 +43,7 @@ const EmptyElement: FC<{ appUrl: string }> = ({ appUrl }) => {
       <div className='mt-2 text-gray-500 text-sm font-normal'>
         <Trans
           i18nKey="appLog.table.empty.element.content"
-          components={{ shareLink: <Link href={`${pathSegments.join('/')}/overview`} className='text-primary-600' />, testLink: <Link href={appUrl} className='text-primary-600' target='_blank' /> }}
+          components={{ shareLink: <Link href={`${pathSegments.join('/')}/overview`} className='text-primary-600' />, testLink: <Link href={appUrl} className='text-primary-600' target='_blank' rel='noopener noreferrer' /> }}
         />
       </div>
     </div>

+ 1 - 1
web/app/components/app/overview/apikey-info-panel/index.tsx

@@ -55,7 +55,7 @@ const APIKeyInfoPanel: FC = () => {
         <a
           className='mt-2 flex items-center h-[26px] text-xs  font-medium text-[#155EEF] p-1 space-x-1'
           href='https://cloud.dify.ai/apps'
-          target='_blank'
+          target='_blank' rel='noopener noreferrer'
         >
           <div>{t('appOverview.apiKeyInfo.tryCloud')}</div>
           <LinkExternal02 className='w-3 h-3' />

+ 5 - 6
web/app/components/app/overview/customize/index.tsx

@@ -63,7 +63,7 @@ const CustomizeModal: FC<IShareLinkProps> = ({
         <div className='flex flex-col'>
           <div className='text-gray-900'>{t(`${prefixCustomize}.way1.step1`)}</div>
           <div className='text-gray-500 text-xs mt-1 mb-2'>{t(`${prefixCustomize}.way1.step1Tip`)}</div>
-          <a href={`https://github.com/langgenius/${isChatApp ? 'webapp-conversation' : 'webapp-text-generator'}`} target='_blank'>
+          <a href={`https://github.com/langgenius/${isChatApp ? 'webapp-conversation' : 'webapp-text-generator'}`} target='_blank' rel='noopener noreferrer'>
             <Button className='text-gray-800 text-sm w-fit'><GithubIcon className='text-gray-800 mr-2' />{t(`${prefixCustomize}.way1.step1Operation`)}</Button>
           </a>
         </div>
@@ -73,7 +73,7 @@ const CustomizeModal: FC<IShareLinkProps> = ({
         <div className='flex flex-col'>
           <div className='text-gray-900'>{t(`${prefixCustomize}.way1.step3`)}</div>
           <div className='text-gray-500 text-xs mt-1 mb-2'>{t(`${prefixCustomize}.way1.step2Tip`)}</div>
-          <a href="https://vercel.com/docs/concepts/deployments/git/vercel-for-github" target='_blank'>
+          <a href="https://vercel.com/docs/concepts/deployments/git/vercel-for-github" target='_blank' rel='noopener noreferrer'>
             <Button className='text-gray-800 text-sm w-fit'>
               <div className='mr-1.5 border-solid border-t-0 border-r-[7px] border-l-[7px] border-b-[12px] border-r-transparent border-b-black border-l-transparent border-t-transparent'></div>
               <span>{t(`${prefixCustomize}.way1.step2Operation`)}</span>
@@ -102,10 +102,9 @@ const CustomizeModal: FC<IShareLinkProps> = ({
         className='w-36 mt-2'
         onClick={() =>
           window.open(
-            `https://docs.dify.ai/${
-              language !== LanguagesSupportedUnderscore[1]
-                ? 'user-guide/launching-dify-apps/developing-with-apis'
-                : `v/${locale.toLowerCase()}/guides/application-publishing/developing-with-apis`
+            `https://docs.dify.ai/${language !== LanguagesSupportedUnderscore[1]
+              ? 'user-guide/launching-dify-apps/developing-with-apis'
+              : `v/${locale.toLowerCase()}/guides/application-publishing/developing-with-apis`
             }`,
             '_blank',
           )

+ 1 - 1
web/app/components/app/overview/settings/index.tsx

@@ -147,7 +147,7 @@ const SettingsModal: FC<ISettingsModalProps> = ({
           <p className={`mt-1 ${s.settingsTip} text-gray-500`}>
             <Trans
               i18nKey={`${prefixSettings}.more.privacyPolicyTip`}
-              components={{ privacyPolicyLink: <Link href={'https://docs.dify.ai/user-agreement/privacy-policy'} target='_blank' className='text-primary-600' /> }}
+              components={{ privacyPolicyLink: <Link href={'https://docs.dify.ai/user-agreement/privacy-policy'} target='_blank' rel='noopener noreferrer' className='text-primary-600' /> }}
             />
           </p>
           <input className={`w-full mt-2 rounded-lg h-10 box-border px-3 ${s.projectName} bg-gray-100`}

+ 1 - 1
web/app/components/billing/billing-page/index.tsx

@@ -28,7 +28,7 @@ const Billing: FC = () => {
     <div>
       <PlanComp loc={'billing-page'} />
       {enableBilling && isCurrentWorkspaceManager && billingUrl && (
-        <a className='mt-5 flex px-6 justify-between h-12 items-center bg-gray-50 rounded-xl cursor-pointer' href={billingUrl} target='_blank'>
+        <a className='mt-5 flex px-6 justify-between h-12 items-center bg-gray-50 rounded-xl cursor-pointer' href={billingUrl} target='_blank' rel='noopener noreferrer'>
           <div className='flex items-center'>
             <ReceiptList className='w-4 h-4 text-gray-700' />
             <div className='ml-2 text-sm font-normal text-gray-700'>{t('billing.viewBilling')}</div>

+ 1 - 1
web/app/components/custom/custom-page/index.tsx

@@ -44,7 +44,7 @@ const CustomPage = () => {
         showContact && (
           <div className='absolute bottom-0 h-[50px] leading-[50px] text-xs text-gray-500'>
             {t('custom.customize.prefix')}
-            <a className='text-[#155EEF]' href={contactSalesUrl} target='_blank'>{t('custom.customize.contactUs')}</a>
+            <a className='text-[#155EEF]' href={contactSalesUrl} target='_blank' rel='noopener noreferrer'>{t('custom.customize.contactUs')}</a>
             {t('custom.customize.suffix')}
           </div>
         )

+ 2 - 2
web/app/components/custom/custom-web-app-brand/index.tsx

@@ -11,13 +11,13 @@ import { ImagePlus } from '@/app/components/base/icons/src/vender/line/images'
 import { useProviderContext } from '@/context/provider-context'
 import { Plan } from '@/app/components/billing/type'
 import { imageUpload } from '@/app/components/base/image-uploader/utils'
-import type {} from '@/app/components/base/image-uploader/utils'
 import { useToastContext } from '@/app/components/base/toast'
 import {
   updateCurrentWorkspace,
 } from '@/service/common'
 import { useAppContext } from '@/context/app-context'
 import { API_PREFIX } from '@/config'
+import { getPurifyHref } from '@/utils'
 
 const ALLOW_FILE_EXTENSIONS = ['svg', 'png']
 
@@ -123,7 +123,7 @@ const CustomWebAppBrand = () => {
                 POWERED BY
                 {
                   webappLogo
-                    ? <img key={webappLogo} src={`${API_PREFIX.slice(0, -12)}/files/workspaces/${currentWorkspace.id}/webapp-logo`} alt='logo' className='ml-2 block w-auto h-5' />
+                    ? <img key={webappLogo} src={`${getPurifyHref(API_PREFIX.slice(0, -12))}/files/workspaces/${currentWorkspace.id}/webapp-logo`} alt='logo' className='ml-2 block w-auto h-5' />
                     : <LogoSite className='ml-2 !h-5' />
                 }
               </div>

+ 1 - 1
web/app/components/datasets/create/step-two/index.tsx

@@ -738,7 +738,7 @@ const StepTwo = ({
                   <div className={s.label}>
                     {t('datasetSettings.form.retrievalSetting.title')}
                     <div className='leading-[18px] text-xs font-normal text-gray-500'>
-                      <a target='_blank' href='https://docs.dify.ai/features/retrieval-augment' className='text-[#155eef]'>{t('datasetSettings.form.retrievalSetting.learnMore')}</a>
+                      <a target='_blank' rel='noopener noreferrer' href='https://docs.dify.ai/features/retrieval-augment' className='text-[#155eef]'>{t('datasetSettings.form.retrievalSetting.learnMore')}</a>
                       {t('datasetSettings.form.retrievalSetting.longDescription')}
                     </div>
                   </div>

+ 1 - 1
web/app/components/datasets/hit-testing/modify-retrieval-modal.tsx

@@ -76,7 +76,7 @@ const ModifyRetrievalModal: FC<Props> = ({
         <div className='text-base font-semibold text-gray-900'>
           <div>{t('datasetSettings.form.retrievalSetting.title')}</div>
           <div className='leading-[18px] text-xs font-normal text-gray-500'>
-            <a target='_blank' href='https://docs.dify.ai/features/retrieval-augment' className='text-[#155eef]'>{t('datasetSettings.form.retrievalSetting.learnMore')}</a>
+            <a target='_blank' rel='noopener noreferrer' href='https://docs.dify.ai/features/retrieval-augment' className='text-[#155eef]'>{t('datasetSettings.form.retrievalSetting.learnMore')}</a>
             {t('datasetSettings.form.retrievalSetting.description')}
           </div>
         </div>

+ 2 - 2
web/app/components/datasets/settings/form/index.tsx

@@ -146,7 +146,7 @@ const Form = () => {
             value={description}
             onChange={e => setDescription(e.target.value)}
           />
-          <a className='flex items-center h-[18px] px-3 text-xs text-gray-500' href="https://docs.dify.ai/features/datasets#how-to-write-a-good-dataset-description" target='_blank'>
+          <a className='flex items-center h-[18px] px-3 text-xs text-gray-500' href="https://docs.dify.ai/features/datasets#how-to-write-a-good-dataset-description" target='_blank' rel='noopener noreferrer'>
             <BookOpenIcon className='w-3 h-[18px] mr-1' />
             {t('datasetSettings.form.descWrite')}
           </a>
@@ -209,7 +209,7 @@ const Form = () => {
           <div>
             <div>{t('datasetSettings.form.retrievalSetting.title')}</div>
             <div className='leading-[18px] text-xs font-normal text-gray-500'>
-              <a target='_blank' href='https://docs.dify.ai/features/retrieval-augment' className='text-[#155eef]'>{t('datasetSettings.form.retrievalSetting.learnMore')}</a>
+              <a target='_blank' rel='noopener noreferrer' href='https://docs.dify.ai/features/retrieval-augment' className='text-[#155eef]'>{t('datasetSettings.form.retrievalSetting.learnMore')}</a>
               {t('datasetSettings.form.retrievalSetting.description')}
             </div>
           </div>

+ 5 - 5
web/app/components/header/account-about/index.tsx

@@ -47,10 +47,10 @@ export default function AccountAbout({
             <div className='text-[#1C64F2]'>
               {
                 IS_CE_EDITION
-                  ? <Link href={'https://github.com/langgenius/dify/blob/main/LICENSE'} target='_blank'>Open Source License</Link>
+                  ? <Link href={'https://github.com/langgenius/dify/blob/main/LICENSE'} target='_blank' rel='noopener noreferrer'>Open Source License</Link>
                   : <>
-                    <Link href={language !== LanguagesSupportedUnderscore[1] ? 'https://docs.dify.ai/user-agreement/privacy-policy' : 'https://docs.dify.ai/v/zh-hans/user-agreement/privacy-policy'} target='_blank'>Privacy Policy</Link>,
-                    <Link href={language !== LanguagesSupportedUnderscore[1] ? 'https://docs.dify.ai/user-agreement/terms-of-service' : 'https://docs.dify.ai/v/zh-hans/user-agreement/terms-of-service'} target='_blank'>Terms of Service</Link>
+                    <Link href={language !== LanguagesSupportedUnderscore[1] ? 'https://docs.dify.ai/user-agreement/privacy-policy' : 'https://docs.dify.ai/v/zh-hans/user-agreement/privacy-policy'} target='_blank' rel='noopener noreferrer'>Privacy Policy</Link>,
+                    <Link href={language !== LanguagesSupportedUnderscore[1] ? 'https://docs.dify.ai/user-agreement/terms-of-service' : 'https://docs.dify.ai/v/zh-hans/user-agreement/terms-of-service'} target='_blank' rel='noopener noreferrer'>Terms of Service</Link>
                   </>
               }
             </div>
@@ -69,7 +69,7 @@ export default function AccountAbout({
             <Link
               className={classNames(buttonClassName, 'mr-2')}
               href={'https://github.com/langgenius/dify/releases'}
-              target='_blank'
+              target='_blank' rel='noopener noreferrer'
             >
               {t('common.about.changeLog')}
             </Link>
@@ -78,7 +78,7 @@ export default function AccountAbout({
                 <Link
                   className={classNames(buttonClassName, 'text-primary-600')}
                   href={langeniusVersionInfo.release_notes}
-                  target='_blank'
+                  target='_blank' rel='noopener noreferrer'
                 >
                   {t('common.about.updateNow')}
                 </Link>

+ 4 - 4
web/app/components/header/account-dropdown/index.tsx

@@ -62,7 +62,7 @@ export default function AppSelector({ isMobile }: IAppSelecotr) {
                   <Avatar name={userProfile.name} className='sm:mr-2 mr-0' size={32} />
                   {!isMobile && <>
                     {userProfile.name}
-                    <ChevronDown className="w-3 h-3 ml-1 text-gray-700"/>
+                    <ChevronDown className="w-3 h-3 ml-1 text-gray-700" />
                   </>}
                 </Menu.Button>
               </div>
@@ -105,7 +105,7 @@ export default function AppSelector({ isMobile }: IAppSelecotr) {
                       <Link
                         className={classNames(itemClassName, 'group justify-between')}
                         href='https://feedback.dify.ai/'
-                        target='_blank'>
+                        target='_blank' rel='noopener noreferrer'>
                         <div>{t('common.userProfile.roadmapAndFeedback')}</div>
                         <ArrowUpRight className='hidden w-[14px] h-[14px] text-gray-500 group-hover:flex' />
                       </Link>
@@ -114,7 +114,7 @@ export default function AppSelector({ isMobile }: IAppSelecotr) {
                       <Link
                         className={classNames(itemClassName, 'group justify-between')}
                         href='https://discord.gg/5AEfbxcd9k'
-                        target='_blank'>
+                        target='_blank' rel='noopener noreferrer'>
                         <div>{t('common.userProfile.community')}</div>
                         <ArrowUpRight className='hidden w-[14px] h-[14px] text-gray-500 group-hover:flex' />
                       </Link>
@@ -125,7 +125,7 @@ export default function AppSelector({ isMobile }: IAppSelecotr) {
                         href={
                           language !== LanguagesSupportedUnderscore[1] ? 'https://docs.dify.ai/' : `https://docs.dify.ai/v/${locale.toLowerCase()}/`
                         }
-                        target='_blank'>
+                        target='_blank' rel='noopener noreferrer'>
                         <div>{t('common.userProfile.helpCenter')}</div>
                         <ArrowUpRight className='hidden w-[14px] h-[14px] text-gray-500 group-hover:flex' />
                       </Link>

+ 1 - 1
web/app/components/header/account-setting/api-based-extension-page/empty.tsx

@@ -14,7 +14,7 @@ const Empty = () => {
       <a
         className='flex items-center mb-2 h-[18px] text-xs text-primary-600'
         href={t('common.apiBasedExtension.linkUrl') || '/'}
-        target='_blank'
+        target='_blank' rel='noopener noreferrer'
       >
         <BookOpen01 className='mr-1 w-3 h-3' />
         {t('common.apiBasedExtension.link')}

+ 2 - 2
web/app/components/header/account-setting/api-based-extension-page/modal.tsx

@@ -74,7 +74,7 @@ const ApiBasedExtensionModal: FC<ApiBasedExtensionModalProps> = ({
   return (
     <Modal
       isShow
-      onClose={() => {}}
+      onClose={() => { }}
       wrapperClassName='!z-[103]'
       className='!p-8 !pb-6 !max-w-none !w-[640px]'
     >
@@ -101,7 +101,7 @@ const ApiBasedExtensionModal: FC<ApiBasedExtensionModalProps> = ({
           {t('common.apiBasedExtension.modal.apiEndpoint.title')}
           <a
             href={t('common.apiBasedExtension.linkUrl') || '/'}
-            target='_blank'
+            target='_blank' rel='noopener noreferrer'
             className='group flex items-center text-xs text-gray-500 font-normal hover:text-primary-600'
           >
             <BookOpen01 className='mr-1 w-3 h-3 text-gray-500 group-hover:text-primary-600' />

+ 1 - 1
web/app/components/header/account-setting/model-provider-page/model-modal/index.tsx

@@ -247,7 +247,7 @@ const ModelModal: FC<ModelModalProps> = ({
                     ? (
                       <a
                         href={provider.help?.url[language]}
-                        target='_blank'
+                        target='_blank' rel='noopener noreferrer'
                         className='inline-flex items-center text-xs text-primary-600'
                         onClick={e => !provider.help.url && e.preventDefault()}
                       >

+ 1 - 1
web/app/components/header/github-star/index.tsx

@@ -36,7 +36,7 @@ const GithubStar = () => {
   return (
     <a
       href='https://github.com/langgenius/dify'
-      target='_blank'
+      target='_blank' rel='noopener noreferrer'
       className='flex items-center leading-[18px] border border-gray-200 rounded-md text-xs text-gray-700 font-semibold overflow-hidden'>
       <div className='flex items-center px-2 py-1 bg-gray-100'>
         <Github className='mr-1 w-[18px] h-[18px]' />

+ 1 - 1
web/app/components/share/chat/welcome/index.tsx

@@ -350,7 +350,7 @@ const Welcome: FC<IWelcomeProps> = ({
                 <a
                   className='text-gray-500'
                   href={siteInfo.privacy_policy}
-                  target='_blank'>{t('share.chat.privacyPolicyMiddle')}</a>
+                  target='_blank' rel='noopener noreferrer'>{t('share.chat.privacyPolicyMiddle')}</a>
                 {t('share.chat.privacyPolicyRight')}
               </div>
               : <div>

+ 1 - 1
web/app/components/share/chatbot/welcome/index.tsx

@@ -351,7 +351,7 @@ const Welcome: FC<IWelcomeProps> = ({
                 <a
                   className='text-gray-500'
                   href={siteInfo.privacy_policy}
-                  target='_blank'>{t('share.chat.privacyPolicyMiddle')}</a>
+                  target='_blank' rel='noopener noreferrer'>{t('share.chat.privacyPolicyMiddle')}</a>
                 {t('share.chat.privacyPolicyRight')}
               </div>
               : <div>

+ 1 - 1
web/app/components/share/text-generation/index.tsx

@@ -591,7 +591,7 @@ const TextGeneration: FC<IMainProps> = ({
                   <a
                     className='text-gray-500'
                     href={siteInfo.privacy_policy}
-                    target='_blank'>{t('share.chat.privacyPolicyMiddle')}</a>
+                    target='_blank' rel='noopener noreferrer'>{t('share.chat.privacyPolicyMiddle')}</a>
                   {t('share.chat.privacyPolicyRight')}
                 </div>
               </>

+ 1 - 1
web/app/components/tools/contribute.tsx

@@ -21,7 +21,7 @@ const Contribute: FC = () => {
           {t('tools.contribute.line2')}
         </div>
       </div>
-      <a href='https://github.com/langgenius/dify/blob/main/CONTRIBUTING.md' target='_blank' className='mt-1 flex items-center space-x-1 text-[#155EEF]'>
+      <a href='https://github.com/langgenius/dify/blob/main/CONTRIBUTING.md' target='_blank' rel='noopener noreferrer' className='mt-1 flex items-center space-x-1 text-[#155EEF]'>
         <BookOpen01 className='w-3 h-3' />
         <div className='leading-[18px] text-xs font-normal'>{t('tools.contribute.viewGuide')}</div>
       </a>

+ 1 - 1
web/app/components/tools/edit-custom-collection-modal/index.tsx

@@ -177,7 +177,7 @@ const EditCustomCollectionModal: FC<Props> = ({
                     <div className='mx-2 w-px h-3 bg-black/5'></div>
                     <a
                       href="https://swagger.io/specification/"
-                      target='_blank'
+                      target='_blank' rel='noopener noreferrer'
                       className='flex items-center h-[18px] space-x-1  text-[#155EEF]'
                     >
                       <div className='text-xs font-normal'>{t('tools.createTool.viewSchemaSpec')}</div>

+ 3 - 3
web/app/signin/normalForm.tsx

@@ -13,7 +13,7 @@ import Button from '@/app/components/base/button'
 import { login, oauth } from '@/service/common'
 import I18n from '@/context/i18n'
 import { LanguagesSupportedUnderscore, getModelRuntimeSupported } from '@/utils/language'
-
+import { getPurifyHref } from '@/utils'
 const validEmailReg = /^[\w\.-]+@([\w-]+\.)+[\w-]{2,}$/
 
 type IState = {
@@ -150,7 +150,7 @@ const NormalForm = () => {
           {!IS_CE_EDITION && (
             <div className="flex flex-col gap-3 mt-6">
               <div className='w-full'>
-                <a href={`${apiPrefix}/oauth/login/github`}>
+                <a href={getPurifyHref(`${apiPrefix}/oauth/login/github`)}>
                   <Button
                     type='default'
                     disabled={isLoading}
@@ -169,7 +169,7 @@ const NormalForm = () => {
                 </a>
               </div>
               <div className='w-full'>
-                <a href={`${apiPrefix}/oauth/login/google`}>
+                <a href={getPurifyHref(`${apiPrefix}/oauth/login/google`)}>
                   <Button
                     type='default'
                     disabled={isLoading}

+ 7 - 0
web/utils/index.ts

@@ -30,3 +30,10 @@ export function randomString(length: number) {
   for (let i = length; i > 0; --i) result += chars[Math.floor(Math.random() * chars.length)]
   return result
 }
+
+export const getPurifyHref = (href: string) => {
+  if (!href)
+    return ''
+
+  return href.replace(/javascript:/ig, '').replace(/vbscript:/ig, '').replace(/data:/ig, '')
+}