agent-ecosystem/src/renderer/utils/markdownPlugins.ts
Leigh Stillard d6ee7bc320 fix(security): simplify attributes merge to prevent future override
The previous Object.fromEntries spread would silently overwrite the
custom abbr attribute list if rehype-sanitize adds abbr to its default
schema in a future version. Simplify to a direct merge.
2026-03-24 01:25:26 +00:00

55 lines
1.8 KiB
TypeScript

/**
* Rehype plugins for markdown rendering (used with react-markdown).
*
* - rehype-raw: parse and render inline HTML in markdown
* - rehype-sanitize: strip dangerous HTML (scripts, event handlers, etc.)
* - rehype-highlight: syntax highlighting for code blocks
*
* Plugin order matters: raw parses inline HTML into hast nodes, sanitize
* removes dangerous content, then highlight adds its own safe classes.
*/
import rehypeHighlight from 'rehype-highlight';
import rehypeRaw from 'rehype-raw';
import rehypeSanitize, { defaultSchema } from 'rehype-sanitize';
import type { Options as SanitizeSchema } from 'rehype-sanitize';
import type { PluggableList } from 'unified';
/**
* Sanitization schema extending the GitHub-based default.
*
* The default already allows: details, summary, kbd, sub, sup, del, ins,
* tables, headings, code, pre, img, a, lists, etc.
*
* We extend it with additional tags Claude commonly uses in markdown output.
*/
const sanitizeSchema: SanitizeSchema = {
...defaultSchema,
tagNames: [
...(defaultSchema.tagNames ?? []),
'mark', // text highlighting
'abbr', // abbreviations
'u', // underline
'figure', // figures
'figcaption', // figure captions
],
attributes: {
...defaultSchema.attributes,
// Allow title on abbr (for tooltip definitions)
abbr: [...(defaultSchema.attributes?.['abbr'] ?? []), 'title'],
},
};
/** Full plugin chain: raw HTML → sanitize → syntax highlighting */
export const REHYPE_PLUGINS: PluggableList = [
rehypeRaw,
[rehypeSanitize, sanitizeSchema],
rehypeHighlight,
];
/** Lightweight chain: raw HTML → sanitize only (used when highlighting is disabled for large content) */
export const REHYPE_PLUGINS_NO_HIGHLIGHT: PluggableList = [
rehypeRaw,
[rehypeSanitize, sanitizeSchema],
];