[Django] #36348: ManifestStaticFilesStorage breaks CSS containing data: URIs with multiple nested url()s

29 views
Skip to first unread message

Django

unread,
Apr 22, 2025, 9:51:03 PM4/22/25
to django-...@googlegroups.com
#36348: ManifestStaticFilesStorage breaks CSS containing data: URIs with multiple
nested url()s
-------------------------------------+-------------------------------------
Reporter: Samuel | Owner: Samuel Cormier-
Cormier-Iijima | Iijima
Type: | Status: assigned
Uncategorized |
Component: | Version: 5.2
contrib.staticfiles |
Severity: Normal | Keywords:
Triage Stage: | Has patch: 0
Unreviewed |
Needs documentation: 0 | Needs tests: 0
Patch needs improvement: 0 | Easy pickings: 0
UI/UX: 0 |
-------------------------------------+-------------------------------------
Consider a CSS file containing the following:

{{{
a {
background-image:
url("data:image/svg+xml;charset=utf-8,filter='url(%23b)'
filter='url(%23c)'");
}
}}}

When this is processed by ManifestStaticFilesStorage, the output is this:

{{{
a {
background-image:
url("data:image/svg+xml;charset=utf-8,filter='url(%23b)'
filter='url("#c")'");
}
}}}

Notice that the second url() has been changed and now contains a double
quote, which is invalid. The entire data: URI should be left as-is, but
the regex in the CSS replacement patterns does not account for this case
and sees the closing paren of the first nested url() as the end.
--
Ticket URL: <https://code.djangoproject.com/ticket/36348>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

Django

unread,
Apr 22, 2025, 9:51:15 PM4/22/25
to django-...@googlegroups.com
#36348: ManifestStaticFilesStorage breaks CSS containing data: URIs with multiple
nested url()s
-------------------------------------+-------------------------------------
Reporter: Samuel Cormier- | Owner: Samuel
Iijima | Cormier-Iijima
Type: Bug | Status: assigned
Component: contrib.staticfiles | Version: 5.2
Severity: Normal | Resolution:
Keywords: | Triage Stage:
| Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Samuel Cormier-Iijima):

* type: Uncategorized => Bug

--
Ticket URL: <https://code.djangoproject.com/ticket/36348#comment:1>

Django

unread,
Apr 23, 2025, 8:09:09 AM4/23/25
to django-...@googlegroups.com
#36348: ManifestStaticFilesStorage breaks CSS containing data: URIs with multiple
nested url()s
-------------------------------------+-------------------------------------
Reporter: Samuel Cormier- | Owner: Samuel
Iijima | Cormier-Iijima
Type: Bug | Status: assigned
Component: contrib.staticfiles | Version: 5.2
Severity: Normal | Resolution:
Keywords: | Triage Stage:
| Unreviewed
Has patch: 1 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Natalia Bidart):

* has_patch: 0 => 1

--
Ticket URL: <https://code.djangoproject.com/ticket/36348#comment:2>

Django

unread,
Apr 23, 2025, 10:06:14 AM4/23/25
to django-...@googlegroups.com
#36348: ManifestStaticFilesStorage breaks CSS containing data: URIs with multiple
nested url()s
-------------------------------------+-------------------------------------
Reporter: Samuel Cormier- | Owner: Samuel
Iijima | Cormier-Iijima
Type: Bug | Status: assigned
Component: contrib.staticfiles | Version: 5.2
Severity: Normal | Resolution:
Keywords: | Triage Stage:
| Unreviewed
Has patch: 1 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Comment (by Samuel Cormier-Iijima):

https://github.com/django/django/pull/19408
--
Ticket URL: <https://code.djangoproject.com/ticket/36348#comment:3>

Django

unread,
Apr 24, 2025, 11:29:04 AM4/24/25
to django-...@googlegroups.com
#36348: ManifestStaticFilesStorage breaks CSS containing data: URIs with multiple
nested url()s
-------------------------------------+-------------------------------------
Reporter: Samuel Cormier- | Owner: Samuel
Iijima | Cormier-Iijima
Type: Bug | Status: closed
Component: contrib.staticfiles | Version: 5.2
Severity: Normal | Resolution: invalid
Keywords: | Triage Stage:
| Unreviewed
Has patch: 1 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Natalia Bidart):

* resolution: => invalid
* status: assigned => closed

Comment:

Hello Samuel Cormier-Iijima, thank you for your ticket. I wasn't able to
find documentation supporting the validity of the provided CSS. Based on
what I've found:

1. The `data:image/svg+xml` scheme allows embedding SVGs directly, but the
correct format looks like this: `background-image:
url("data:image/svg+xml;charset=utf-8,<svg>...</svg>");`. See
[https://developer.mozilla.org/en-
US/docs/Web/CSS/url_function?utm_source=chatgpt.com#using_a_data_url MDN
documentation] for reference.
2. It seems the CSS is attempting to apply multiple filters within the SVG
via the filter attribute in the data URL. However, I don't believe this is
valid SVG syntax. In SVG, filters are defined within the `<defs>` element
and then applied using a single filter attribute on a specific SVG
element. See [https://developer.mozilla.org/en-
US/docs/Web/SVG/Reference/Attribute/filter filter attribute] and
[https://developer.mozilla.org/en-US/docs/Web/SVG/Reference/Element/filter
filter element] docs.

