Harden request origin checks and configure allowed hosts

This commit is contained in:
2026-10-04 17:00:02 +05:00
parent 5289c17adf
commit 04cc4f39f6
6 changed files with 319 additions and 26 deletions

View File

@@ -5,6 +5,7 @@ import { z } from "zod";
import { admin, required, user } from "./supabase";
import { datasetSchema, faces, difficulties } from "../shared/protocol";
import { mediaUrl } from "./catalog";
import { requestOrigin, verifyOrigin } from "./request-origin";
const hash = (value: string) =>
createHash("sha256").update(value).digest("hex");
const idSchema = z.string().uuid();
@@ -91,21 +92,6 @@ async function jsonBody(request: NextRequest) {
}
return JSON.parse(Buffer.concat(chunks).toString("utf8"));
}
function verifyOrigin(request: NextRequest) {
if (request.method === "GET" || request.method === "HEAD") return;
const origin = request.headers.get("origin");
const allowed = new Set([
new URL(request.url).origin,
process.env.MINEGEO_URL || "http://localhost:3000",
]);
if (origin && !allowed.has(origin)) throw new Error("Invalid request origin");
if (
!origin &&
!request.headers.get("authorization") &&
!request.headers.get("content-type")?.includes("application/json")
)
throw new Error("JSON request required");
}
export async function handle(request: NextRequest, path: string[]) {
try {
verifyOrigin(request);
@@ -537,7 +523,7 @@ export async function handle(request: NextRequest, path: string[]) {
return NextResponse.json({
deviceCode,
userCode: code,
verificationUri: `${process.env.MINEGEO_URL || new URL(request.url).origin}/pair?code=${code}`,
verificationUri: `${process.env.MINEGEO_URL ? new URL(process.env.MINEGEO_URL).origin : requestOrigin(request)}/pair?code=${code}`,
interval: 5,
});
}
@@ -622,13 +608,13 @@ export async function handle(request: NextRequest, path: string[]) {
.parse(await jsonBody(request));
if (b.decision === "reject" && !b.reason?.trim())
throw new Error("Provide a rejection reason");
const {error}=await client.rpc("publish_dataset", {
p_dataset: b.datasetId,
p_reviewer: reviewer,
p_decision: b.decision,
p_reason: b.reason ?? null,
});
if(error)throw new Error(error.message);
const { error } = await client.rpc("publish_dataset", {
p_dataset: b.datasetId,
p_reviewer: reviewer,
p_decision: b.decision,
p_reason: b.reason ?? null,
});
if (error) throw new Error(error.message);
return NextResponse.json({ ok: true });
}
}