Skip to content

Commit b40fda0

Browse files
aks07Aditya Singh
andauthored
fix: add safeguard for large log body entries (#8560)
* fix: add safeguard for large log body entries * feat: added test cases for getSanitizedLogBody * feat: minor refactor * feat: revert try catch * feat: minor refactor * feat: minor refactor --------- Co-authored-by: Aditya Singh <[email protected]>
1 parent c9e8114 commit b40fda0

File tree

8 files changed

+190
-58
lines changed

8 files changed

+190
-58
lines changed

frontend/src/components/LogDetail/index.tsx

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
import './LogDetails.styles.scss';
33

44
import { Color, Spacing } from '@signozhq/design-tokens';
5-
import Convert from 'ansi-to-html';
65
import { Button, Divider, Drawer, Radio, Tooltip, Typography } from 'antd';
76
import { RadioChangeEvent } from 'antd/lib';
87
import cx from 'classnames';
@@ -17,12 +16,10 @@ import JSONView from 'container/LogDetailedView/JsonView';
1716
import Overview from 'container/LogDetailedView/Overview';
1817
import {
1918
aggregateAttributesResourcesToString,
20-
escapeHtml,
19+
getSanitizedLogBody,
2120
removeEscapeCharacters,
22-
unescapeString,
2321
} from 'container/LogDetailedView/utils';
2422
import { useOptionsMenu } from 'container/OptionsMenu';
25-
import dompurify from 'dompurify';
2623
import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder';
2724
import { useIsDarkMode } from 'hooks/useDarkMode';
2825
import { useNotifications } from 'hooks/useNotifications';
@@ -46,14 +43,11 @@ import { AppState } from 'store/reducers';
4643
import { Query, TagFilter } from 'types/api/queryBuilder/queryBuilderData';
4744
import { DataSource, StringOperators } from 'types/common/queryBuilder';
4845
import { GlobalReducer } from 'types/reducer/globalTime';
49-
import { FORBID_DOM_PURIFY_TAGS } from 'utils/app';
5046

5147
import { RESOURCE_KEYS, VIEW_TYPES, VIEWS } from './constants';
5248
import { LogDetailProps } from './LogDetail.interfaces';
5349
import QueryBuilderSearchWrapper from './QueryBuilderSearchWrapper';
5450

55-
const convert = new Convert();
56-
5751
function LogDetail({
5852
log,
5953
onClose,
@@ -118,11 +112,7 @@ function LogDetail({
118112

119113
const htmlBody = useMemo(
120114
() => ({
121-
__html: convert.toHtml(
122-
dompurify.sanitize(unescapeString(escapeHtml(log?.body || '')), {
123-
FORBID_TAGS: [...FORBID_DOM_PURIFY_TAGS],
124-
}),
125-
),
115+
__html: getSanitizedLogBody(log?.body || '', { shouldEscapeHtml: true }),
126116
}),
127117
[log?.body],
128118
);

frontend/src/components/Logs/ListLogView/index.tsx

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,13 @@
11
import './ListLogView.styles.scss';
22

33
import { blue } from '@ant-design/colors';
4-
import Convert from 'ansi-to-html';
54
import { Typography } from 'antd';
65
import cx from 'classnames';
76
import LogDetail from 'components/LogDetail';
87
import { VIEW_TYPES } from 'components/LogDetail/constants';
98
import { DATE_TIME_FORMATS } from 'constants/dateTimeFormats';
10-
import { escapeHtml, unescapeString } from 'container/LogDetailedView/utils';
9+
import { getSanitizedLogBody } from 'container/LogDetailedView/utils';
1110
import { FontSize } from 'container/OptionsMenu/types';
12-
import dompurify from 'dompurify';
1311
import { useActiveLog } from 'hooks/logs/useActiveLog';
1412
import { useCopyLogLink } from 'hooks/logs/useCopyLogLink';
1513
import { useIsDarkMode } from 'hooks/useDarkMode';
@@ -20,7 +18,6 @@ import { useCallback, useMemo, useState } from 'react';
2018
// interfaces
2119
import { IField } from 'types/api/logs/fields';
2220
import { ILog } from 'types/api/logs/log';
23-
import { FORBID_DOM_PURIFY_TAGS } from 'utils/app';
2421

2522
// components
2623
import AddToQueryHOC, { AddToQueryHOCProps } from '../AddToQueryHOC';
@@ -37,8 +34,6 @@ import {
3734
} from './styles';
3835
import { isValidLogField } from './util';
3936

40-
const convert = new Convert();
41-
4237
interface LogFieldProps {
4338
fieldKey: string;
4439
fieldValue: string;
@@ -57,11 +52,7 @@ function LogGeneralField({
5752
}: LogFieldProps): JSX.Element {
5853
const html = useMemo(
5954
() => ({
60-
__html: convert.toHtml(
61-
dompurify.sanitize(unescapeString(escapeHtml(fieldValue)), {
62-
FORBID_TAGS: [...FORBID_DOM_PURIFY_TAGS],
63-
}),
64-
),
55+
__html: getSanitizedLogBody(fieldValue, { shouldEscapeHtml: true }),
6556
}),
6657
[fieldValue],
6758
);

frontend/src/components/Logs/RawLogView/index.tsx

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
11
import './RawLogView.styles.scss';
22

3-
import Convert from 'ansi-to-html';
43
import { DrawerProps } from 'antd';
54
import LogDetail from 'components/LogDetail';
65
import { VIEW_TYPES, VIEWS } from 'components/LogDetail/constants';
76
import { DATE_TIME_FORMATS } from 'constants/dateTimeFormats';
8-
import { escapeHtml, unescapeString } from 'container/LogDetailedView/utils';
7+
import { getSanitizedLogBody } from 'container/LogDetailedView/utils';
98
import LogsExplorerContext from 'container/LogsExplorerContext';
10-
import dompurify from 'dompurify';
119
import { useActiveLog } from 'hooks/logs/useActiveLog';
1210
import { useCopyLogLink } from 'hooks/logs/useCopyLogLink';
1311
// hooks
@@ -23,7 +21,6 @@ import {
2321
useMemo,
2422
useState,
2523
} from 'react';
26-
import { FORBID_DOM_PURIFY_TAGS } from 'utils/app';
2724

2825
import LogLinesActionButtons from '../LogLinesActionButtons/LogLinesActionButtons';
2926
import LogStateIndicator from '../LogStateIndicator/LogStateIndicator';
@@ -32,8 +29,6 @@ import { getLogIndicatorType } from '../LogStateIndicator/utils';
3229
import { RawLogContent, RawLogViewContainer } from './styles';
3330
import { RawLogViewProps } from './types';
3431

35-
const convert = new Convert();
36-
3732
function RawLogView({
3833
isActiveLog,
3934
isReadOnly,
@@ -176,11 +171,7 @@ function RawLogView({
176171

177172
const html = useMemo(
178173
() => ({
179-
__html: convert.toHtml(
180-
dompurify.sanitize(unescapeString(escapeHtml(text)), {
181-
FORBID_TAGS: [...FORBID_DOM_PURIFY_TAGS],
182-
}),
183-
),
174+
__html: getSanitizedLogBody(text, { shouldEscapeHtml: true }),
184175
}),
185176
[text],
186177
);

frontend/src/components/Logs/TableView/useTableView.tsx

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,14 @@
11
import './useTableView.styles.scss';
22

3-
import Convert from 'ansi-to-html';
43
import { Typography } from 'antd';
54
import { ColumnsType } from 'antd/es/table';
65
import cx from 'classnames';
76
import { DATE_TIME_FORMATS } from 'constants/dateTimeFormats';
8-
import { unescapeString } from 'container/LogDetailedView/utils';
9-
import dompurify from 'dompurify';
7+
import { getSanitizedLogBody } from 'container/LogDetailedView/utils';
108
import { useIsDarkMode } from 'hooks/useDarkMode';
119
import { FlatLogData } from 'lib/logs/flatLogData';
1210
import { useTimezone } from 'providers/Timezone';
1311
import { useMemo } from 'react';
14-
import { FORBID_DOM_PURIFY_TAGS } from 'utils/app';
1512

1613
import LogStateIndicator from '../LogStateIndicator/LogStateIndicator';
1714
import { getLogIndicatorTypeForTable } from '../LogStateIndicator/utils';
@@ -27,8 +24,6 @@ import {
2724
UseTableViewResult,
2825
} from './types';
2926

30-
const convert = new Convert();
31-
3227
export const useTableView = (props: UseTableViewProps): UseTableViewResult => {
3328
const {
3429
logs,
@@ -149,11 +144,7 @@ export const useTableView = (props: UseTableViewProps): UseTableViewResult => {
149144
children: (
150145
<TableBodyContent
151146
dangerouslySetInnerHTML={{
152-
__html: convert.toHtml(
153-
dompurify.sanitize(unescapeString(field as string), {
154-
FORBID_TAGS: [...FORBID_DOM_PURIFY_TAGS],
155-
}),
156-
),
147+
__html: getSanitizedLogBody(field as string),
157148
}}
158149
fontSize={fontSize}
159150
linesPerRow={linesPerRow}

frontend/src/container/LogDetailedView/TableView/TableViewActions.tsx

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
import './TableViewActions.styles.scss';
33

44
import { Color } from '@signozhq/design-tokens';
5-
import Convert from 'ansi-to-html';
65
import { Button, Popover, Spin, Tooltip, Tree } from 'antd';
76
import GroupByIcon from 'assets/CustomIcons/GroupByIcon';
87
import cx from 'classnames';
@@ -12,22 +11,19 @@ import { OPERATORS } from 'constants/queryBuilder';
1211
import ROUTES from 'constants/routes';
1312
import { RESTRICTED_SELECTED_FIELDS } from 'container/LogsFilters/config';
1413
import { MetricsType } from 'container/MetricsApplication/constant';
15-
import dompurify from 'dompurify';
1614
import { ArrowDownToDot, ArrowUpFromDot, Ellipsis } from 'lucide-react';
1715
import { useTimezone } from 'providers/Timezone';
1816
import React, { useCallback, useMemo, useState } from 'react';
1917
import { useLocation } from 'react-router-dom';
2018
import { DataTypes } from 'types/api/queryBuilder/queryAutocompleteResponse';
21-
import { FORBID_DOM_PURIFY_TAGS } from 'utils/app';
2219

2320
import { DataType } from '../TableView';
2421
import {
25-
escapeHtml,
2622
filterKeyForField,
2723
getFieldAttributes,
24+
getSanitizedLogBody,
2825
parseFieldValue,
2926
removeEscapeCharacters,
30-
unescapeString,
3127
} from '../utils';
3228
import useAsyncJSONProcessing from './useAsyncJSONProcessing';
3329

@@ -51,8 +47,6 @@ interface ITableViewActionsProps {
5147
) => () => void;
5248
}
5349

54-
const convert = new Convert();
55-
5650
// Memoized Tree Component
5751
const MemoizedTree = React.memo<{ treeData: any[] }>(({ treeData }) => (
5852
<Tree
@@ -146,11 +140,7 @@ export default function TableViewActions(
146140
if (record.field !== 'body') return { __html: '' };
147141

148142
return {
149-
__html: convert.toHtml(
150-
dompurify.sanitize(unescapeString(escapeHtml(record.value)), {
151-
FORBID_TAGS: [...FORBID_DOM_PURIFY_TAGS],
152-
}),
153-
),
143+
__html: getSanitizedLogBody(record.value, { shouldEscapeHtml: true }),
154144
};
155145
}, [record.field, record.value]);
156146

frontend/src/container/LogDetailedView/TableView/useAsyncJSONProcessing.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import { useEffect, useRef, useState } from 'react';
44

55
import { jsonToDataNodes, recursiveParseJSON } from '../utils';
66

7+
const MAX_BODY_BYTES = 100 * 1024; // 100 KB
8+
79
// Hook for async JSON processing
810
const useAsyncJSONProcessing = (
911
value: string,
@@ -31,6 +33,12 @@ const useAsyncJSONProcessing = (
3133
return (): void => {};
3234
}
3335

36+
// Avoid processing if the json is too large
37+
const byteSize = new Blob([value]).size;
38+
if (byteSize > MAX_BODY_BYTES) {
39+
return (): void => {};
40+
}
41+
3442
processingRef.current = true;
3543
setJsonState({ isLoading: true, treeData: null, error: null });
3644

0 commit comments

Comments
 (0)