π¨ Problem Statement
VidyaSetu supports a Notes upload and extraction workflow using Cloudinary. The current upload implementation in src/ sends files directly to Cloudinary without validating:
- File type β non-PDF files (images, executables, ZIP archives) can be uploaded and will fail the PDF extraction step silently
- File size β there is no documented maximum file size; large files (100MB+) can exhaust Cloudinary free-tier storage and cause slow uploads that time out
- File count per user β no limit on how many notes a single user can upload, enabling storage abuse
Current Impact
- A student uploading a
.jpg file as notes gets no immediate error β the extraction pipeline fails silently later
- Storage costs scale unpredictably with no per-user cap
- The Cloudinary free tier (25GB storage, 25GB bandwidth/month) can be exhausted by a small number of bad uploads
Proposed Fix
In the upload API route (src/app/api/notes/upload/route.ts or equivalent):
const ALLOWED_MIME_TYPES = ['application/pdf'];
const MAX_FILE_SIZE_MB = 10;
const MAX_FILE_SIZE_BYTES = MAX_FILE_SIZE_MB * 1024 * 1024;
export async function POST(req: Request) {
const formData = await req.formData();
const file = formData.get('file') as File | null;
if (!file) {
return Response.json({ error: 'No file provided' }, { status: 400 });
}
// Validate MIME type
if (!ALLOWED_MIME_TYPES.includes(file.type)) {
return Response.json(
{ error: `Invalid file type: ${file.type}. Only PDF files are accepted.` },
{ status: 415 }
);
}
// Validate file size
if (file.size > MAX_FILE_SIZE_BYTES) {
return Response.json(
{ error: `File too large: ${(file.size / 1024 / 1024).toFixed(1)}MB. Maximum allowed: ${MAX_FILE_SIZE_MB}MB.` },
{ status: 413 }
);
}
// Proceed with Cloudinary upload...
}
Also validate MIME type from magic bytes (not just the Content-Type header, which can be spoofed):
import { fileTypeFromBuffer } from 'file-type';
const buffer = Buffer.from(await file.arrayBuffer());
const detected = await fileTypeFromBuffer(buffer);
if (!detected || detected.mime !== 'application/pdf') {
return Response.json({ error: 'File content does not match a valid PDF.' }, { status: 415 });
}
Add file-type to package.json:
Files to Modify
| File |
Change |
src/app/api/notes/upload/route.ts |
Add MIME type + magic byte + size validation |
package.json |
Add file-type dependency |
src/ (upload UI component) |
Show client-side error for wrong file type before upload |
π Impact
Without validation, any file can be uploaded to the shared Cloudinary account. A single user can upload 50 Γ 100MB files and exhaust the storage quota for all VidyaSetu users. The fix is self-contained to the upload route and prevents both the abuse vector and the silent pipeline failure for non-PDF files.
Suggested labels: bug, security, backend, gssoc:level2
I would like to work on this. Could you please assign it to me?
π¨ Problem Statement
VidyaSetu supports a Notes upload and extraction workflow using Cloudinary. The current upload implementation in
src/sends files directly to Cloudinary without validating:Current Impact
.jpgfile as notes gets no immediate error β the extraction pipeline fails silently laterProposed Fix
In the upload API route (
src/app/api/notes/upload/route.tsor equivalent):Also validate MIME type from magic bytes (not just the
Content-Typeheader, which can be spoofed):Add
file-typetopackage.json:Files to Modify
src/app/api/notes/upload/route.tspackage.jsonfile-typedependencysrc/(upload UI component)π Impact
Without validation, any file can be uploaded to the shared Cloudinary account. A single user can upload 50 Γ 100MB files and exhaust the storage quota for all VidyaSetu users. The fix is self-contained to the upload route and prevents both the abuse vector and the silent pipeline failure for non-PDF files.
Suggested labels:
bug,security,backend,gssoc:level2I would like to work on this. Could you please assign it to me?