Could you provide a failing test using valid CSS? I'll close this ticket
as `invalid` for now, as I’m not convinced this is a Django issue. Feel
free to reopen it with more information or a reproducible example using
valid syntax. Also I would advice reaching out to the
[https://forum.djangoproject.com/ Django Forum] for getting further
assistance and confirming this is indeed a Django issue.
--
Ticket URL: <https://code.djangoproject.com/ticket/36348#comment:4>

Django

unread,
Apr 24, 2025, 11:55:57 AM4/24/25
to django-...@googlegroups.com
#36348: ManifestStaticFilesStorage breaks CSS containing data: URIs with multiple
nested url()s
-------------------------------------+-------------------------------------
Reporter: Samuel Cormier- | Owner: Samuel
Iijima | Cormier-Iijima
Type: Bug | Status: closed
Component: contrib.staticfiles | Version: 5.2
Severity: Normal | Resolution: invalid
Keywords: | Triage Stage:
| Unreviewed
Has patch: 1 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Comment (by Samuel Cormier-Iijima):

Sure, I had shortened the example to make the issue clearer, but this
happens with valid SVGs. Here's a
[https://editsvgcode.com/9sw9316mzb9m9vjjz4t sample valid SVG file]:

{{{
<svg width="100" height="100" xmlns="http://www.w3.org/2000/svg">
<filter id="blur1">
<feGaussianBlur stdDeviation="2" />
</filter>
<filter id="blur2">
<feGaussianBlur stdDeviation="5" />
</filter>
<rect width="50" height="50" x="10" y="10" fill="red"
filter="url(#blur1)" />
<rect width="50" height="50" x="40" y="40" fill="blue"
filter="url(#blur2)" />
</svg>
}}}

If this gets inlined into CSS with a data: URI, the resulting CSS file
looks like this:

{{{
#example {
background-image: url("data:image/svg+xml,%3Csvg width='100'
height='100' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter
id='blur1'%3E%3CfeGaussianBlur stdDeviation='2' /%3E%3C/filter%3E%3Cfilter
id='blur2'%3E%3CfeGaussianBlur stdDeviation='5' /%3E%3C/filter%3E%3Crect
width='50' height='50' x='10' y='10' fill='red' filter='url(%23blur1)'
/%3E%3Crect width='50' height='50' x='40' y='40' fill='blue'
filter='url(%23blur2)' /%3E%3C/svg%3E");
}
}}}

When this then gets processed by Django's collectstatic, the output is
this:

{{{
#example {
background-image: url("data:image/svg+xml,%3Csvg width='100'
height='100' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter
id='blur1'%3E%3CfeGaussianBlur stdDeviation='2' /%3E%3C/filter%3E%3Cfilter
id='blur2'%3E%3CfeGaussianBlur stdDeviation='5' /%3E%3C/filter%3E%3Crect
width='50' height='50' x='10' y='10' fill='red' filter='url(%23blur1)'
/%3E%3Crect width='50' height='50' x='40' y='40' fill='blue'
filter='url("#blur2")' /%3E%3C/svg%3E");
}
}}}

Notice that the second use of filter has been changed to `url("#blur2")` -
because this has the double quotes this CSS is invalid.
--
Ticket URL: <https://code.djangoproject.com/ticket/36348#comment:5>

Django

unread,
Apr 24, 2025, 4:50:48 PM4/24/25
to django-...@googlegroups.com
#36348: ManifestStaticFilesStorage breaks CSS containing data: URIs with multiple
nested url()s
-------------------------------------+-------------------------------------
Reporter: Samuel Cormier- | Owner: Samuel
Iijima | Cormier-Iijima
Type: Bug | Status: new
Component: contrib.staticfiles | Version: 5.2
Severity: Normal | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Natalia Bidart):

* resolution: invalid =>
* stage: Unreviewed => Accepted
* status: closed => new

Comment:

Thank you Samuel, this helps. I have used your SVG and I have encoded it
and try it with `ManifestStaticFilesStorage`. What I get is:

{{{
#example {
background-image: url("data:image/svg+xml,%3Csvg width='100'
height='100' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter
id='blur1'%3E%3CfeGaussianBlur stdDeviation='2' /%3E%3C/filter%3E%3Cfilter
id='blur2'%3E%3CfeGaussianBlur stdDeviation='5' /%3E%3C/filter%3E%3Crect
width='50' height='50' x='10' y='10' fill='red' filter='url(%23blur1)'
/%3E%3Crect width='50' height='50' x='40' y='40' fill='blue'
filter='url("#blur2#blur2")' /%3E%3C/svg%3E");
}
}}}

I'm not sure why I get `url("#blur2#blur2")` instead of `url("#blur2")`
but I see your point that is the result invalid. What I don't understand
is why the SVG still seems to work: I tested in Firefox, is this a Firefox
wizardry?
--
Ticket URL: <https://code.djangoproject.com/ticket/36348#comment:6>

Django

unread,
Apr 24, 2025, 4:56:32 PM4/24/25
to django-...@googlegroups.com
#36348: ManifestStaticFilesStorage breaks CSS containing data: URIs with multiple
nested url()s
-------------------------------------+-------------------------------------
Reporter: Samuel Cormier- | Owner: Samuel
Iijima | Cormier-Iijima
Type: Bug | Status: new
Component: contrib.staticfiles | Version: 5.2
Severity: Normal | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Natalia Bidart):

