An upload went straight to libvips: whatever loader recognised the bytes ran (an SVG sent as image/png was rasterised), nothing bounded how many pixels it would decode to (a small PNG could decode to gigabytes, three times over), a GIF was loaded frame by frame and never resized, and all of it ran inside the request with nothing limiting how many at once. A GIF was typed gifv but stayed a .gif, which a gifv player can't play; its metadata was kept; colours lost their ICC profile without being converted; HEIC was advertised but the bundled libvips can't decode it. Now: - only libvips' JPEG, PNG, GIF, WebP and HEIF loaders ever run on an upload (every other loader is blocked); - the header alone says how big an image would decode, refused above Media:MaxPixels (40 MP) or MaxFrames; - a still image is shrunk on load, turned by its orientation and brought into sRGB (thumbnail), then written without metadata, a profile picture the same way; - an animated GIF becomes a looping silent H.264 mp4 typed gifv, as on Mastodon (PostMedia.Kind keeps it a gifv), and a remote GIF is an image; - processing runs Media:Concurrency at a time, and uploads have their own rate limit per credential; - HEIC and HEIF are no longer offered. Tests: only the upload formats load, the header tells the size, an SVG posing as a PNG and an image too large are refused before decoding, an animated GIF becomes a gifv and a still one an image, HEIC isn't advertised. The media scenarios against the pasture (GoToSocial, Mastodon, Misskey, Akkoma, Pixelfed, Smithereen, Vernissage, Castopod, PeerTube) pass: 329 checks. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LsXgEaXee4GCU1hwYgPJXw
25 lines
967 B
C#
25 lines
967 B
C#
namespace PrivaPub.Models.Post
|
|
{
|
|
public class PostMedia
|
|
{
|
|
public Guid Id { get; set; } = Guid.NewGuid();
|
|
public string ContentType { get; set; }
|
|
public string Kind { get; set; }//a local upload's kind ("gifv" for a GIF made an mp4), where the type alone can't tell
|
|
public string FileName { get; set; }
|
|
public string Extension { get; set; }
|
|
public string Path { get; set; }
|
|
public string URL { get; set; }
|
|
public string RemoteURL { get; set; }
|
|
public string PreviewURL { get; set; }
|
|
public string AttachmentId { get; set; }
|
|
public string Description { get; set; }
|
|
public string Blurhash { get; set; }
|
|
public int? Width { get; set; }
|
|
public int? Height { get; set; }
|
|
public float[] Focus { get; set; }
|
|
public string RemotePreviewURL { get; set; }//the remote thumbnail (attachment icon), served through the proxy
|
|
public double? DurationSeconds { get; set; }
|
|
public bool? Sensitive { get; set; }//Misskey marks each attachment
|
|
}
|
|
}
|