Skip to content

Enable SVG decode via librsvg, read-only - #95

Open
Meldiron wants to merge 1 commit into
mainfrom
feat-svg-decode
Open

Enable SVG decode via librsvg, read-only#95
Meldiron wants to merge 1 commit into
mainfrom
feat-svg-decode

Conversation

@Meldiron

Copy link
Copy Markdown
Contributor

What does this PR do?

Makes Imagick able to decode SVG so Appwrite's /preview endpoint can rasterize SVG uploads and apply the full transformation pipeline (crop, rotate, borders, output=png, …). Today SVG previews fall back to a placeholder icon because the image cannot open SVG at all — two independent blockers:

  1. Alpine's imagemagick package is installed without the imagemagick-svg subpackage, so there is no SVG decode delegate (no decode delegate for this image format 'SVG' even with the policy lifted).
  2. policy.xml denies the SVG/SVGZ/MSVG coders and module.

Changes:

  • Install imagemagick-svg, which decodes through librsvg — the memory-safe Rust renderer — never ImageMagick's internal MSVG coder.
  • Grant the SVG/SVGZ coders read-only rights in policy.xml.
  • The policy install step now decodes a probe SVG, so the build fails loudly if the delegate or policy regresses.
  • Structure tests: SVG/SVGZ in registered formats, the rights: Read{SVG,SVGZ} policy pairing, and a real decode through the PHP imagick extension.

What stays blocked (the reasons SVG was denied in the first place):

Guard Status
HTTP/HTTPS delegates (SSRF via external hrefs) still denied
@* path reads (local file disclosure) still denied
MSVG internal renderer (riskier fallback if librsvg is absent) still denied
SVG encode denied — the grant is read-only
Resource bombs existing width/height/disk/memory limits apply to the rasterized output

Test Plan

Validated against a container from appwrite/base:2.0.0 with imagemagick-svg installed and this exact policy.xml:

  • SVG decode + rotate + PNG encode through the PHP imagick extension works (also verified end-to-end through Utopia\Image\Image crop/rotate/output('png') — the exact Appwrite preview pipeline)
  • SVG encode is denied
  • MSVG decode is denied
  • identify -list policy output matches the new structure-test regex

All three new/extended tests.yaml assertions were validated against real container output.

Related PRs and Issues

🤖 Generated with Claude Code

The Appwrite preview endpoint substitutes SVG uploads with a placeholder
icon because Imagick cannot open them: the image ships no SVG decode
delegate (Alpine's imagemagick package without the imagemagick-svg
subpackage) and the hardened policy denies the SVG coders and module.

Install imagemagick-svg, which decodes through librsvg — the memory-safe
Rust renderer — and grant the SVG/SVGZ coders read-only rights so
previews can rasterize, crop, rotate and convert SVG uploads.

The reasons SVG was blocked stay enforced: HTTP/HTTPS delegates remain
denied (no external hrefs), the @* path deny still blocks local file
reads, MSVG — ImageMagick's internal, riskier SVG renderer — stays
denied so it cannot be reached even if librsvg goes missing, and SVG
encode is denied by the read-only grant.

The policy install step now decodes a probe SVG so the build fails
loudly if the delegate or policy regresses, and structure tests assert
the registered formats, the read-only policy pairing, and a real decode
through the PHP extension.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@greptile-apps

greptile-apps Bot commented Aug 27, 2026

Copy link
Copy Markdown

Greptile Summary

The PR adds librsvg-backed SVG decoding to the runtime image and grants SVG/SVGZ read-only ImageMagick access while retaining existing resource, network-delegate, path, and MSVG restrictions.

  • Installs the Alpine imagemagick-svg package.
  • Adds build-time and container-structure probes for basic SVG decoding.
  • Updates the changelog and policy documentation for the new capability.

Confidence Score: 4/5

The PR appears safe to merge, with a non-blocking recommendation to test the external-resource restrictions that now protect SVG decoding.

The package, policy, build probe, and runtime capability test are aligned for basic SVG decoding; the remaining concern is that validation proves successful decoding but not continued enforcement of the security controls surrounding hostile SVG references.

Files Needing Attention: tests.yaml

Security Review

No concrete vulnerability was established. The new tests should additionally exercise the external-resource restrictions that now protect the enabled SVG path, so later package or policy regressions cannot pass validation unnoticed.

Important Files Changed

Filename Overview
Dockerfile Installs the SVG delegate and adds a successful basic SVG decode as a build-time capability check.
policy.xml Re-enables SVG/SVGZ decoding with read-only coder rights while retaining MSVG, network-delegate, indirect-path, and resource restrictions.
tests.yaml Verifies format registration, policy rights, and basic Imagick decoding, but does not validate the external-resource restrictions protecting the newly enabled input path.
CHANGES.md Documents the new SVG capability and the security controls intended to remain in force.

Fix all with Greploop Fix All in Claude Code Fix All in Codex

Prompt To Fix All With AI
### Issue 1
tests.yaml:115-118
**External-resource guards untested**

The new test decodes only an empty inline SVG, so image validation does not exercise the HTTP/HTTPS and indirect-path restrictions protecting the newly enabled untrusted SVG path. A later package or policy regression can leave basic decoding green while those security controls no longer isolate external resources.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Reviews (1): Last reviewed commit: "Enable SVG decode via librsvg, read-only" | Re-trigger Greptile

Comment thread tests.yaml
Meldiron added a commit to appwrite/appwrite that referenced this pull request Aug 27, 2026
Replaces the sanitize-and-serve approach: with appwrite/base 2.1.0 the
image ships the librsvg-backed SVG coder with read-only rights, so SVG
becomes a regular preview input — decoded by Imagick and run through the
existing crop, rotate, border and output pipeline like any raster
format. No endpoint changes needed; image/svg+xml joins the accepted
inputs and the base image tags move to 2.1.0.

Requires the base release from appwrite/docker-base#95.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant