Files
SocialPub/tools/pasture/appsettings.Pasture.json
T
thepraandClaude Opus 5.5 e4f9d0b61e An image is checked before it is decoded
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
2026-10-07 10:48:44 +02:00

38 lines
1.3 KiB
JSON

{
"MongoSettings": {
"Database": "PrivaPub",
"LogsDatabase": "logs",
"ConnectionString": "mongodb://mongo:27017"
},
"AppConfiguration": {
"Version": "0.0.0",
"MaxAllowedUploadFiles": 3,
"MaxAllowedFileSize": 2097152,
"SupportedLanguages": [ "en" ],
"BackendBaseAddress": "https://privapub.test",
"FrontendBaseAddress": "https://privapub.test",
"HashingOptions": { "Iterations": 10101 },
"Jwt": {
"Key": "pasture-only-key-not-a-secret-pasture-only-key-not-a-secret-0123456789",
"Issuer": "http://privapub.test",
"Audience": "http://privapub.test",
"HoursTimeout": 24
}
},
"Federation": {
"AllowPrivateNetworks": true,
"AllowPlainHttp": true,
"AcceptAnyCertificate": true,
"Relays": [ "https://relay.test/actor", "https://aoderelay.test/actor" ]
},
"Media": { "Root": "/tmp/privapub-media" },
"RateLimits": { "AccountsPerMinute": 1000, "UploadsBurst": 1000, "UploadsPerMinute": 1000 },
"Registrations": { "Mode": "Open" },
"Statistics": { "Geo": { "AutoUpdate": false } },
"Kestrel": { "Endpoints": { "Http": { "Url": "http://0.0.0.0:80", "Protocols": "Http1AndHttp2" } } },
"Serilog": {
"MinimumLevel": { "Default": "Information", "Override": { "Microsoft": "Warning", "System": "Warning" } },
"WriteTo": [ { "Name": "Console" } ]
}
}