fix security issues

This commit is contained in:
Gerhard Scheikl
2026-05-09 22:19:25 +02:00
parent c45648832a
commit 3a77bed716
6 changed files with 391 additions and 36 deletions
+15 -12
View File
@@ -1,5 +1,6 @@
import db from "../../db.server";
import { STORED_LOGO_SENTINEL } from "./logoCache.constants";
import { safeFetch, SafeFetchError } from "./safeFetch.server";
const MAX_BYTES = 5 * 1024 * 1024; // 5 MB cap
const STALE_AFTER_MS = 24 * 60 * 60 * 1000; // re-fetch once a day at most
@@ -41,26 +42,28 @@ export async function getLogoDataUrl(
return toDataUrl(cached.bytes, cached.contentType);
}
let response: Response;
let response: Awaited<ReturnType<typeof safeFetch>>;
try {
response = await fetch(logoUrl);
response = await safeFetch(logoUrl, {
maxBytes: MAX_BYTES,
accept: "image/*",
});
} catch (err) {
console.warn(`Logo fetch failed for ${shopDomain}:`, err);
if (err instanceof SafeFetchError) {
console.warn(`Logo fetch refused for ${shopDomain} (${err.code}): ${err.message}`);
} else {
console.warn(`Logo fetch failed for ${shopDomain}:`, err);
}
return cached ? toDataUrl(cached.bytes, cached.contentType) : undefined;
}
if (!response.ok) {
if (response.status < 200 || response.status >= 300) {
console.warn(`Logo fetch HTTP ${response.status} for ${shopDomain}`);
return cached ? toDataUrl(cached.bytes, cached.contentType) : undefined;
}
const arrayBuf = await response.arrayBuffer();
if (arrayBuf.byteLength > MAX_BYTES) {
console.warn(`Logo too large (${arrayBuf.byteLength} bytes) — skipping cache.`);
return undefined;
}
const bytes = Buffer.from(arrayBuf);
const contentType = response.headers.get("content-type") || guessContentType(logoUrl);
const etag = response.headers.get("etag") || "";
const bytes = Buffer.from(response.bytes);
const contentType = response.contentType || guessContentType(logoUrl);
const etag = "";
await db.logoCache.upsert({
where: { shopDomain },