fix(api,frontend): isolate active share files and allowlist link schemes

This commit is contained in:
hh committed 2026-08-29 12:52:54 +02:00
1 parent 0399145791
commit c832513e5c
10 files changed
+75 -16

No files matched your search

+4 -9
View File
@@ -1,4 +1,5 @@
import type { EntityView } from "$lib/api/types";
import { safeHref } from "$lib/format/url";
export interface TextNode {
kind: "text";
@@ -61,12 +62,6 @@ export function buildEntityTree(
return buildNodes(text, sorted, 0, text.length);
}
const PROTOCOL_RE = /^[a-z]+:/i;
function ensureProtocol(url: string): string {
return PROTOCOL_RE.test(url) ? url : `https://${url}`;
}
export function nodeText(node: EntityTreeNode): string {
if (node.kind === "text") {
return node.text;
@@ -74,10 +69,10 @@ export function nodeText(node: EntityTreeNode): string {
return node.children.map(nodeText).join("");
}
export function linkHref(node: EntityNode): string {
export function linkHref(node: EntityNode): string | undefined {
const { entity } = node;
if (entity.type === "text_link" && entity.url) {
return ensureProtocol(entity.url);
return safeHref(entity.url);
}
if (entity.type === "email") {
return `mailto:${nodeText(node)}`;
@@ -85,7 +80,7 @@ export function linkHref(node: EntityNode): string {
if (entity.type === "phone_number") {
return `tel:${nodeText(node)}`;
}
return ensureProtocol(nodeText(node));
return safeHref(nodeText(node));
}
const EMOJI_RE = /\p{Extended_Pictographic}/u;
+14
View File
@@ -0,0 +1,14 @@
const SCHEME_RE = /^([a-z][a-z0-9+.-]*):/i;
const SAFE_SCHEMES = new Set(["http", "https", "tg", "ton", "mailto", "tel"]);
export function safeHref(url: string | null | undefined): string | undefined {
if (!url) {
return;
}
const trimmed = url.trim();
const scheme = SCHEME_RE.exec(trimmed)?.[1].toLowerCase();
if (scheme === undefined) {
return `https://${trimmed}`;
}
return SAFE_SCHEMES.has(scheme) ? trimmed : undefined;
}