From 24afd44409ef6341b14a501a7b7d62ad6b1075a2 Mon Sep 17 00:00:00 2001 From: austinkelsay Date: Wed, 25 Sep 2024 11:22:45 -0500 Subject: [PATCH] Security updates to image proxy --- src/pages/api/image-proxy.js | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/src/pages/api/image-proxy.js b/src/pages/api/image-proxy.js index 4f52273..5e46b46 100644 --- a/src/pages/api/image-proxy.js +++ b/src/pages/api/image-proxy.js @@ -12,14 +12,26 @@ export default async function handler(req, res) { const response = await axios({ method: 'GET', url: imageUrl, - responseType: 'stream', + responseType: 'arraybuffer', + timeout: 8000, // Set a timeout to prevent long-running requests + // limit the size of the response to 100MB + maxContentLength: 100 * 1024 * 1024, }); - // Forward the content type - res.setHeader('Content-Type', response.headers['content-type']); + // Validate content type + const contentType = response.headers['content-type']; + const allowedContentTypes = ['image/jpeg', 'image/png', 'image/gif', 'image/webp']; + if (!allowedContentTypes.includes(contentType)) { + return res.status(403).json({ error: 'Invalid content type' }); + } - // Stream the image from the external source to the client - response.data.pipe(res); + // Set security headers + res.setHeader('Content-Security-Policy', "img-src 'self'; object-src 'none'"); + res.setHeader('X-Content-Type-Options', 'nosniff'); + + // Set the content type and send the image data + res.setHeader('Content-Type', contentType); + res.send(response.data); } catch (error) { console.error('Image proxy error:', error); res.status(500).json({ error: 'Failed to fetch image' });