Allowlist validation for operator-supplied values that are embedded in CSS.
A settings field that ends up inside a stylesheet is not ordinary text: the
surrounding <style> element is parsed as raw character data, so HTML
escaping does not apply there and a value carrying </style> closes the
element and starts a new one. That turned the auth-page background colour —
a free-text field reachable by any holder of the settings permission — into
stored XSS served to every anonymous visitor of the login page.
Both functions here are allowlists that fail to "", not sanitisers that
attempt repair. A value that is not recognisably a colour or a URL is dropped
entirely, because guessing at what an unrecognised value meant is how
filters get bypassed.
Usage
iex> PhoenixKit.Utils.CssValue.color("#1e293b")
"#1e293b"
iex> PhoenixKit.Utils.CssValue.color("linear-gradient(135deg, #667eea 0%, #764ba2 100%)")
"linear-gradient(135deg, #667eea 0%, #764ba2 100%)"
iex> PhoenixKit.Utils.CssValue.color("red; } </style><script>alert(1)</script>")
""
iex> PhoenixKit.Utils.CssValue.url("/file/018e/original/ab12")
"/file/018e/original/ab12"
iex> PhoenixKit.Utils.CssValue.url("x'); } </style><script>alert(1)</script>")
""
Summary
Functions
Returns value when it is a safe CSS colour, colour function or gradient,
otherwise "".
Returns value when it is safe to place inside a CSS url('…') token,
otherwise "".
Functions
Returns value when it is a safe CSS colour, colour function or gradient,
otherwise "".
Accepts what the background-colour setting is actually for — hex colours,
rgb() / rgba() / hsl() / hsla(), CSS named colours, and
linear-gradient() / radial-gradient() — and refuses everything else.
Returns value when it is safe to place inside a CSS url('…') token,
otherwise "".
Only same-origin absolute paths and http/https URLs are accepted. The
application generates these from a stored file uuid, so this is a guard
against a malformed or crafted uuid reaching the stylesheet, not against an
operator typing a URL.