Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 | 37x 37x 37x 37x 4816x 4809x | /**
* sanitizeHtml.js
*
* Shared DOMPurify wrapper for all dangerouslySetInnerHTML sinks that display
* staff-authored question content to teachers and students.
*
* Security goal: strip stored-XSS vectors (<script>, on* event handlers,
* javascript:/vbscript: URIs) while preserving:
* - Rich text formatting (bold, italic, tables, lists, images, links …)
* - Math formula spans: <span class="mfe-formula" data-latex="…">
* - Math custom element: <math-field read-only …>
* - Graph2d placeholders: <div class="graph2d-embed" data-graph2d="…">
* - MathJax inline/display text delimiters \(...\), \[...\], $$...$$ (plain
* text — survive DOMPurify unmodified)
*
* Source for allowed tag/attribute list:
* - TinyMCETextEditorReadOnly.jsx extended_valid_elements / custom_elements
* - math-formula plugin.js (MATH_CLASS = "mfe-formula", LATEX_ATTR = "data-latex")
* - tinymceGraph2dOpenUrlPlugin.js (PLACEHOLDER_CLASS = "graph2d-embed",
* DATA_ATTR = "data-graph2d")
*/
import DOMPurify from "dompurify";
// ---------------------------------------------------------------------------
// Allowed HTML tags
// ---------------------------------------------------------------------------
const ALLOWED_TAGS = [
// Structure / layout
"div",
"span",
"p",
"br",
// Headings
"h1",
"h2",
"h3",
"h4",
"h5",
"h6",
// Inline formatting
"strong",
"b",
"em",
"i",
"u",
"s",
"del",
"sub",
"sup",
"mark",
"code",
"pre",
"blockquote",
// Lists
"ul",
"ol",
"li",
// Tables
"table",
"thead",
"tbody",
"tfoot",
"tr",
"td",
"th",
"caption",
"colgroup",
"col",
// Media / links
"img",
"a",
"figure",
"figcaption",
// Interactive question UI (client-generated blanks — not staff-authored TinyMCE)
"select",
"option",
"button",
];
// ---------------------------------------------------------------------------
// Allowed attributes
// ---------------------------------------------------------------------------
const ALLOWED_ATTR = [
// Universal
"class",
"style",
"id",
"lang",
"dir",
// Links / media
"href",
"src",
"alt",
"title",
"target",
"rel",
// Image dimensions — TinyMCE's custom resize overlay (ImageResizeOverlay.jsx)
// sets both an inline style AND these attributes when a teacher resizes an
// image; without them allowlisted, DOMPurify silently dropped the resize
// and every image rendered at its natural size again.
"width",
"height",
// Tables
"colspan",
"rowspan",
"scope",
// Form controls (dropdown blanks, drag-drop clear buttons)
"value",
"selected",
"disabled",
"type",
// math-field custom element attrs
"read-only",
// data-* are enabled globally via ALLOW_DATA_ATTR below
];
// Math custom element (mathlive / math-formula plugin) — non-HTML namespace
const CUSTOM_TAGS = ["math-field"];
// ---------------------------------------------------------------------------
// DOMPurify config
// ---------------------------------------------------------------------------
const PURIFY_CONFIG = {
ALLOWED_TAGS,
ALLOWED_ATTR,
// Allow all data-* attributes (covers data-latex, data-graph2d, data-drop-index,
// data-clear-index, data-dropdown-index, data-menu-index, data-mce-selected, etc.)
ALLOW_DATA_ATTR: true,
// Keep math-field as a custom element (non-HTML namespace)
ADD_TAGS: CUSTOM_TAGS,
// Strip dangerous URI schemes from href / src / action
FORCE_BODY: true,
};
/**
* Sanitize staff-authored rich HTML for display to teachers and students.
*
* Strips: <script>, on* event handler attributes, javascript:/vbscript: URIs,
* <iframe>, <object>, <embed>, <form>, and any other tags not in the allow-list.
*
* Preserves: all formatting + math formula spans (.mfe-formula / data-latex) +
* math-field custom element + graph2d embed divs (data-graph2d) + plain-text
* MathJax delimiters (\(...\), $$...$$) + client-generated dropdown blanks
* (`<select>` / `<option>`) and menu triggers (`<button data-menu-index>`).
*
* @param {string} html - Raw HTML string from the question bank
* @returns {string} Sanitized HTML safe for dangerouslySetInnerHTML
*/
export function sanitizeRichText(html) {
if (!html || typeof html !== "string") return "";
return DOMPurify.sanitize(html, PURIFY_CONFIG);
}
|