diff --git a/CHANGES.md b/CHANGES.md index ad9ad1f..4bbcdac 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,5 +1,11 @@ # CHANGELOG +## Version 1.3.2 + +### Security + +* Ship a hardened ImageMagick `policy.xml` in the final image to mitigate image-decompression-bomb DoS via the Appwrite storage/avatars preview pipeline. A crafted image (small on disk, huge dimensions) previously decoded unbounded, spilling ImageMagick's pixel cache to disk and filling the volume — killing MongoDB or the container. The policy caps `disk` (4GiB spill limit — the primary control; sized for a 150MP Q16-HDRI photo) plus generous `width`/`height` backstops (50KP, well above any real camera so legitimate high-res photos are never rejected), sets `memory`/`map`/`area`/`thread` limits, and disables coders/modules never used for previews (PS/EPS/PDF/XPS/MSL/MVG/HTTP/etc., plus SVG/SVGZ/MSVG via a `module` deny that also closes the SVG SSRF/XXE delegate route). Installed into ImageMagick's configure dir (discovered at build time); the build fails if the policy does not load. Added a `tests.yaml` assertion verifying the policy is active. + ## Version 1.3.1 ### Fix diff --git a/Dockerfile b/Dockerfile index 3c88a0f..9332369 100644 --- a/Dockerfile +++ b/Dockerfile @@ -244,6 +244,18 @@ RUN apk update && \ zstd-libs \ && rm -rf /var/cache/apk/* +# Hardened ImageMagick policy — bounds per-decode width/height/disk so a crafted +# "image bomb" (small on disk, enormous when decoded) cannot exhaust memory or +# fill the disk and take down the container or its neighbours. Installed into +# ImageMagick's configure dir, discovered at build time so it survives package +# path changes; the build fails loudly if the policy does not load. +COPY policy.xml /tmp/policy.xml +RUN set -eux; \ + POLICY_DIR="$(identify -list configure | awk '/^CONFIGURE_PATH/ {print $2}' | cut -d: -f1)"; \ + cp /tmp/policy.xml "${POLICY_DIR%/}/policy.xml"; \ + rm /tmp/policy.xml; \ + identify -list policy | grep -q '50KP' + WORKDIR /usr/src/code COPY --from=core-extensions /artifacts/ /tmp/exts/ diff --git a/policy.xml b/policy.xml new file mode 100644 index 0000000..ea431ba --- /dev/null +++ b/policy.xml @@ -0,0 +1,73 @@ + + + + + + + + + + + +]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests.yaml b/tests.yaml index 926e132..69482b2 100644 --- a/tests.yaml +++ b/tests.yaml @@ -97,6 +97,14 @@ commandTests: args: ["-i"] expectedOutput: - "ImageMagick supported formats .*WEBP.*" + - name: 'ImageMagick hardened policy loaded' + command: "identify" + args: ["-list", "policy"] + expectedOutput: + - "name: width" + - "name: height" + - "name: disk" + - "50KP" - name: 'PHP intl' command: "php" args: ["-r", 'print(\Normalizer::FORM_D);']