Fix code scanning and dependabot security alerts

Code scanning fixes (14 alerts):
- Fix XSS in OG image route by validating request origin against allowlist
- Fix incomplete URL sanitization in blog layout using exact hostname matching
- Bind port-check socket to 127.0.0.1 instead of 0.0.0.0
- Add explicit permissions to 7 GitHub Actions workflows

Dependabot fixes:
- Update @isaacs/brace-expansion 5.0.0 -> 5.0.1 (CVE-2026-25547)
- Update bytes 1.10.1 -> 1.11.1 (CVE-2026-25541)
- Update time 0.3.41 -> 0.3.47 (CVE-2026-25727)
- Update cryptography 45.0.7 -> 46.0.5 (CVE-2026-26007)
- Update python-multipart 0.0.20 -> 0.0.22 (CVE-2026-24486)
- Update urllib3 2.6.2 -> 2.6.3 in test lockfiles (CVE-2026-21441)
- Update Werkzeug 3.1.4 -> 3.1.5 (CVE-2026-21860)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Adil Hafeez 2026-02-14 04:29:08 +00:00
parent 38646fdac2
commit ce5a221b11
16 changed files with 6292 additions and 1978 deletions

View file

@ -4,6 +4,28 @@ import { client, urlFor } from "@/lib/sanity";
export const runtime = "edge";
const ALLOWED_HOSTS = new Set([
"archgw-tau.vercel.app",
"plano.katanemo.com",
"localhost",
]);
function getSafeBaseUrl(requestOrigin: string): string {
if (process.env.NEXT_PUBLIC_APP_URL) {
return process.env.NEXT_PUBLIC_APP_URL;
}
if (process.env.VERCEL_URL) {
return `https://${process.env.VERCEL_URL}`;
}
try {
const parsed = new URL(requestOrigin);
if (ALLOWED_HOSTS.has(parsed.hostname)) {
return parsed.origin;
}
} catch {}
return "http://localhost:3000";
}
// Font loading function that uses the request origin
function loadFont(fileName: string, baseUrl: string) {
return fetch(new URL(`/fonts/${fileName}`, baseUrl)).then((res) => {
@ -55,12 +77,8 @@ export async function GET(
{ params }: { params: Promise<{ slug: string }> },
) {
try {
// Get base URL for font loading - use request origin in production
const fontBaseUrl =
process.env.NEXT_PUBLIC_APP_URL ||
(process.env.VERCEL_URL
? `https://${process.env.VERCEL_URL}`
: request.nextUrl.origin);
// Get base URL for font loading - use validated origin
const fontBaseUrl = getSafeBaseUrl(request.nextUrl.origin);
// Load fonts with error handling
let fontData;
@ -116,11 +134,7 @@ export async function GET(
}
// Use logo PNG
const baseUrl =
process.env.NEXT_PUBLIC_APP_URL ||
(process.env.VERCEL_URL
? `https://${process.env.VERCEL_URL}`
: request.nextUrl.origin);
const baseUrl = getSafeBaseUrl(request.nextUrl.origin);
const logoUrl = `${baseUrl}/Logomark.png`;
return new ImageResponse(

View file

@ -51,20 +51,25 @@ export async function generateMetadata({
let baseUrl = "http://localhost:3000";
if (process.env.NEXT_PUBLIC_APP_URL) {
const url = process.env.NEXT_PUBLIC_APP_URL;
if (
url.includes("archgw-tau.vercel.app") ||
url.includes("plano.katanemo.com") ||
url.includes("localhost:3000")
) {
baseUrl = url;
try {
const parsed = new URL(process.env.NEXT_PUBLIC_APP_URL);
const allowedHosts = new Set([
"archgw-tau.vercel.app",
"plano.katanemo.com",
"localhost",
]);
if (allowedHosts.has(parsed.hostname)) {
baseUrl = parsed.origin;
}
} catch {
// Invalid URL, keep default
}
} else if (process.env.VERCEL_URL) {
const hostname = process.env.VERCEL_URL;
// VERCEL_URL is just the hostname, not the full URL
if (hostname === "archgw-tau.vercel.app") {
baseUrl = `https://${hostname}`;
} else if (hostname === "plano.katanemo.com") {
if (
hostname === "archgw-tau.vercel.app" ||
hostname === "plano.katanemo.com"
) {
baseUrl = `https://${hostname}`;
}
}