release: WRNexusJS 0.7.0
This commit is contained in:
@@ -0,0 +1,52 @@
|
||||
import { SecurityError } from "./errors.ts";
|
||||
|
||||
const TRUSTED_HTML = Symbol("wrnexus.trusted-html");
|
||||
|
||||
export interface TrustedHtmlPolicy {
|
||||
/** Stable policy name used in diagnostics and CSP/Trusted Types integration. */
|
||||
name: string;
|
||||
/** Application-supplied, reviewed sanitizer. It must return sanitized HTML. */
|
||||
sanitize(input: string): string;
|
||||
}
|
||||
|
||||
export interface TrustedHtmlValue {
|
||||
readonly policy: string;
|
||||
readonly value: string;
|
||||
readonly [TRUSTED_HTML]: true;
|
||||
}
|
||||
|
||||
export function createTrustedHtml(input: string, policy: TrustedHtmlPolicy): TrustedHtmlValue {
|
||||
if (!policy?.name?.trim() || typeof policy.sanitize !== "function") {
|
||||
throw new SecurityError(
|
||||
"WRN-SEC-TRUSTED-HTML-POLICY",
|
||||
"Trusted HTML requires a named sanitizer policy.",
|
||||
);
|
||||
}
|
||||
const value = policy.sanitize(String(input));
|
||||
if (typeof value !== "string") {
|
||||
throw new SecurityError(
|
||||
"WRN-SEC-TRUSTED-HTML-RESULT",
|
||||
`Trusted HTML policy '${policy.name}' must return a string.`,
|
||||
);
|
||||
}
|
||||
return Object.freeze({ policy: policy.name.trim(), value, [TRUSTED_HTML]: true as const });
|
||||
}
|
||||
|
||||
export function isTrustedHtml(value: unknown): value is TrustedHtmlValue {
|
||||
return Boolean(
|
||||
value &&
|
||||
typeof value === "object" &&
|
||||
(value as Partial<TrustedHtmlValue>)[TRUSTED_HTML] === true &&
|
||||
typeof (value as Partial<TrustedHtmlValue>).value === "string",
|
||||
);
|
||||
}
|
||||
|
||||
export function unwrapTrustedHtml(value: TrustedHtmlValue): string {
|
||||
if (!isTrustedHtml(value)) {
|
||||
throw new SecurityError(
|
||||
"WRN-SEC-TRUSTED-HTML-REQUIRED",
|
||||
"Raw HTML must be produced by createTrustedHtml().",
|
||||
);
|
||||
}
|
||||
return value.value;
|
||||
}
|
||||
Reference in New Issue
Block a user