/** * branding-sanitize — neutralises CSS injection in tenant-controlled * white-label values before they reach CSS custom properties. * * Closes two risks in the `applyBrandingToRoot` sink in `BrandingProvider`: * * SEC-002 — CSS injection via `font_stack`. A crafted value written to * `--font-stack` can carry ``, `expression(...)`, * `url(...)` or a declaration breakout. * SEC-003 — CSS injection via `logo_url` / `mark_url` / `logo_*_url` / * `favicon_url`. An unescaped value embedded in an unquoted * `url(...)` token can close the token early and inject * arbitrary CSS, or smuggle a dangerous scheme * (`javascript:`, `data:text/html`, …). * * The three white-label tables backing `branding_json_for_tenant` * (`platform_branding`, `tenant_branding`, `tenant_app_branding`) are * writable by semi-trusted platform/tenant admins, so the sanitiser runs * at the DOM-apply boundary — every write path is covered, not just the * admin UI. * * Mirrors the canonical sanitiser shipped on * business-suite-unified/src/lib/branding-sanitize.ts (BSU#485, merged * 2026-05-25) * crm7/src/lib/branding-sanitize.ts (crm7#857, open draft) * — DRY-merged into `@bsuite/theme` here so every consumer of * `` is covered with a single version bump. * * All helpers are pure and regex-free (per the BSuite No-Regex-by-Default * rule); they are exercised directly in `./branding-sanitize.test.ts`. */ /** * Validate a branding image URL (logo / mark / favicon). * * Accepts and returns: * - absolute `http(s)` URLs — parsed and normalised via the URL API * - root-relative paths (`/logo.svg`) — same-origin, no scheme to abuse * * Returns `null` for everything else — dangerous schemes, protocol-relative * `//host` forms, control characters, unparseable input, over-long input. * Callers treat `null` as "no logo" and fall back to the default. */ export declare function sanitizeBrandingUrl(raw: string | null | undefined): string | null; /** * Wrap a validated URL in a `url("...")` token, escaping `"` and `\` so the * string cannot be closed early. Always pair with {@link sanitizeBrandingUrl} * — never call this on un-validated input. Returns `null` for `null` input * so call sites can pass the result straight to a set-or-clear helper. */ export declare function toCssUrl(safeUrl: string | null | undefined): string | null; /** * Validate a CSS `font-family` value. Legitimate font stacks are * comma-separated family names (`"Inter", "Helvetica Neue", sans-serif`) * and never need braces, semicolons, parentheses, at-rules or comment * markers. The presence of any forbidden token means an injection attempt, * so the whole value is rejected (returns `null` → caller falls back to the * default font). */ export declare function sanitizeFontFamily(raw: string | null | undefined): string | null; /** * Validate a CSS `font-family` value, resolve a known alias to the face * this package actually ships, and append {@link FONT_FALLBACK_CHAIN} — for * call sites that write straight to a CSS custom property consumed as * `font-family: var(--font-x)`. Delegates the injection check to * {@link sanitizeFontFamily} — this only changes what a legitimate value * turns into on its way to the DOM, never the accept/reject decision. * Returns `null` when the input fails sanitization (caller then leaves the * theme's own default — which already carries its own fallback — in place). * * Alias resolution looks only at the FIRST (primary) entry of the stack — * the one a single-family branding picker actually submits — and, when it * matches a known alias, prepends the resolved face ahead of it (keeping * the raw name in the stack too): `Geist` → `"Geist Variable", Geist, * system-ui, sans-serif`. A value with no known alias (`Inter`, or anything * else this package has not shipped a face for) is passed through * unresolved and still gets the fallback chain, so it degrades to system * sans rather than the browser's serif default. */ export declare function sanitizeFontFamilyForCss(raw: string | null | undefined): string | null; //# sourceMappingURL=branding-sanitize.d.ts.map