diff --git a/backend/src/main/java/org/raddatz/familienarchiv/model/Document.java b/backend/src/main/java/org/raddatz/familienarchiv/model/Document.java index 8f1690dc..e5526294 100644 --- a/backend/src/main/java/org/raddatz/familienarchiv/model/Document.java +++ b/backend/src/main/java/org/raddatz/familienarchiv/model/Document.java @@ -6,6 +6,7 @@ import org.hibernate.annotations.CreationTimestamp; import org.hibernate.annotations.UpdateTimestamp; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; import java.net.URLEncoder; @@ -134,6 +135,14 @@ public class Document { @Builder.Default private Set trainingLabels = new HashSet<>(); + // The `?v={thumbnailGeneratedAt}` cache-buster is load-bearing: the thumbnail + // endpoint sends `Cache-Control: private, max-age=31536000, immutable` + // (DocumentController.getDocumentThumbnail). `immutable` is only safe because + // this URL changes whenever the underlying file does. Dropping the query param + // would let browsers serve a stale thumbnail for a year after the file is + // replaced, and shared caches could leak one user's thumbnail to another + // (CWE-525). + @JsonProperty("thumbnailUrl") public String getThumbnailUrl() { if (thumbnailKey == null) return null; String base = "/api/documents/" + id + "/thumbnail";