Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .jules/sentinel.md
Original file line number Diff line number Diff line change
@@ -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.
18 changes: 9 additions & 9 deletions src/app/api/upload/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 }
);
}
Expand Down Expand Up @@ -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 }
);
}
Expand Down