fix(housekeeping): address people moderation review

This commit is contained in:
Simo committed 2026-08-29 23:53:38 +02:00
1 parent 29fe22297b
commit 3fa1119f5a
20 files changed
+2000 -777

No files matched your search

@@ -138,10 +138,20 @@ const approvedRuntimeImports = new Map<string, ReadonlySet<string>>([
"src/lib/auth",
"src/lib/auth/password",
"src/lib/db",
"src/features/housekeeping/domains/people/services/moderation-mutations",
"src/features/housekeeping/domains/people/services/support-mutations",
"drizzle-orm",
"mysql2",
]),
],
[
"src/features/housekeeping/domains/people/services/moderation-mutations.ts",
new Set(["src/lib/db", "drizzle-orm"]),
],
[
"src/features/housekeeping/domains/people/services/support-mutations.ts",
new Set(["src/lib/db", "drizzle-orm"]),
],
[
"src/features/housekeeping/domains/people/manifest.ts",
new Set([
@@ -170,7 +180,15 @@ const approvedRuntimeImports = new Map<string, ReadonlySet<string>>([
"src/features/housekeeping/domains/people/widgets.ts",
new Set([
"src/features/housekeeping/domains/people/models",
"src/features/housekeeping/domains/people/queries/support",
"src/features/housekeeping/domains/people/widgets-production",
]),
],
[
"src/features/housekeeping/domains/people/widgets-production.ts",
new Set([
"src/features/housekeeping/domains/people/widgets",
"src/lib/db",
"drizzle-orm",
]),
],
[
@@ -0,0 +1,70 @@
const HOUSEKEEPING_ORIGIN = "https://housekeeping.invalid";
function containsControlCharacter(value: string): boolean {
return Array.from(value).some((character) => {
const code = character.codePointAt(0) ?? 0;
return code < 32 || code === 127;
});
}
function decodedVariants(value: string): readonly string[] | null {
const variants = [value];
for (let pass = 0; pass < 3; pass += 1) {
let decoded: string;
try {
decoded = decodeURIComponent(variants.at(-1) ?? "");
} catch {
return null;
}
if (decoded === variants.at(-1)) break;
variants.push(decoded);
}
return variants;
}
function containsDotSegment(path: string): boolean {
return path.split("/").some((segment) => segment === "." || segment === "..");
}
export function isSafeHousekeepingHref(href: string): boolean {
if (
href.length === 0 ||
!href.startsWith("/") ||
href.startsWith("//") ||
containsControlCharacter(href) ||
href.includes("\\")
) {
return false;
}
const variants = decodedVariants(href);
if (
variants === null ||
variants.some(
(value) => containsControlCharacter(value) || value.includes("\\"),
)
) {
return false;
}
const rawPath = href.split(/[?#]/u, 1)[0] ?? "";
const pathVariants = decodedVariants(rawPath);
if (
pathVariants === null ||
pathVariants.some((path) => containsDotSegment(path))
) {
return false;
}
let normalized: URL;
try {
normalized = new URL(href, HOUSEKEEPING_ORIGIN);
} catch {
return false;
}
return (
normalized.origin === HOUSEKEEPING_ORIGIN &&
(normalized.pathname === "/ase" ||
normalized.pathname.startsWith("/ase/"))
);
}