From 67f31800f36c30b4fdce366fe37a263c6952be03 Mon Sep 17 00:00:00 2001 From: janis steiner Date: Tue, 12 May 2026 10:05:25 +0200 Subject: [PATCH] enforce filetypes --- backend/api/index.php | 25 ++++++++++++++++++++++++- frontend/assets/js/app.js | 19 ++++++++++++++++--- frontend/index.html | 2 +- 3 files changed, 41 insertions(+), 5 deletions(-) diff --git a/backend/api/index.php b/backend/api/index.php index cf67622..eca3fc9 100644 --- a/backend/api/index.php +++ b/backend/api/index.php @@ -666,6 +666,14 @@ function handleDocuments($method, $id, $db) { function handleAttachments($method, $id, $db) { $username = $_SESSION['neptune_username'] ?? 'Unknown'; $uploadDir = '/var/www/uploads/'; + $allowedExtensions = ['pdf', 'md', 'txt', 'xlsx', 'csv', 'pptx', 'evidence']; + $allowedMimes = [ + 'application/pdf', + 'text/markdown', 'text/x-markdown', 'text/plain', + 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', + 'text/csv', 'application/csv', + 'application/vnd.openxmlformats-officedocument.presentationml.presentation', + ]; switch ($method) { case 'GET': @@ -693,7 +701,22 @@ function handleAttachments($method, $id, $db) { return; } $file = $_FILES['file']; - $ext = pathinfo($file['name'], PATHINFO_EXTENSION); + $ext = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION)); + + if (!in_array($ext, $allowedExtensions)) { + http_response_code(400); + echo json_encode(['error' => 'File type not allowed. Allowed: ' . implode(', ', $allowedExtensions)]); + return; + } + + $mime = $file['type'] ?: ''; + $mimeAllowed = empty($mime) || in_array($mime, $allowedMimes); + if (!$mimeAllowed && $ext !== 'evidence') { + http_response_code(400); + echo json_encode(['error' => 'Invalid file content']); + return; + } + $storedName = uniqid('att_', true) . '.' . $ext; $dest = $uploadDir . $storedName; diff --git a/frontend/assets/js/app.js b/frontend/assets/js/app.js index 7b35e7f..b317a91 100644 --- a/frontend/assets/js/app.js +++ b/frontend/assets/js/app.js @@ -167,11 +167,24 @@ function initApp() { document.getElementById('opacityVal').textContent = parseFloat(e.target.value).toFixed(2); }); - document.getElementById('eventFileInput').addEventListener('change', (e) => { + const ALLOWED_EXTENSIONS = ['pdf', 'md', 'txt', 'docx', 'xlsx', 'csv', 'pptx', 'evidence']; + +document.getElementById('eventFileInput').addEventListener('change', (e) => { const preview = document.getElementById('eventFilePreview'); - const files = e.target.files; + const files = Array.from(e.target.files); + const invalid = files.filter(f => { + const ext = f.name.split('.').pop().toLowerCase(); + return !ALLOWED_EXTENSIONS.includes(ext); + }); + if (invalid.length) { + preview.innerHTML = '
Invalid type(s): ' + + invalid.map(f => f.name).join(', ') + + '. Allowed: ' + ALLOWED_EXTENSIONS.join(', ') + '
'; + e.target.value = ''; + return; + } if (!files.length) { preview.innerHTML = ''; return; } - preview.innerHTML = Array.from(files).map(f => + preview.innerHTML = files.map(f => `
${esc(f.name)} (${formatFileSize(f.size)})
` ).join(''); }); diff --git a/frontend/index.html b/frontend/index.html index 0516fcd..079c1bb 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -253,7 +253,7 @@
- +