fix: harden share bot uploads

This commit is contained in:
2026-08-16 01:13:47 +07:00 Unverified
parent c2af37efaa
commit a9f91d6a13
4 changed files with 104 additions and 8 deletions
+32 -3
View File
@@ -2,7 +2,10 @@ import { timingSafeEqual } from "node:crypto";
import { cdnUrl } from "@/lib/cdn-images";
import { ensureDiscordUser } from "@/lib/auth/discord-user";
import { getCanonicalUrl, getShareBotSecret } from "@/lib/config/server";
import { getDiscordMemberProfile } from "@/lib/discord/discord";
import {
DiscordProfileLookupError,
getDiscordSenderProfile,
} from "@/lib/discord/discord";
import { createShare } from "@/lib/share/create";
import { ShareHttpError, shareErrorResponse } from "@/lib/share/http-error";
import { enforceShareRateLimit } from "@/lib/share/rate-limit";
@@ -44,7 +47,25 @@ export async function POST(request: Request) {
windowSeconds: 60 * 60,
});
const formData = await request.formData();
let formData: FormData;
try {
formData = await request.formData();
} catch {
throw new ShareHttpError("Malformed multipart form data", 400);
}
for (const field of [
"displayName",
"avatarUrl",
"authorName",
"authorAvatarUrl",
]) {
if (formData.has(field)) {
throw new ShareHttpError(
`Profile field ${field} must not be supplied`,
400,
);
}
}
const file = formData.get("file");
const senderDiscordId = formData.get("senderDiscordId");
if (!(file instanceof File)) {
@@ -62,7 +83,15 @@ export async function POST(request: Request) {
validateOptionalImage(formData.get("image")),
]);
const description = validateShareDescription(formData.get("description"));
const profile = await getDiscordMemberProfile(senderDiscordId);
let profile;
try {
profile = await getDiscordSenderProfile(senderDiscordId);
} catch (error) {
if (error instanceof DiscordProfileLookupError) {
throw new ShareHttpError("Discord profile lookup is unavailable", 503);
}
throw error;
}
if (!profile) {
throw new ShareHttpError(
"Discord sender was not found in the configured guild",