felladrin / felladrin/MiniSearch
security: audit thumbnail endpoint SSRF protection
- Dominant language
- TypeScript
- Stars
- 587
- Forks
- 70
- Avg merge
- 1h 3m
- Merged PRs (30d)
- 175
Description
## Problem
The `/thumbnail` endpoint (`server/thumbnailEndpointServerHook.ts`) fetches external URLs to lazy-load image thumbnails. While it uses `server/utils/publicUrl.ts` to block private and reserved addresses, this is an active attack surface that warrants a dedicated security audit.
## Why It Matters
- **SSRF risk**: If the URL validation has gaps, an attacker could use the server to scan internal networks
- **Active attack surface**: The endpoint fetches arbitrary URLs from search results, which could be malicious
- **Rate limiting**: The endpoint should be rate-limited to prevent abuse
- **Content validation**: The endpoint should verify the fetched content is actually an image
## Current Implementation
```typescript
// server/thumbnailEndpointServerHook.ts (simplified)
const url = new URL(req.url);
const targetUrl = url.searchParams.get('url');
// Validate URL
if (!publicUrl.isPublicUrl(targetUrl)) {
return res.status(400).end('Invalid URL');
}
// Fetch thumbnail
const response = await fetch(targetUrl, { /* options */ });
```
## Audit Checklist
1. **URL validation**
- [ ] Does `publicUrl.ts` block all private IP ranges (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16)?
- [ ] Does it block link-local addresses (169.254.0.0/16)?
- [ ] Does it block the loopback range (127.0.0.0/8, ::1)?
- [ ] Does it block the cloud metadata endpoint (169.254.169.254)?
- [ ] Does it block IPv6-mapped IPv4 addresses?
- [ ] Does it block DNS rebinding attacks (validate after DNS resolution)?
2. **Request validation**
- [ ] Is the URL length limited?
- [ ] Are only HTTP/HTTPS schemes allowed?
- [ ] Are redirects followed safely (no redirect to private IP)?
3. **Response validation**
- [ ] Is the Content-Type checked to ensure it's an image?
- [ ] Is the response size limited?
- [ ] Is the timeout configured?
4. **Rate limiting**
- [ ] Is the endpoint rate-limited per IP?
- [ ] Is there a global rate limit?
## Proposed Improvements
1. **Add DNS rebinding protection**: Resolve the DNS name and validate the IP before fetching
2. **Add redirect validation**: Follow redirects but re-validate each URL
3. **Add Content-Type validation**: Only accept image/* Content-Types
4. **Add response size limit**: Reject responses larger than a reasonable size (e.g., 5MB)
5. **Add detailed logging**: Log all thumbnail requests for audit purposes
## Files to Audit
- `server/thumbnailEndpointServerHook.ts`
- `server/utils/publicUrl.ts`
## Acceptance Criteria
- All items in the audit checklist are verified or fixed
- DNS rebinding attacks are prevented
- Redirects are validated
- Content-Type and size are validated
- Rate limiting is in place
- A security review comment is added to the endpoint code
Contributor guide
Research direction
Read server/thumbnailEndpointServerHook.ts and server/utils/publicUrl.ts first, then trace the thumbnail request, URL validation, fetch, redirects, and response handling against the audit checklist. Done means every checklist item is verified or fixed, the stated protections are covered, rate limiting is addressed, and a security review comment is added to the endpoint code.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- api, backend, security
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 30/100