docker compose pull won't apply the n8n security update patch

n8n published a security update on October 14, 2026, and every write-up gives self-hosters the same four words: update your container image. That assumes the image is n8n's. If yours is a custom build with FROM n8nio/n8n and FFmpeg on top, docker compose pull is a no-op and your stack comes up green on the old, vulnerable n8n.
Quick answer: Applying the n8n security update patch to a custom Docker image takes three commands, not one: bump theFROMtag in your Dockerfile to 1.123.85 or 2.43.5 (2.44.1 on beta), rundocker compose build --pull, thendocker compose up -d.docker compose pulldoes nothing for a custom image because the tag you reference is local. Your~/.n8nvolume, credentials, and encryption key survive the rebuild as long as the volume mount stays in compose. If the FFmpeg binary is the only reason your image is custom, move that step to a hosted FFmpeg API over one HTTP Request and go back to the stock image, where the documented one-command patch works.
What the October 14 bulletin requires
The n8n security update of October 14, 2026 fixes a batch of GitHub security advisories, five rated High, with fixed versions at 1.123.85, 2.43.5 on stable and 2.44.1 on beta. n8n Cloud was patched automatically. Self-hosters have to update the image and recreate the container with persistent data intact. Current heads are above that floor, so patch forward rather than to the exact bulletin number.
readthemanual.co.uk counted 15 advisories where earlier reporting said eight. Two are worth reading twice: stored XSS through webhook responses at CVSS 8.4, and cross-project Data Table access through a crafted workflow ID at CVSS 7.2. GHSA-3c3p-5959-3ghr in the Slack Trigger needs no login, which matters if your webhook URLs are reachable from the internet. No active exploitation was confirmed at publication.
Censys' October 14, 2026 State of the Internet Report counted n8n as the most exposed AI product on the public internet, at 113,926 hosts, and 76% of version-parseable ones ran a version affected by a recent critical vulnerability. Roughly 77,000 instances, many unpatched for exactly this reason.
Why docker compose pull leaves a custom image unpatched
The official update procedure is docker compose pull, docker compose down, docker compose up -d. That works when your compose file's image name points at a registry tag n8n owns. A custom image points at a tag that only exists on your box, so pull prints nothing useful and up -d restarts the same bytes as before.
The community answer to the most common n8n upgrade failure on a custom image is to bump the FROM tag and run docker compose build --pull. The --pull is not optional: tags are mutable, docker build reuses cached base layers, and a rebuild against a stale local base can succeed and still ship the old n8n.
The Dockerfile most readers are running
Most n8n FFmpeg tutorials produce some version of this file:
FROM n8nio/n8n:1.123.70
USER root
RUN apk add --no-cache ffmpeg fontconfig ttf-dejavu font-noto-emoji
USER node
Two lines are load-bearing. The pinned FROM tag never moves, no matter how often you rebuild. The unpinned apk add line will move, possibly by a whole FFmpeg major version, the next time the base image's Alpine index refreshes.
Check before you start: the official docker.n8n.io/n8nio/n8n image went distroless in 2026, with no apk or apt inside. If your FROM line uses that path at a recent tag, the Dockerfile above won't build, and the fix is a multi-stage build that copies the FFmpeg binaries from an Alpine stage. The runtime-error version is in why n8n says "No usable ffmpeg was found".
The rebuild, in order
Patching a custom n8n image is six steps. The last three are the ones people skip.
- Edit the
FROMline to the patched tag:FROM n8nio/n8n:1.123.85on 1.x, or the 2.43.5+ tag on 2.x. Commit it so the next person can see the base. docker compose build --pullfrom the directory with your compose file.docker compose up -d. Compose notices the image ID changed and recreates the container. No separatedownneeded.- Verify the running version, not the container state. Help then About in the editor UI shows the version string, and
docker compose exec n8n n8n --versionworks if your image still has a shell. "Up 4 seconds" proves nothing about the n8n inside. - Confirm the volume is still mounted, and is the same one:
docker inspect -f '{{json .Mounts}}' $(docker compose ps -q n8n). Then open a credential in the UI. If it decrypts, the encryption key in~/.n8n/configcame through and your workflows are intact. If credentials look empty, compose probably created a fresh anonymous volume instead of reattaching yours. - Re-test the FFmpeg layer, covered next.
The two things that break
Two failure modes cause most bad outcomes here, and neither errors at rebuild time.
A pinned base tag that rebuilds clean and stays unpatched
A pinned FROM n8nio/n8n:1.123.70 is right for reproducibility and wrong for a security deadline: nothing in the build output tells you the base is five weeks stale. The fix is procedural, so whoever handles the patch edits the Dockerfile first, every time. Running latest instead swaps silent staleness for a silent major upgrade, worse on n8n 2.x and the coming 3.0. Pin, and put the tag bump in the runbook.
If you also run external task runners, you own two images. FFmpeg has to live in the `n8nio/runners` image (1.121.0 or newer to be extensible), at a version matching n8n's. Two Dockerfiles per bulletin, and skew between them fails in ways that look like workflow bugs.
An FFmpeg layer that has to be re-tested, not just rebuilt
apk add --no-cache ffmpeg resolves against whatever the base image's package index offers that day, so a base bump can move your FFmpeg major version without you asking. That is how a working -vsync flag becomes a deprecation warning and then an error, covered in FFmpeg vsync is deprecated. Fonts are nastier: drawtext and subtitle burn-in need fontconfig plus a font package, and without them FFmpeg exits 0 and writes a video with no text on it. Your workflow goes green, your output is wrong.
A check, right after step 5:
docker compose exec n8n sh -c '
ffmpeg -version | head -1
ffmpeg -hide_banner -filters | grep -c drawtext
ffmpeg -hide_banner -encoders | grep -c libx264
fc-list | wc -l
'
You want a familiar FFmpeg version, 1 for drawtext, 1 for libx264, and a font count well above zero. A 0 there is the silent caption failure waiting to happen. Then run one real workflow end to end on the longest input you have, because the n8n 3.0 line drops the task runner timeout to 1 minute, shorter than most real transcodes.
Custom image versus stock image plus an HTTP Request
Nobody maintains a custom n8n image for fun. One node needs a binary. Compare what each costs on a security bulletin day.
| Custom image with FFmpeg | Stock image + hosted FFmpeg API | |
|---|---|---|
| Patch command | Edit Dockerfile, `build --pull`, `up -d` | `docker compose pull`, `up -d` |
| Re-test after patch | FFmpeg version, codecs, fonts, one real render | None |
| Distroless base change | Breaks the build, needs a multi-stage rewrite | Not your problem |
| Task runners | Second image to bump and version-match | Not affected |
| CPU during a 4K encode | Your n8n box, competing with the scheduler | Elsewhere |
n8n's security cadence is now roughly fortnightly: CVEs on October 5, this bulletin on October 14. Each one is a rebuild plus a re-test if your video step lives inside the image.
The replacement for the Execute Command node is an HTTP Request node: submit the job, poll for status, download the output. Same transcode your FFmpeg layer was doing, as one call to FFmpeg Micro:
curl -X POST https://api.ffmpeg-micro.com/v1/transcodes \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"inputs": [{"url": "https://storage.example.com/input.mp4"}],
"outputFormat": "mp4",
"preset": {"quality": "medium", "resolution": "1080p"}
}'
That returns a job id and status: "pending". A second HTTP Request node polls GET /v1/transcodes/{id} until status is completed, then GET /v1/transcodes/{id}/download hands back a signed URL. Captions work the same way: POST /v1/transcribe with a media_url produces an SRT you can feed into a subtitles='...' filter on a transcode job. No fontconfig to install: the fonts are on our side of the API. More than 300 builders already run it from Make or n8n, and the full HTTP pattern is in n8n 3.0 breaking changes kill your FFmpeg step.
Cost: one token buys 10 seconds of input video, metered per second with no rounding to the minute. A new account gets 200 tokens free with no card, about 33 minutes of video. Paid plans start at $19.99 a month for 2,500 tokens. Failed jobs are never billed.
When the custom image is still the right call
Keeping FFmpeg inside your n8n image makes sense in a few real cases. If your video files can't leave your network for compliance reasons, a hosted API is out and the rebuild cycle is the price. If you depend on a filter the API does not expose, including -filter_complex, which FFmpeg Micro does not support, your own binary wins. And if your inputs are routinely over 2 GB, our caps stop you: 100 MB on Free, 1,024 MB on Starter, 2,048 MB on Pro.
Third-party prebuilt n8n-plus-FFmpeg images track upstream releases for you, which removes the build latency but not the ownership: someone else's unofficial image holds your credential store, and you still own the codec and font surface inside. Fine for a hobby instance, a hard sell with customer data in it.
FAQ
Why did docker compose pull && docker compose up -d not change my n8n version?
docker compose pull only fetches images from a registry. A custom image built with a build: directive exists only locally, so there is nothing to pull and the old image ID stays. Run docker compose build --pull after bumping the FROM tag, then docker compose up -d.
Will a rebuild wipe my workflows, credentials, or encryption key?
A rebuild and recreate does not touch your data: workflows, credentials, and the encryption key live in the ~/.n8n volume, not in the image. The one way to lose them is to change or remove the volume definition while editing the compose file.
Should I jump to 1.123.85, 2.43.5, or the newest release?
Pick the patched version on the line you already run: 1.123.85 on 1.x, 2.43.5 or newer on 2.x stable, 2.44.1 or newer on beta. Jumping 1.x to 2.x stacks a feature upgrade on a security patch, and 2.x disables the Execute Command node by default, so your FFmpeg step would break for an unrelated reason.
Does the October 14 bulletin matter if my n8n is behind a VPN?
Most advisories need some access to the instance, so a single-user n8n behind a VPN with no public webhook endpoints is a smaller target than one of the 113,926 exposed hosts Censys found. Patch anyway: the stored XSS via webhook responses is reachable by anyone who can edit or trigger a workflow, including an automation pulling untrusted content into a node.
If this is the third rebuild this month, run the video step outside the image and see. The FFmpeg API quickstart creates a temporary key and walks presigned upload, transcode, poll, and download on the free tier, so one HTTP Request node can prove it before you touch the Dockerfile again.
About Javid Jamae
Founder & CEO at FFmpeg Micro
Javid is a software engineer, author, and entrepreneur with over 25 years of professional software development experience across enterprise, startup, and consulting environments. He founded FFmpeg Micro to make video processing accessible to developers through a simple, automation-first REST API.
You might also like

n8n 3.0 breaking changes kill your FFmpeg step. Send it HTTP.
n8n 3.0 breaking changes kill the npx + host ffmpeg video step. Here's the Docker Compose and distroless Dockerfile that work, and the HTTP alternative.

n8n 3.0 breaking changes: fix your video step in this order
The n8n 3.0 breaking changes that kill FFmpeg steps: the 60-second task timeout, Docker-only self-hosting, Compression caps, and removed nodes, in fix order.

n8n CVE October 2026: upgrade without breaking FFmpeg
n8n CVE October 2026: patch to 1.123.76, 2.37.7, or 2.38.2, what each flaw allows, NODES_EXCLUDE mitigations, and how to upgrade without breaking FFmpeg.
Ready to process videos at scale?
Start using FFmpeg Micro's simple API today. No infrastructure required.
Get Started Free