diff --git a/src/frontend/apps/impress/src/features/docs/doc-editor/api/checkDocMediaStatus.tsx b/src/frontend/apps/impress/src/features/docs/doc-editor/api/checkDocMediaStatus.tsx index d0841a05..0014547a 100644 --- a/src/frontend/apps/impress/src/features/docs/doc-editor/api/checkDocMediaStatus.tsx +++ b/src/frontend/apps/impress/src/features/docs/doc-editor/api/checkDocMediaStatus.tsx @@ -1,5 +1,8 @@ import { APIError, errorCauses } from '@/api'; import { sleep } from '@/utils'; +import { isSafeUrl } from '@/utils/url'; + +import { ANALYZE_URL } from '../conf'; interface CheckDocMediaStatusResponse { file?: string; @@ -13,6 +16,10 @@ interface CheckDocMediaStatus { export const checkDocMediaStatus = async ({ urlMedia, }: CheckDocMediaStatus): Promise => { + if (!isSafeUrl(urlMedia) || !urlMedia.includes(ANALYZE_URL)) { + throw new APIError('Url invalid', { status: 400 }); + } + const response = await fetch(urlMedia, { credentials: 'include', }); diff --git a/src/frontend/apps/impress/src/features/docs/doc-editor/components/custom-blocks/PdfBlock.tsx b/src/frontend/apps/impress/src/features/docs/doc-editor/components/custom-blocks/PdfBlock.tsx index bac459c9..e6d29c6e 100644 --- a/src/frontend/apps/impress/src/features/docs/doc-editor/components/custom-blocks/PdfBlock.tsx +++ b/src/frontend/apps/impress/src/features/docs/doc-editor/components/custom-blocks/PdfBlock.tsx @@ -18,6 +18,7 @@ import { useTranslation } from 'react-i18next'; import { createGlobalStyle } from 'styled-components'; import { Box, Icon, Loading } from '@/components'; +import { isSafeUrl } from '@/utils/url'; import Warning from '../../assets/warning.svg'; import { ANALYZE_URL } from '../../conf'; @@ -87,7 +88,7 @@ const PdfBlockComponent = ({ editor, block }: PdfBlockComponentProps) => { }, [lang, t]); useEffect(() => { - if (!pdfUrl || pdfUrl.includes(ANALYZE_URL)) { + if (!pdfUrl || pdfUrl.includes(ANALYZE_URL) || !isSafeUrl(pdfUrl)) { return; } @@ -115,7 +116,8 @@ const PdfBlockComponent = ({ editor, block }: PdfBlockComponentProps) => { }, [pdfUrl]); const isInvalidPDF = - !isPDFContentLoading && isPDFContent !== null && !isPDFContent; + (!isPDFContentLoading && isPDFContent !== null && !isPDFContent) || + !isSafeUrl(pdfUrl); if (isInvalidPDF) { return ( diff --git a/src/frontend/apps/impress/src/features/docs/doc-editor/components/custom-blocks/UploadLoaderBlock.tsx b/src/frontend/apps/impress/src/features/docs/doc-editor/components/custom-blocks/UploadLoaderBlock.tsx index 39406239..67934a4f 100644 --- a/src/frontend/apps/impress/src/features/docs/doc-editor/components/custom-blocks/UploadLoaderBlock.tsx +++ b/src/frontend/apps/impress/src/features/docs/doc-editor/components/custom-blocks/UploadLoaderBlock.tsx @@ -11,6 +11,7 @@ import { useEffect } from 'react'; import { Box, Text } from '@/components'; import { useMediaUrl } from '@/core'; +import { isSafeUrl } from '@/utils/url'; import { loopCheckDocMediaStatus } from '../../api'; import Loader from '../../assets/loader.svg'; @@ -67,7 +68,7 @@ const UploadLoaderBlockComponent = ({ block.props.type === 'loading' && isEditable; - if (!shouldCheckStatus) { + if (!shouldCheckStatus || !isSafeUrl(block.props.blockUploadUrl)) { return; } diff --git a/src/frontend/apps/impress/src/features/docs/doc-editor/hook/useUploadFile.tsx b/src/frontend/apps/impress/src/features/docs/doc-editor/hook/useUploadFile.tsx index 2687bad9..5913f2d5 100644 --- a/src/frontend/apps/impress/src/features/docs/doc-editor/hook/useUploadFile.tsx +++ b/src/frontend/apps/impress/src/features/docs/doc-editor/hook/useUploadFile.tsx @@ -4,6 +4,7 @@ import { useCallback, useEffect } from 'react'; import { useTranslation } from 'react-i18next'; import { backendUrl } from '@/api'; +import { isSafeUrl } from '@/utils/url'; import { useCreateDocAttachment } from '../api'; import { ANALYZE_URL } from '../conf'; @@ -57,7 +58,8 @@ export const useUploadStatus = (editor: DocsBlockNoteEditor) => { if ( !block || !('url' in block.props) || - ('url' in block.props && !block.props.url.includes(ANALYZE_URL)) + ('url' in block.props && !block.props.url.includes(ANALYZE_URL)) || + !isSafeUrl(block.props.url) ) { return; } diff --git a/src/frontend/apps/impress/src/features/docs/doc-export/utils_html.ts b/src/frontend/apps/impress/src/features/docs/doc-export/utils_html.ts index b64ee756..571f5faf 100644 --- a/src/frontend/apps/impress/src/features/docs/doc-export/utils_html.ts +++ b/src/frontend/apps/impress/src/features/docs/doc-export/utils_html.ts @@ -1,5 +1,7 @@ import JSZip from 'jszip'; +import { isSafeUrl } from '@/utils/url'; + import { exportResolveFileUrl } from './api'; // Escape user-provided text before injecting it into the exported HTML document. @@ -414,7 +416,7 @@ export const addMediaFilesToZip = async ( url = null; } - if (!url || url.origin !== mediaUrl) { + if (!url || url.origin !== mediaUrl || !isSafeUrl(url.href)) { return; } diff --git a/src/frontend/apps/impress/src/features/docs/doc-versioning/api/useDocVersion.tsx b/src/frontend/apps/impress/src/features/docs/doc-versioning/api/useDocVersion.tsx index 3af15aad..35c148ac 100644 --- a/src/frontend/apps/impress/src/features/docs/doc-versioning/api/useDocVersion.tsx +++ b/src/frontend/apps/impress/src/features/docs/doc-versioning/api/useDocVersion.tsx @@ -13,9 +13,7 @@ const getDocVersion = async ({ versionId, docId, }: DocVersionParam): Promise => { - const url = `documents/${docId}/versions/${versionId}/`; - - const response = await fetchAPI(url); + const response = await fetchAPI(`documents/${docId}/versions/${versionId}/`); if (!response.ok) { throw new APIError( diff --git a/src/frontend/apps/impress/src/features/docs/doc-versioning/api/useDocVersions.tsx b/src/frontend/apps/impress/src/features/docs/doc-versioning/api/useDocVersions.tsx index cd6adcdb..80cb2049 100644 --- a/src/frontend/apps/impress/src/features/docs/doc-versioning/api/useDocVersions.tsx +++ b/src/frontend/apps/impress/src/features/docs/doc-versioning/api/useDocVersions.tsx @@ -29,9 +29,9 @@ const getDocVersions = async ({ versionId, docId, }: DocVersionsAPIParams): Promise => { - const url = `documents/${docId}/versions/?version_id=${versionId}`; - - const response = await fetchAPI(url); + const response = await fetchAPI( + `documents/${docId}/versions/?version_id=${versionId}`, + ); if (!response.ok) { throw new APIError(