diff --git a/files/helpers/regex.py b/files/helpers/regex.py index 437b8b5ca..039220e3d 100644 --- a/files/helpers/regex.py +++ b/files/helpers/regex.py @@ -80,7 +80,7 @@ image_regex = re.compile("(^|\s)(https:\/\/[\w\-.#&/=\?@%;+,:]{5,250}(\.png|\.jp link_fix_regex = re.compile("(\[.*?\]\()(?!http|/)(.*?\))", flags=re.A) -css_regex = re.compile('(https?:)?\/\/[\w:~,()\-.#&\/=?@%;+]*', flags=re.I|re.A) +css_url_regex = re.compile('url\(\s*[\'"]?(.*?)[\'"]?\s*\)', flags=re.I|re.A) procoins_li = (0,2500,5000,10000,25000,50000,125000,250000) diff --git a/files/helpers/sanitize.py b/files/helpers/sanitize.py index 9f21b11f8..6a16f42d6 100644 --- a/files/helpers/sanitize.py +++ b/files/helpers/sanitize.py @@ -458,3 +458,15 @@ def normalize_url(url): url = giphy_regex.sub(r'\1.webp', url) return url + +def validate_css(css): + if '@import' in css: + return False, "@import statements not allowed." + + for i in css_url_regex.finditer(css): + url = i.group(1) + if not is_safe_url(url): + domain = tldextract.extract(url).registered_domain + return False, f"The domain '{domain}' is not allowed, please use one of these domains\n\n{approved_embed_hosts}." + + return True, "" diff --git a/files/routes/settings.py b/files/routes/settings.py index 5f0fb74fb..b1f747e90 100644 --- a/files/routes/settings.py +++ b/files/routes/settings.py @@ -599,14 +599,9 @@ def settings_profilecss_get(v): def settings_profilecss(v): profilecss = request.values.get("profilecss").strip().replace('\\', '').strip()[:4000] - - for i in css_regex.finditer(profilecss): - url = i.group(0) - if not is_safe_url(url): - domain = tldextract.extract(url).registered_domain - error = f"The domain '{domain}' is not allowed, please use one of these domains\n\n{approved_embed_hosts}." - return render_template("settings_profilecss.html", error=error, v=v) - + valid, error = validate_css(profilecss) + if not valid: + return render_template("settings_profilecss.html", error=error, v=v) v.profilecss = profilecss g.db.add(v) diff --git a/files/routes/subs.py b/files/routes/subs.py index e3dc8f85c..cb368bea7 100644 --- a/files/routes/subs.py +++ b/files/routes/subs.py @@ -352,21 +352,17 @@ def post_sub_sidebar(v, sub): @is_not_permabanned def post_sub_css(v, sub): sub = g.db.query(Sub).filter_by(name=sub.strip().lower()).one_or_none() - if not sub: abort(404) - - if not v.mods(sub.name): abort(403) - css = request.values.get('css', '').strip() + if not sub: + abort(404) + if not v.mods(sub.name): + abort(403) - for i in css_regex.finditer(css): - url = i.group(0) - if not is_safe_url(url): - domain = tldextract.extract(url).registered_domain - error = f"The domain '{domain}' is not allowed, please use one of these domains\n\n{approved_embed_hosts}." - return render_template('sub/settings.html', v=v, sidebar=sub.sidebar, sub=sub, error=error) - - + valid, error = validate_css(css) + if not valid: + return render_template('sub/settings.html', + v=v, sidebar=sub.sidebar, sub=sub, error=error) sub.css = css g.db.add(sub)