Skip to content

Commit f799a04

Browse files
committed
fix: allow svg in image-proxy
1 parent d2393dc commit f799a04

1 file changed

Lines changed: 41 additions & 121 deletions

File tree

server/api/registry/image-proxy/index.get.ts

Lines changed: 41 additions & 121 deletions
Original file line numberDiff line numberDiff line change
@@ -58,49 +58,27 @@ export default defineEventHandler(async event => {
5858
// Verify HMAC signature to ensure this URL was generated server-side
5959
const { imageProxySecret } = useRuntimeConfig()
6060
if (!imageProxySecret || !verifyImageUrl(url, sig, imageProxySecret)) {
61-
return {
62-
place: 'sig',
63-
url,
64-
sig,
65-
reqUrl: event.node.req.url,
66-
reqOrigUrl: event.node.req.originalUrl,
67-
imageProxySecret,
68-
}
69-
// throw createError({
70-
// statusCode: 403,
71-
// message: 'Invalid signature.',
72-
// })
61+
throw createError({
62+
statusCode: 403,
63+
message: 'Invalid signature.',
64+
})
7365
}
7466

7567
// Validate URL syntactically
7668
if (!isAllowedImageUrl(url)) {
77-
return {
78-
place: 'isAllowedImageUrl',
79-
url,
80-
sig,
81-
reqUrl: event.node.req.url,
82-
reqOrigUrl: event.node.req.originalUrl,
83-
}
84-
// throw createError({
85-
// statusCode: 400,
86-
// message: 'Invalid or disallowed image URL.',
87-
// })
69+
throw createError({
70+
statusCode: 400,
71+
message: 'Invalid or disallowed image URL.',
72+
})
8873
}
8974

9075
// Resolve hostname via DNS and validate the resolved IP is not private.
9176
// This prevents DNS rebinding attacks where a hostname resolves to a private IP.
9277
if (!(await resolveAndValidateHost(url))) {
93-
return {
94-
place: 'resolveAndValidateHost',
95-
url,
96-
sig,
97-
reqUrl: event.node.req.url,
98-
reqOrigUrl: event.node.req.originalUrl,
99-
}
100-
// throw createError({
101-
// statusCode: 400,
102-
// message: 'Invalid or disallowed image URL.',
103-
// })
78+
throw createError({
79+
statusCode: 400,
80+
message: 'Invalid or disallowed image URL.',
81+
})
10482
}
10583

10684
try {
@@ -134,31 +112,17 @@ export default defineEventHandler(async event => {
134112

135113
// Validate the redirect target before following it
136114
if (!isAllowedImageUrl(redirectUrl)) {
137-
return {
138-
place: 'isAllowedImageUrl 2',
139-
url,
140-
sig,
141-
reqUrl: event.node.req.url,
142-
reqOrigUrl: event.node.req.originalUrl,
143-
}
144-
// throw createError({
145-
// statusCode: 400,
146-
// message: 'Redirect to disallowed URL.',
147-
// })
115+
throw createError({
116+
statusCode: 400,
117+
message: 'Redirect to disallowed URL.',
118+
})
148119
}
149120

150121
if (!(await resolveAndValidateHost(redirectUrl))) {
151-
return {
152-
place: 'resolveAndValidateHost 2',
153-
url,
154-
sig,
155-
reqUrl: event.node.req.url,
156-
reqOrigUrl: event.node.req.originalUrl,
157-
}
158-
// throw createError({
159-
// statusCode: 400,
160-
// message: 'Redirect to disallowed URL.',
161-
// })
122+
throw createError({
123+
statusCode: 400,
124+
message: 'Redirect to disallowed URL.',
125+
})
162126
}
163127

164128
// Consume the redirect response body to free resources
@@ -167,66 +131,38 @@ export default defineEventHandler(async event => {
167131
}
168132

169133
if (!response) {
170-
return {
171-
place: 'response',
172-
url,
173-
sig,
174-
reqUrl: event.node.req.url,
175-
reqOrigUrl: event.node.req.originalUrl,
176-
}
177-
// throw createError({
178-
// statusCode: 502,
179-
// message: 'Failed to fetch image.',
180-
// })
134+
throw createError({
135+
statusCode: 502,
136+
message: 'Failed to fetch image.',
137+
})
181138
}
182139

183140
// Check if we exhausted the redirect limit
184141
if (REDIRECT_STATUSES.has(response.status)) {
185142
await response.body?.cancel()
186-
return {
187-
place: 'response 2',
188-
url,
189-
sig,
190-
reqUrl: event.node.req.url,
191-
reqOrigUrl: event.node.req.originalUrl,
192-
}
193-
// throw createError({
194-
// statusCode: 502,
195-
// message: 'Too many redirects.',
196-
// })
143+
throw createError({
144+
statusCode: 502,
145+
message: 'Too many redirects.',
146+
})
197147
}
198148

199149
if (!response.ok) {
200150
await response.body?.cancel()
201-
return {
202-
place: 'response 3',
203-
url,
204-
sig,
205-
reqUrl: event.node.req.url,
206-
reqOrigUrl: event.node.req.originalUrl,
207-
}
208-
// throw createError({
209-
// statusCode: response.status === 404 ? 404 : 502,
210-
// message: `Failed to fetch image: ${response.status}`,
211-
// })
151+
throw createError({
152+
statusCode: response.status === 404 ? 404 : 502,
153+
message: `Failed to fetch image: ${response.status}`,
154+
})
212155
}
213156

214157
const contentType = response.headers.get('content-type') || 'application/octet-stream'
215158

216159
// Allow raster/vector image content types (we don't inject external content into DOM, so SVG is allowed too)
217160
if (!contentType.startsWith('image/')) {
218161
await response.body?.cancel()
219-
return {
220-
place: 'contentType',
221-
url,
222-
sig,
223-
reqUrl: event.node.req.url,
224-
reqOrigUrl: event.node.req.originalUrl,
225-
}
226-
// throw createError({
227-
// statusCode: 400,
228-
// message: 'URL does not point to an allowed image type.',
229-
// })
162+
throw createError({
163+
statusCode: 400,
164+
message: 'URL does not point to an allowed image type.',
165+
})
230166
}
231167

232168
// Check Content-Length header if present (may be absent or dishonest)
@@ -288,28 +224,12 @@ export default defineEventHandler(async event => {
288224
} catch (error: unknown) {
289225
// Re-throw H3 errors
290226
if (error && typeof error === 'object' && 'statusCode' in error) {
291-
return {
292-
place: 'error',
293-
url,
294-
sig,
295-
reqUrl: event.node.req.url,
296-
reqOrigUrl: event.node.req.originalUrl,
297-
error,
298-
}
299-
// throw error
227+
throw error
300228
}
301229

302-
return {
303-
place: 'error 2',
304-
url,
305-
sig,
306-
reqUrl: event.node.req.url,
307-
reqOrigUrl: event.node.req.originalUrl,
308-
error,
309-
}
310-
// throw createError({
311-
// statusCode: 502,
312-
// message: 'Failed to proxy image.',
313-
// })
230+
throw createError({
231+
statusCode: 502,
232+
message: 'Failed to proxy image.',
233+
})
314234
}
315235
})

0 commit comments

Comments
 (0)