fix: security hardening across platform
- Disable open /api/auth/register endpoint (gateway) - Require gateway session auth on Immich and Karakeep hooks proxies - Replace SHA-256 with bcrypt in fitness service (auth + seed) - Remove hardcoded Telegram user IDs from fitness seed - Add Secure flag to session cookie - Add domain allowlist and content-type validation to image proxy - Strengthen .gitignore (env variants, runtime data, test artifacts)
This commit is contained in:
@@ -8,8 +8,26 @@ const karakeepUrl = env.KARAKEEP_URL || '';
|
||||
const karakeepApiKey = env.KARAKEEP_API_KEY || '';
|
||||
|
||||
export const handle: Handle = async ({ event, resolve }) => {
|
||||
async function isAuthenticated(request: Request): Promise<boolean> {
|
||||
const cookie = request.headers.get('cookie') || '';
|
||||
if (!cookie.includes('platform_session=')) return false;
|
||||
try {
|
||||
const res = await fetch(`${gatewayUrl}/api/auth/me`, { headers: { cookie } });
|
||||
if (!res.ok) return false;
|
||||
const data = await res.json();
|
||||
return data.authenticated === true;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// ── Immich API proxy (shared across all pages) ──
|
||||
if (event.url.pathname.startsWith('/api/immich/') && immichUrl && immichApiKey) {
|
||||
if (!await isAuthenticated(event.request)) {
|
||||
return new Response(JSON.stringify({ error: 'Unauthorized' }), {
|
||||
status: 401, headers: { 'Content-Type': 'application/json' }
|
||||
});
|
||||
}
|
||||
const immichPath = event.url.pathname.replace('/api/immich', '/api');
|
||||
|
||||
// Thumbnail/original image proxy — cache-friendly binary response
|
||||
@@ -78,6 +96,11 @@ export const handle: Handle = async ({ event, resolve }) => {
|
||||
|
||||
// ── Karakeep API proxy (server-to-server) ──
|
||||
if (event.url.pathname.startsWith('/api/karakeep/') && karakeepUrl && karakeepApiKey) {
|
||||
if (!await isAuthenticated(event.request)) {
|
||||
return new Response(JSON.stringify({ error: 'Unauthorized' }), {
|
||||
status: 401, headers: { 'Content-Type': 'application/json' }
|
||||
});
|
||||
}
|
||||
const action = event.url.pathname.split('/').pop(); // 'save' or 'delete'
|
||||
try {
|
||||
const body = await event.request.json();
|
||||
@@ -125,6 +148,9 @@ export const handle: Handle = async ({ event, resolve }) => {
|
||||
|
||||
// Legacy trips-specific Immich thumbnail (keep for backward compat)
|
||||
if (event.url.pathname.startsWith('/api/trips/immich/thumb/') && immichUrl && immichApiKey) {
|
||||
if (!await isAuthenticated(event.request)) {
|
||||
return new Response('', { status: 401 });
|
||||
}
|
||||
const assetId = event.url.pathname.split('/').pop();
|
||||
try {
|
||||
const response = await fetch(`${immichUrl}/api/assets/${assetId}/thumbnail`, {
|
||||
|
||||
Reference in New Issue
Block a user