Repository navigation
Upgrading from 1.3.0
No format or env var was removed, and no database migration runs. Every deployment should update:
- From 1.1.0 to 1.3.0, GIFs and palette PNGs came back in one colour, and portrait photos on their side.
- A request's upload and result are now removed however the request ends.
- The image moves past dnspython CVE-2026-114605 (high) and Mako CVE-2026-102991, which scanners report for 1.3.0. Neither is reachable in FileMorph.
See the Fixed and Security entries in the changelog.
Five DOMPurify advisories in the Swagger UI bundle on /docs stay accepted, as in 1.3.0, because Swagger UI does not use the options they need. They are reviewed again on 2026-11-02 (see docs/security-overview.md).
Check before pulling:
- Pinned to
1.3or1.3.0(or their-officevariants):- There is no 1.3.1, so these image tags stay on 1.3.0 without these fixes.
- Move to
1.4(or1.4.0). - If you can't move to 1.4,
SECURITY.mddescribes how to request a backport onto 1.3.
- New:
- Inserting pages into a PDF:
POST /api/v1/pdf/insertand the page/pdf/insert. - A Word file goes in through LibreOffice, which only the
-officeimage ships. Without it, or withFILEMORPH_OFFICE_ENGINE=mammoth, the API answersword_not_converted. - A page for Video → GIF:
/convert/video-to-gif. /toolslists every tool page.
- Inserting pages into a PDF:
- Audio and video:
- One time limit,
MEDIA_SUBPROCESS_TIMEOUT_SECONDS, now covers the whole request, with a batch's files sharing it. It is 85 seconds by default; it used to be 600 seconds for each ffmpeg run. - An
.envcopied from the.env.exampleof 1.2.0 to 1.3.0 sets600, which now covers the whole request. Delete the line to get the 85 seconds. Keep a higher value only where no CDN or proxy in front of FileMorph stops waiting sooner. The nginx and Caddy examples indocs/self-hosting.mdwait 300 seconds. - A file that runs out of time gets
400(invalid_input) instead of500. - Two new refusals, neither with a setting, both
400(invalid_input; video → GIF:video_too_complex, as before):- a video larger than 4K;
- a stream in a codec outside
INPUT_DECODERS(app/converters/_ffmpeg.py).
- On Linux, ffmpeg now stops writing at the output cap. The answer stays
413(output_cap_exceeded); its message no longer gives the output's size. - Video outputs no longer copy the source's tags and chapters. Audio keeps only the music tags.
- One time limit,
- Temporary files: the sweep for folders that a crashed worker left behind now runs every 10 minutes instead of every hour (
TEMP_SWEEP_INTERVAL_MINUTES).- An
.envcopied from an older.env.examplesets60: change it to10or delete the line. - The sweep removes any temp folder older than
TEMP_SWEEP_MAX_AGE_MINUTES, even one a request is still using. IfMEDIA_SUBPROCESS_TIMEOUT_SECONDSis above 600 (ten minutes), set the max age above it.
- An
- Now
400instead of500:- Images between one and two times the size limit get
decompression_bomb. - PDF → TXT of a PDF whose page content is JBIG2 data, on a host with
jbig2dec.
- Images between one and two times the size limit get
- Docker image and debugging:
- In the image, the app's code belongs to root and is read-only for
appuser; only/app/datastays writable. A custom Dockerfile that runschown -R appuser:appuser /appcan limit that to/app/data. - On Linux the app process is non-dumpable. Attaching a debugger or profiler (gdb, py-spy) needs root; in a container, root with
SYS_PTRACE.
- In the image, the app's code belongs to root and is read-only for
- Translations: the app reads the
.pofiles directly. A.moplaced inlocale/is ignored; edit the.poinstead. - Installing from
requirements.txt:-
Floors that move up: FastAPI 0.162.0, SQLAlchemy 2.1.6, alembic 1.20.1, pypdf 6.21.2, ReportLab 5.1.0 and certifi 2026.10.23.
-
Newly listed, with these floors: Starlette 1.10.0, Mako 1.4.3 and dnspython 2.9.0.
-
FastAPI 0.155–0.162 changed three things:
- it refuses unknown keyword arguments to
Form()andQuery(); - it applies a parameter model's
extrasetting to the fields declared next to it; - it no longer reads an omitted
boolform field asFalse.
FileMorph's routes rely on none of these, but a fork's own routes might.
- it refuses unknown keyword arguments to
-
The full list of changes is in CHANGELOG.md.
What's Changed
- fix(media): video and audio outputs drop the source's metadata — like images by @MrChengLen in #264
- ci(deps): audit every lockfile against PyPI and OSV — uv and SBOM locks too, Mako 1.4.3 by @MrChengLen in #267
- feat(media): ffmpeg runs with resource limits — time per request, memory, decoders by @MrChengLen in #271
- feat(security): app process non-dumpable — gs without app secrets, code read-only by @MrChengLen in #272
- refactor(pages): one catalogue of public pages — sitemap, llms.txt and related links built from it by @MrChengLen in #277
- deps: dnspython 2.9.0 — CVE-2026-114605 in DNS name decompression by @MrChengLen in #278
- fix(images): palette images keep their colours — strip_metadata now keeps the palette by @MrChengLen in #274
- ci(deps): Bump the actions-all group across 1 directory with 2 updates by @dependabot[bot] in #269
- test(media): #271 follow-ups — parent-death test waits on a pidfd; docs name ffmpeg and ffprobe by @MrChengLen in #276
- chore(i18n): translations load from the .po files — no .mo in the repository by @MrChengLen in #275
- fix(images): portrait photos stay upright — the EXIF turn is applied before the strip by @MrChengLen in #279
- feat(pdf): insert pages into a PDF — a PDF, Word file or image at a chosen page by @MrChengLen in #280
- fix(pdf): JBIG2 page content gets a 400 in PDF → TXT — also with jbig2dec installed by @MrChengLen in #281
- feat(pages): /tools lists every tool page — quick actions, /tools and the footer read the page catalogue by @MrChengLen in #282
- feat(pages): one layout for the tool pages — a breadcrumb instead of "← Back", one related block by @MrChengLen in #283
- feat(pages): /convert/video-to-gif — a page for Video → GIF, findable on /tools, in the footer and from /compress by @MrChengLen in #284
- deps: python-all batch — FastAPI 0.162, Starlette 1.10, SQLAlchemy 2.1.6 and five smaller updates by @MrChengLen in #285
- feat(pages): /pdf/insert — insert a PDF, Word file or image at a chosen page by @MrChengLen in #286
- fix(files): temp dirs go however a response ends — sweep every 10 minutes by @MrChengLen in #287
- docs(changelog): release 1.4.0 — fold changelog.d, bump the version by @MrChengLen in #288
Full Changelog: v1.3.0...v1.4.0