mirror of
https://github.com/infiniflow/ragflow.git
synced 2026-08-01 13:33:48 +08:00
## Summary - harden reopened advisory fixes across REST connector, invoke, document downloads, and markdown rendering - add targeted regression coverage for redirect-safe SSRF handling, invoke SSRF checks, document access control, and markdown sanitization - verify each referenced GHSA against the original GitHub advisory text and align the closed-advisory plan with the implemented remediation ## What changed - add tenant access checks to document download endpoints to avoid cross-tenant document disclosure - add per-hop SSRF validation, DNS pinning, redirect handling, and redirect limits to the REST API connector - ensure invoke requests validate and pin the resolved host and never follow redirects implicitly - keep the generic rate-limited request path wrapped, not just GET and POST helpers - sanitize markdown HTML before rendering in the highlight markdown component ## Validation - `cd web && npm test -- --runInBand src/components/highlight-markdown/__tests__/index.test.tsx` - `.venv/bin/python -m pytest -q test/unit_test/data_source/test_rest_api_connector.py` - targeted `test/testcases/test_web_api/...` unit additions were reviewed, but the suite cannot be executed end-to-end in this environment because parent `test/testcases/conftest.py` requires a local service on `127.0.0.1:9380` ## Notes - all GHSA entries referenced by the plan were checked against the original GitHub advisory text, not sampled - the closed-advisory plan document was updated locally during review, but is intentionally not included in this PR
77 lines
2.6 KiB
TypeScript
77 lines
2.6 KiB
TypeScript
import { MarkdownRemarkPlugins } from '@/constants/markdown-remark-plugins';
|
|
import classNames from 'classnames';
|
|
import DOMPurify from 'dompurify';
|
|
import Markdown from 'react-markdown';
|
|
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
|
|
import {
|
|
oneDark,
|
|
oneLight,
|
|
} from 'react-syntax-highlighter/dist/esm/styles/prism';
|
|
import rehypeKatex from 'rehype-katex';
|
|
import rehypeRaw from 'rehype-raw';
|
|
|
|
import 'katex/dist/katex.min.css'; // `rehype-katex` does not import the CSS for you
|
|
|
|
import { preprocessLaTeX } from '@/utils/chat';
|
|
import { citationMarkerReg } from '@/utils/citation-utils';
|
|
import { getDirAttribute } from '@/utils/text-direction';
|
|
import { omit } from 'lodash';
|
|
import { useIsDarkTheme } from '../theme-provider';
|
|
import styles from './index.module.less';
|
|
|
|
const HighLightMarkdown = ({
|
|
children,
|
|
}: {
|
|
className?: string;
|
|
children: string | null | undefined;
|
|
}) => {
|
|
const isDarkTheme = useIsDarkTheme();
|
|
// IMPORTANT: preprocessLaTeX() decodes </>/& back to raw HTML before
|
|
// rehypeRaw parses the markdown. Sanitizing children *before* preprocessLaTeX
|
|
// would let entity-encoded payloads bypass DOMPurify and inject HTML.
|
|
// Sanitize the *post*-processed string instead. (Coderabbit CRITICAL #3486038798)
|
|
const processed = children ? preprocessLaTeX(children) : children;
|
|
const safeChildren = processed ? DOMPurify.sanitize(processed) : processed;
|
|
const dir = children
|
|
? getDirAttribute(children.replace(citationMarkerReg, ''))
|
|
: undefined;
|
|
|
|
return (
|
|
<div dir={dir} className={classNames(styles.text)}>
|
|
<Markdown
|
|
remarkPlugins={MarkdownRemarkPlugins}
|
|
rehypePlugins={[rehypeRaw, rehypeKatex]}
|
|
components={
|
|
{
|
|
p: ({ children, ...props }: any) => (
|
|
<p {...omit(props, 'node')}>{children}</p>
|
|
),
|
|
code(props: any) {
|
|
const { children, className, ...rest } = props;
|
|
const match = /language-(\w+)/.exec(className || '');
|
|
return match ? (
|
|
<SyntaxHighlighter
|
|
{...rest}
|
|
PreTag="div"
|
|
language={match[1]}
|
|
style={isDarkTheme ? oneDark : oneLight}
|
|
>
|
|
{String(children).replace(/\n$/, '')}
|
|
</SyntaxHighlighter>
|
|
) : (
|
|
<code {...rest} className={`${className} ${styles.code}`}>
|
|
{children}
|
|
</code>
|
|
);
|
|
},
|
|
} as any
|
|
}
|
|
>
|
|
{safeChildren}
|
|
</Markdown>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default HighLightMarkdown;
|