#1708·imgproxy

SVG sanitizer does not strip external resource references in <style>, <image>, and <feImage> elements

Author: geo-chenCreated Aug 4, 2026Updated Aug 4, 2026

reported via email on 13 June 2026:

I found an incomplete case in imgproxy's SVG sanitizer that allows attacker-controlled external resource loading to survive sanitization.

When IMGPROXY_SANITIZE_SVG=true (the default), imgproxy removes <script> tags, <iframe> tags, and on* event-handler attributes from SVG files before serving them. However, the sanitizer does not remove or neutralize:

  1. Content inside <style> tags -- CSS @import url([https://attacker-server/)](https://attacker-server/)) and background: url(...) directives pass through unchanged.
  2. <image href="[https://attacker-server/..](https://attacker-server/)."> SVG image elements.
  3. <feImage href="[https://attacker-server/..](https://attacker-server/)."> inside SVG <filter> blocks.

When imgproxy serves the sanitized SVG with Content-Type: image/svg+xml and Content-Disposition: inline (the default), a browser opening the URL will perform GET requests to those external origins. The CSP header script-src 'none' that imgproxy already sets does not restrict CSS or image loading, so these requests are not blocked.

I confirmed this by running imgproxy v4.0.4 with default settings, fetching a test SVG containing the above elements, and observing that the response body contains the attacker URLs unchanged. The full test steps and observed output are shown below.

To reproduce:

  1. Run: docker run -d -p 8080:8080 -e IMGPROXY_SANITIZE_SVG=true darthsim/imgproxy:latest
  2. Prepare an SVG with <image href="https://attacker.example.com/"> and serve it locally.
  3. Request http://localhost:8080/insecure/<base64-encoded-url>.svg.
  4. The response body contains the <image> element with the attacker URL intact.

Suggested fix: Extend the sanitizeElement function in processing/svg/svg.go to either (a) strip <style> elements entirely, or sanitize their content to remove url() references and @import directives; (b) strip <image> elements or allow only data: URIs; and (c) strip <feImage> elements. Additionally, consider adding default-src 'none' or img-src 'none'; style-src 'none' to the existing CSP header as a defense-in-depth measure.