* cc: Adam Johnson, Claude Paroz (added)

--
Ticket URL: <https://code.djangoproject.com/ticket/36348#comment:7>

Django

unread,
Apr 24, 2025, 5:12:09 PM4/24/25
to django-...@googlegroups.com
#36348: ManifestStaticFilesStorage breaks CSS containing data: URIs with multiple
nested url()s
-------------------------------------+-------------------------------------
Reporter: Samuel Cormier- | Owner: Samuel
Iijima | Cormier-Iijima
Type: Bug | Status: new
Component: contrib.staticfiles | Version: 5.2
Severity: Normal | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 0
Needs tests: 1 | Patch needs improvement: 1
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Natalia Bidart):

* needs_better_patch: 0 => 1
* needs_tests: 0 => 1

--
Ticket URL: <https://code.djangoproject.com/ticket/36348#comment:8>

Django

unread,
Apr 24, 2025, 10:13:31 PM4/24/25
to django-...@googlegroups.com
#36348: ManifestStaticFilesStorage breaks CSS containing data: URIs with multiple
nested url()s
-------------------------------------+-------------------------------------
Reporter: Samuel Cormier- | Owner: Samuel
Iijima | Cormier-Iijima
Type: Bug | Status: new
Component: contrib.staticfiles | Version: 5.2
Severity: Normal | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 0
Needs tests: 1 | Patch needs improvement: 1
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Adam Zapletal):

* cc: Adam Zapletal (added)

--
Ticket URL: <https://code.djangoproject.com/ticket/36348#comment:9>

Django

unread,
May 10, 2025, 1:18:12 PM5/10/25
to django-...@googlegroups.com
#36348: ManifestStaticFilesStorage breaks CSS containing data: URIs with multiple
nested url()s
-------------------------------------+-------------------------------------
Reporter: Samuel Cormier- | Owner: Samuel
Iijima | Cormier-Iijima
Type: Bug | Status: new
Component: contrib.staticfiles | Version: 5.2
Severity: Normal | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Jacob Walls):

* needs_better_patch: 1 => 0
* needs_tests: 1 => 0

--
Ticket URL: <https://code.djangoproject.com/ticket/36348#comment:10>

Django

unread,
May 16, 2025, 7:35:25 AM5/16/25
to django-...@googlegroups.com
#36348: ManifestStaticFilesStorage breaks CSS containing data: URIs with multiple
nested url()s
-------------------------------------+-------------------------------------
Reporter: Samuel Cormier- | Owner: Samuel
Iijima | Cormier-Iijima
Type: Bug | Status: new
Component: contrib.staticfiles | Version: 5.2
Severity: Normal | Resolution:
Keywords: | Triage Stage: Ready for
| checkin
Has patch: 1 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Sarah Boyce):

* stage: Accepted => Ready for checkin

--
Ticket URL: <https://code.djangoproject.com/ticket/36348#comment:11>

Django

unread,
May 16, 2025, 9:56:28 AM5/16/25
to django-...@googlegroups.com
#36348: ManifestStaticFilesStorage breaks CSS containing data: URIs with multiple
nested url()s
-------------------------------------+-------------------------------------
Reporter: Samuel Cormier- | Owner: Samuel
Iijima | Cormier-Iijima
Type: Bug | Status: closed
Component: contrib.staticfiles | Version: 5.2
Severity: Normal | Resolution: fixed
Keywords: | Triage Stage: Ready for
| checkin
Has patch: 1 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Sarah Boyce <42296566+sarahboyce@…>):

* resolution: => fixed
* status: new => closed

Comment:

In [changeset:"1ba5fe19ca221663e6a1e9391dbe726bb2baaf8a" 1ba5fe19]:
{{{#!CommitTicketReference repository=""
revision="1ba5fe19ca221663e6a1e9391dbe726bb2baaf8a"
Fixed #36348 -- Fixed handling multiple nested url()s in
ManifestStaticFilesStorage.

Signed-off-by: Samuel Cormier-Iijima <sam...@cormier-iijima.com>
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/36348#comment:12>
Reply all
Reply to author
Forward
0 new messages