Stripy Horse
Stripy Horse

← All guides

ImageMagick won't open your PDF ("not allowed by the security policy")

Your code reads a PDF with ImageMagick. It works on your laptop. It fails on the server, in CI, or inside the container, with this:

convert-im6.q16: attempt to perform an operation not allowed by the security policy `PDF'
@ error/constitute.c/IsCoderAuthorized/426.

From PHP the same thing arrives as an exception:

ImagickException: attempt to perform an operation not allowed by the security policy `PDF'

Older builds point at error/constitute.c/ReadImage/412 instead of IsCoderAuthorized/426. Same rule, different line number.

Nothing is wrong with your PDF or your code. ImageMagick is refusing to load its PDF reader because a config file told it to.

First, check what your policy actually says

Do not assume it is PDF that is blocked. The rule varies by distro and has changed over time, so read yours before you change anything:

identify -list policy      # ImageMagick 6
magick -list policy        # ImageMagick 7

You are looking for a Policy: Coder block naming PDF. On a current Ubuntu box you may find PDF is already allowed and something else is not:

Policy: Coder
  rights: Read Write
  pattern: PDF

The file itself is usually one of:

/etc/ImageMagick-6/policy.xml
/etc/ImageMagick-7/policy.xml

A blocked entry looks like this, and an allowed one carries read | write:

<policy domain="coder" rights="none" pattern="PDF" />
<policy domain="coder" rights="none" pattern="EPS" />
<policy domain="coder" rights="none" pattern="XPS" />

This is the single most common reason the same code passes locally and fails in CI: two different base images, two different policies. Check both before assuming your code is at fault.

Why the block exists

ImageMagick cannot read PDF by itself. It hands the file to Ghostscript and reads back what comes out. That makes every PDF you open a Ghostscript execution on your server, with a file someone else may have supplied.

In 2016 the ImageTragick bugs (CVE-2016-3714 and friends) let a crafted file run commands through ImageMagick's delegates, which is what the policy.xml mechanism was built for. In 2018 a run of Ghostscript sandbox escapes (CVE-2018-16509 and siblings) turned "open this PDF" into remote code execution again. Distributions responded by disabling the PDF, PS, EPS and XPS coders by default rather than shipping a delegate with that history.

That was a reasonable call. It is also why a shipping label you generated yourself will not open on a stock Debian container.

Five ways past it

1. Re-enable the coder (needs root)

Edit policy.xml and give the PDF pattern read rights:

<!-- before -->
<policy domain="coder" rights="none" pattern="PDF" />
<!-- after -->
<policy domain="coder" rights="read | write" pattern="PDF" />

Then confirm it took:

identify -list policy | grep -A2 'pattern: PDF'

This puts the Ghostscript path back. That is defensible on a current Ghostscript, which is patched against the 2018 escapes, and much less so on whatever version a five-year-old base image is pinned to. If the PDFs are uploaded by your users rather than generated by you, treat this as a security decision and not a config toggle, because it is one.

2. Do it in the Dockerfile

If you own the image, make it part of the build so it survives a rebuild:

RUN sed -i 's/rights="none" pattern="PDF"/rights="read|write" pattern="PDF"/' \
      /etc/ImageMagick-6/policy.xml

Pin and update Ghostscript in the same image while you are there.

3. Rasterize with something that is not Ghostscript

The policy is about one delegate, so a renderer that does not use it never trips the rule. pdfium (what Chrome uses) and mupdf both rasterize PDF without Ghostscript.

Be honest about the cost in PHP, though: reaching either one means a PECL extension or a system binary, which is the same install conversation you were trying to avoid, on a package your ops team has not heard of. It is a real fix on a host you control and a non-starter on one you do not.

4. Do not rasterize on that host at all

If the blocker is that you cannot change the host, the way out is to stop needing to. Send the PDF somewhere that already has a rasterizer and get the result back. No policy.xml, no Ghostscript on your box, no ticket:

curl https://api.stripyhorse.io/v1/convert \
  -H "X-Api-Key: sh_live_YOUR_KEY" \
  -F file=@label.pdf -F preset=4x6 -F dpmm=8

That is the API this site runs on, and it is worth naming what you are trading: a network call and a dependency on someone else's uptime, in exchange for no native dependencies and nothing to patch. If your host is locked down enough to hit this error in the first place, that is usually the trade you wanted.

5. Give it an image instead of a PDF

The policy only guards the PDF coder. Most PHP imaging work, including benfaerber/pdf-to-zpl, can run on GD alone once the input is already a raster, and GD ships in nearly every PHP install while Imagick is an extension somebody has to add. So if your input is a PNG or a JPEG, none of this page applies to you: no Imagick, no Ghostscript, no policy.xml.

That is worth knowing before you fight the policy, because the input is sometimes negotiable. Several carrier APIs will return a PNG label if you ask for one, and a PDF that arrives from a system you control can be rasterized at the point it is made rather than the point it is printed.

Be clear-eyed about what it costs, though. GD does the pixel work in PHP rather than in C, and a full label at print resolution is around a million pixels, so expect it to take tens of seconds where Imagick takes a fraction of one. Fine for a handful of labels a day. Not fine for an end-of-day batch, where the answer is a host you can install on, or option 4.

This is not a way to rasterize a PDF without Ghostscript. It is a way to keep using the library when what you actually have is an image.

If you hit this converting a label

The most common way people meet this error is turning a carrier PDF into something a Zebra printer will accept, because ZPL has no PDF support and the label has to become a bitmap first.

Three routes, and the policy wall only affects the first, and only when the input is a PDF:

  1. benfaerber/pdf-to-zpl, the MIT-licensed PHP library. Runs in your app. PDF input needs Imagick, which is what this page is about; image input runs on GD alone.
  2. The free online converter. Drop the PDF, get ZPL per page. Nothing to install.
  3. The API or one of its SDKs, shown above.

The full walkthrough covers the dpmm maths that decides whether the output actually prints at the right size, which is the next thing to get wrong after this one.

Why does it work locally and fail in CI?

Different policies in different images, almost always. Run identify -list policy in both and compare. Recent Ubuntu ships PDF enabled while Debian and several minimal base images still ship it off, so a laptop and a container legitimately disagree.

Can I fix this on shared hosting?

Usually not. policy.xml lives under /etc and belongs to root, and managed platforms rarely let you edit it or install a PECL extension. If that is where you are, options 1 to 3 are all closed and option 4 is the only one left.

Is re-enabling PDF safe?

It is a judgement, not a yes or no. Ghostscript is actively maintained and the 2018 bugs are long fixed, so a current version processing PDFs you generated yourself is a small risk. An old version processing files uploaded by strangers is how the CVEs got written. Know which of those you are running.

EPS and PS still fail after I fixed PDF

They are separate patterns. Distros that re-enabled PDF often left EPS, PS and XPS at rights="none", so each coder you need has to be allowed by name.

Stripy Horse is the developer platform for Zebra printing: convert PDFs and images, design labels in HTML, preview ZPL pixel-true, and test against virtual printers in CI. Get in touch or try the free tools.

Published 2026-09-03 · Ben Faerber, software engineer, five years building warehouse fulfillment and label-printing systems; maintainer of pdf-to-zpl (27,000+ installs powering production label generation).