- Split approve/dismiss application workflows with distinct audit logs, rate-limited guards and real error logging - Validate article status/date/id input and stop resetting publishedAt on every update - Validate guild updates (state, forum enums, non-empty name) behind rate-limited guard - Fix scheduled-article publishing (ignore NULL dates, set updatedAt, type-safe predicates) - Harden admin search API (LIKE escaping, query cap, per-user rate limit, round-robin result cap) and fix search dialog abort/res.ok/loading races - Lock down HTML sanitizer to an allowlist profile and add XSS tests - Improve mobile nav accessibility (unique id, dialog role, focus management, scroll lock, outside close) - Log swallowed server errors instead of silent catch blocks - Remove dead eslint config, drop unused dompurify deps, restore knip CI step, add Playwright config with smoke spec
53 lines
682 B
TypeScript
53 lines
682 B
TypeScript
import DOMPurify from "isomorphic-dompurify";
|
|
|
|
const ALLOWED_TAGS = [
|
|
"a",
|
|
"b",
|
|
"blockquote",
|
|
"br",
|
|
"code",
|
|
"em",
|
|
"h1",
|
|
"h2",
|
|
"h3",
|
|
"h4",
|
|
"hr",
|
|
"i",
|
|
"img",
|
|
"li",
|
|
"ol",
|
|
"p",
|
|
"pre",
|
|
"strong",
|
|
"table",
|
|
"tbody",
|
|
"td",
|
|
"th",
|
|
"thead",
|
|
"tr",
|
|
"u",
|
|
"ul",
|
|
];
|
|
|
|
const ALLOWED_ATTR = [
|
|
"href",
|
|
"src",
|
|
"alt",
|
|
"title",
|
|
"target",
|
|
"rel",
|
|
"colspan",
|
|
"rowspan",
|
|
];
|
|
|
|
export function sanitize(html: string | null | undefined): string {
|
|
if (!html) return "";
|
|
return DOMPurify.sanitize(html, {
|
|
ALLOWED_TAGS,
|
|
ALLOWED_ATTR,
|
|
ALLOW_DATA_ATTR: false,
|
|
FORBID_TAGS: ["style", "script", "svg", "math", "form", "input", "button"],
|
|
USE_PROFILES: { html: true },
|
|
});
|
|
}
|