attempt to perform an operation not allowed by the security policy 'PDF'
你的命令没问题,是 policy.xml 默认封掉了 PDF、PS 和 EPS。如何找到这个文件、改哪几行,以及什么情况下不该改。
你跑了类似 magick input.pdf output.png 的命令,然后得到:
convert: attempt to perform an operation not allowed by the security policy 'PDF'
@ error/constitute.c/ReadImage/412
你的命令是对的。 ImageMagick 是故意拒绝的。
为什么会这样
ImageMagick 把 PDF、PostScript 和 EPS 的解码委托给 Ghostscript。2018 年 Ghostscript 爆出一系列漏洞,攻击者可以用精心构造的 PDF 在主机上执行任意命令。因为 ImageMagick 极常用于处理用户上传的文件,各发行版的应对方式就是默认发一份把这些格式全部禁用的 policy.xml。
所以这不是 bug,也不是你配错了 —— Debian、Ubuntu、RHEL、Fedora、Alpine 和大多数 Docker 镜像都是这个默认值。
找到策略文件
magick -list policy
ImageMagick 6 上是:
convert -list policy
输出的第一行就是路径。常见位置:
/etc/ImageMagick-7/policy.xml/etc/ImageMagick-6/policy.xml/usr/local/etc/ImageMagick-7/policy.xml(Homebrew)~/.config/ImageMagick/policy.xml(用户级覆盖)
要改的几行
文件靠底部能找到:
<policy domain="coder" rights="none" pattern="PS" />
<policy domain="coder" rights="none" pattern="PS2" />
<policy domain="coder" rights="none" pattern="PS3" />
<policy domain="coder" rights="none" pattern="EPS" />
<policy domain="coder" rights="none" pattern="PDF" />
<policy domain="coder" rights="none" pattern="XPS" />
把你需要的那几行注释掉或删掉。如果只想允许读 PDF,改权限而不是删行:
<policy domain="coder" rights="read" pattern="PDF" />
这样 pdf → png 可以做,但仍然禁止写 PDF,是个比较合理的折中。
验证
magick -list policy | grep -i pdf
magick -density 150 input.pdf page.png
不改系统文件的用户级覆盖
如果你没有 /etc 的写权限,ImageMagick 也会读取你主目录下的策略:
mkdir -p ~/.config/ImageMagick
cat > ~/.config/ImageMagick/policy.xml <<'EOF'
<policymap>
<policy domain="coder" rights="read|write" pattern="PDF" />
<policy domain="coder" rights="read|write" pattern="EPS" />
<policy domain="coder" rights="read|write" pattern="PS" />
</policymap>
EOF
也可以用 MAGICK_CONFIGURE_PATH 环境变量为单次运行指定策略文件。
在 Docker 里
RUN apt-get update && apt-get install -y imagemagick ghostscript \
&& sed -i 's/rights="none" pattern="PDF"/rights="read|write" pattern="PDF"/' \
/etc/ImageMagick-6/policy.xml
什么时候不该改
这点很重要。如果你的服务器要处理陌生人上传的 PDF,这条策略是在真正做事的。关掉它就等于把当初为之添加的攻击面重新打开。这种情况下应该保留策略,改用职责更窄的工具:
pdftoppm -png -r 150 input.pdf page # poppler-utils
pdftoppm 只做一件事,攻击面比 Ghostscript 小得多,而且通常更快。如果确实必须对不可信输入用 Ghostscript,请把它放进容器或沙箱里跑,断网、只读文件系统,并保持更新。
在自己电脑上转自己的 PDF,改策略完全没问题。