Lemmy has SSRF and internal image disclosure in post link metadata via unvalidated og:image
Date: 2026-04
Affected: rust/lemmy_api_common
Attack vector: ssrf
Category: vulnerability-disclosure
Severity: Medium
CVE: CVE-2026-42181
CWE: CWE-918
CVSS: 6.5 (CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N)

### Summary Lemmy fetches metadata for user-supplied post URLs and, under the default `StoreLinkPreviews` image mode, downloads the preview image through local pict-rs. While the top-level page URL is checked against internal IP ranges, the extracted `og:image` URL is not subject to the same restriction. As a result, an authenticated low-privileged user can submit an attacker-controlled public page whose Open Graph image points to an internal image endpoint. Lemmy will fetch that internal image server-side and store a local thumbnail that can then be served back to users. ### Details The metadata fetch logic applies an internal-address check only to the initial post URL. After HTML parsing, `extract_opengraph_data()` accepts absolute `og:image` values and returns them as-is. Later, `generate_post_link_metadata()` passes that second-hop image URL into `generate_pictrs_thumbnail()`, which instructs local pict-rs to fetch it through `image/download?url=...`. This creates a two-stage source-to-sink chain where the first URL is constrained, but the security boundary is bypassed through an unvalidated secondary resource. Core vulnerable code path: ```rust // crates/api_common/src/request.rs let metadata = match &post.url { Some(url) => fetch_link_metadata(url, &context, false).await.unwrap_or_default(), _ => Default::default(), }; ``` ```rust // crates/api_common/src/request.rs let og_image = page .opengraph .images .first() .and_then(|ogo| url.join(&ogo.url).ok()


Mitigations:

Architectural layers (MAESTRO):