Fix security warnings

This commit is contained in:
gpt-engineer-app[bot]
2025-10-20 21:43:26 +00:00
parent 6b0627054e
commit 42723015f3
7 changed files with 588 additions and 21 deletions

View File

@@ -0,0 +1,116 @@
import { serve } from "https://deno.land/std@0.168.0/http/server.ts";
import { createClient } from 'https://esm.sh/@supabase/supabase-js@2.39.3';
const corsHeaders = {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type',
};
const DOCKER_SOCKET = '/var/run/docker.sock';
serve(async (req) => {
if (req.method === 'OPTIONS') {
return new Response(null, { headers: corsHeaders });
}
try {
const authHeader = req.headers.get('Authorization');
if (!authHeader) {
throw new Error('Missing authorization header');
}
const supabase = createClient(
Deno.env.get('SUPABASE_URL') ?? '',
Deno.env.get('SUPABASE_ANON_KEY') ?? '',
{ global: { headers: { Authorization: authHeader } } }
);
const { data: { user }, error: userError } = await supabase.auth.getUser();
if (userError || !user) {
throw new Error('Unauthorized');
}
const url = new URL(req.url);
const containerId = url.searchParams.get('container');
const tail = url.searchParams.get('tail') || '100';
if (!containerId) {
throw new Error('Container ID required');
}
// Connect to Docker socket
const conn = await Deno.connect({ transport: "unix", path: DOCKER_SOCKET });
const request = `GET /containers/${containerId}/logs?stdout=true&stderr=true&tail=${tail}&follow=true HTTP/1.1\r\nHost: localhost\r\n\r\n`;
await conn.write(new TextEncoder().encode(request));
// Create a readable stream from the socket
const stream = new ReadableStream({
async start(controller) {
const decoder = new TextDecoder();
let buffer = new Uint8Array(8192);
let headerRead = false;
try {
while (true) {
const n = await conn.read(buffer);
if (n === null) break;
let data = decoder.decode(buffer.subarray(0, n));
// Skip HTTP headers on first read
if (!headerRead) {
const headerEnd = data.indexOf('\r\n\r\n');
if (headerEnd !== -1) {
data = data.substring(headerEnd + 4);
headerRead = true;
}
}
// Docker logs use a special frame format:
// [8]byte{STREAM_TYPE, 0, 0, 0, SIZE1, SIZE2, SIZE3, SIZE4}
// We'll parse and clean this
const lines = data.split('\n').filter(line => {
// Skip binary headers (first 8 bytes of each frame)
if (line.length > 8) {
return line.substring(8).trim().length > 0;
}
return false;
});
for (const line of lines) {
if (line.length > 8) {
const cleaned = line.substring(8).trim();
if (cleaned) {
controller.enqueue(new TextEncoder().encode(`data: ${cleaned}\n\n`));
}
}
}
}
} catch (error) {
console.error('Stream error:', error);
} finally {
conn.close();
controller.close();
}
}
});
return new Response(stream, {
headers: {
...corsHeaders,
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache',
'Connection': 'keep-alive',
},
});
} catch (error) {
console.error('Docker logs error:', error);
const message = error instanceof Error ? error.message : 'Unknown error';
return new Response(JSON.stringify({ error: message }), {
status: 500,
headers: { ...corsHeaders, 'Content-Type': 'application/json' },
});
}
});