diff --git a/custom-css.php b/custom-css.php
index f186afb61642fa3e3fb3ed0dd9a766501f65670f..b8821c5ab2d46d9b32d4c6dcc14f0dd7cbea2a07 100644
--- a/custom-css.php
+++ b/custom-css.php
@@ -7,10 +7,77 @@
  * Author URI: https://autistici.org
  */
 
-// The following code is heavily inspired by the Jetpack plugin custom-css module.
-function ai_sanitize_css( $css, $args = array() ) {
+/*
+ * This plugin sanitizes the custom CSS that admins can add to their
+ * websites, by removing constructs referencing URLs that can lead to
+ * XSS (@import, url refs, etc). The point of it is to allow all
+ * admins on a multisite instance to edit CSS (not just super-admins),
+ * via something like the multisite-custom-css plugin.
+ *
+ * It uses CSSTidy to parse the custom CSS, then inspects the CSS
+ * structure and removes unwanted directives, before finally rendering
+ * the CSS again. It does so by overriding some methods in our
+ * "safecss" custom subclass of the CSSTidy optimizer.
+ *
+ * The custom CSS hook structure that invokes CSSTidy is lifted from
+ * the Jetpack plugin, modules/custom-css/custom-css-4.7.php, with the
+ * sanitization part taken from
+ * https://meta.trac.wordpress.org/changeset/2085.
+ */
+
+function ai_sanitize_urls_in_css_properties($url, $property) {
+    $property = trim($property);
+    $url = trim($url, "' \" \r \n");
+
+    // The current policy is: no URLs at all.
+    return '';
+}
+
+// Lazy load csstidy and our custom subclasses.
+function ai_safecss_class() {
+    if (class_exists('safecss')) {
+        return;
+    }
+
     require_once(__DIR__ . '/csstidy/class.csstidy.php');
 
+    class safecss extends csstidy_optimise {
+        public function subvalue() {
+            $this->sub_value = trim($this->sub_value);
+
+            if (preg_match('!^\s*(?P<url_expression>url\s*(?P<opening_paren>\(|\\0028)(?P<parenthetical_content>.*)(?P<closing_paren>\)|\\0029))(.*)$!Dis', $safecss->sub_value, $matches)) {
+                $this->sub_value = ai_sanitize_urls_in_css_properties($matches['parenthetical_content'], $safecss->property);
+
+                // Only replace the url([...]) portion of the sub_value so we don't
+                // lose things like trailing commas or !important declarations.
+                if ($this->sub_value) {
+                    $this->sub_value = str_replace($matches['url_expression'], $this->sub_value, $matches[0]);
+                }
+            }
+
+            // Strip any expressions
+            if (preg_match('!^\\s*expression!Dis', $this->sub_value)) {
+                $this->sub_value = '';
+            }
+
+            return parent::subvalue();
+        }
+
+        public function postparse() {
+            // @import rules are stripped because they can enable XSS.
+            $this->parser->import = array();
+
+            // @charset rules are stripped because manipulating the charset
+            // can allow an attacker to introduce XSS vulnerabilities by
+            // tricking the browser into interpreting the CSS as HTML.
+            $this->parser->charset = array();
+
+            return parent::postparse();
+        }
+    }
+}
+
+function ai_sanitize_css($css, $args = array()) {
     $args = wp_parse_args(
         $args,
         array(
@@ -20,9 +87,9 @@ function ai_sanitize_css( $css, $args = array() ) {
 	
     if ($args['force'] || !current_user_can('unfiltered_html')) {
         $warnings = array();
-	
-        safecss_class();
-        $csstidy           = new csstidy();
+
+        ai_safecss_class();
+        $csstidy = new csstidy();
         $csstidy->optimise = new safecss( $csstidy );
 
         $csstidy->set_cfg( 'remove_bslash', false );
@@ -54,7 +121,7 @@ function ai_sanitize_css( $css, $args = array() ) {
         $css = wp_kses_split( $css, array(), array() );
         $css = str_replace( '&gt;', '>', $css ); // kses replaces lone '>' with &gt;
         // Why both KSES and strip_tags?  Because we just added some '>'.
-        $css = strip_tags( $css ); // phpcs:ignore WordPress.WP.AlternativeFunctions.strip_tags_strip_tags -- scared to update this to wp_strip_all_tags since we're building a CSS file here.
+        $css = strip_tags( $css );
 
         if ( $css !== $prev ) {
             $warnings[] = 'kses found stuff';
@@ -63,6 +130,7 @@ function ai_sanitize_css( $css, $args = array() ) {
         $csstidy->parse( $css );
         $css = $csstidy->print->plain();
     }
+
     return $css;
 }