🔒️(frontend) harden security check on url
We harden the security check on url to prevent attacks.
This commit is contained in:
@@ -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<CheckDocMediaStatusResponse> => {
|
||||
if (!isSafeUrl(urlMedia) || !urlMedia.includes(ANALYZE_URL)) {
|
||||
throw new APIError('Url invalid', { status: 400 });
|
||||
}
|
||||
|
||||
const response = await fetch(urlMedia, {
|
||||
credentials: 'include',
|
||||
});
|
||||
|
||||
@@ -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 (
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -13,9 +13,7 @@ const getDocVersion = async ({
|
||||
versionId,
|
||||
docId,
|
||||
}: DocVersionParam): Promise<Version> => {
|
||||
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(
|
||||
|
||||
@@ -29,9 +29,9 @@ const getDocVersions = async ({
|
||||
versionId,
|
||||
docId,
|
||||
}: DocVersionsAPIParams): Promise<VersionsResponse> => {
|
||||
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(
|
||||
|
||||
Reference in New Issue
Block a user