diff --git a/.jules/sentinel.md b/.jules/sentinel.md new file mode 100644 index 00000000..54c088f4 --- /dev/null +++ b/.jules/sentinel.md @@ -0,0 +1,4 @@ +## 2024-05-18 - Sanitize Third-Party Error Responses +**Vulnerability:** The API upload endpoint was exposing detailed internal configuration state (e.g. missing Cloudinary credentials) and raw third-party error objects (`cloudinaryError`) directly to clients in HTTP 500 responses. +**Learning:** Developers often pass full error objects from third-party services (like Cloudinary, AWS, etc) down to the client for debugging, inadvertently leaking internal architecture details and potentially sensitive configurations. +**Prevention:** Always fail securely by catching exceptions, logging the detailed error object strictly server-side, and returning a generic, safe error message to the API consumer. diff --git a/src/app/api/upload/route.ts b/src/app/api/upload/route.ts index 1664e115..84197dd2 100644 --- a/src/app/api/upload/route.ts +++ b/src/app/api/upload/route.ts @@ -6,13 +6,15 @@ export async function POST(request: NextRequest) { try { // Verify Cloudinary configuration if (!process.env.CLOUDINARY_CLOUD_NAME || !process.env.CLOUDINARY_API_KEY || !process.env.CLOUDINARY_API_SECRET) { + // 🛡️ SECURITY: Log the detailed missing config server-side but do not expose + // internal service requirements (like Cloudinary) to the client. console.error('Missing Cloudinary credentials:', { cloud_name: !!process.env.CLOUDINARY_CLOUD_NAME, api_key: !!process.env.CLOUDINARY_API_KEY, api_secret: !!process.env.CLOUDINARY_API_SECRET }); return NextResponse.json( - { error: 'Cloudinary is not configured. Please set environment variables.' }, + { error: 'Image upload service configuration error.' }, { status: 500 } ); } @@ -60,18 +62,16 @@ export async function POST(request: NextRequest) { } catch (error: any) { console.error('Upload error:', error); - // Return detailed error message - const errorMessage = error?.message || error?.error?.message || 'Failed to upload image'; - const errorDetails = { - error: errorMessage, + // 🛡️ SECURITY: Log detailed errors (like 3rd party API objects) server-side + // and fail securely by providing only a generic error to the client. + console.error('Full error details:', { + message: error?.message || error?.error?.message || 'Failed to upload image', details: error?.http_code ? `HTTP ${error.http_code}` : undefined, cloudinaryError: error?.error || undefined - }; - - console.error('Full error details:', errorDetails); + }); return NextResponse.json( - errorDetails, + { error: 'An error occurred during image upload.' }, { status: 500 } ); }