From 110278d87f863bf477fd19db846e149a3497c116 Mon Sep 17 00:00:00 2001 From: TLSM <104547575+TLSM@users.noreply.github.com> Date: Thu, 5 May 2022 03:57:34 -0400 Subject: [PATCH 1/3] Add typekit to approved hosts. (#243) --- files/helpers/const.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/files/helpers/const.py b/files/helpers/const.py index b69bcd1892..9d0f204cb2 100644 --- a/files/helpers/const.py +++ b/files/helpers/const.py @@ -864,7 +864,8 @@ approved_embed_hosts = [ 'deviantart.com', 'deviantart.net', 'googleapis.com', - 'bing.com' + 'bing.com', + 'typekit.net', ] hosts = "|".join(approved_embed_hosts).replace('.','\.') From a0cfc7bf1c814279618e1060047fd863eb9fffb1 Mon Sep 17 00:00:00 2001 From: TLSM <104547575+TLSM@users.noreply.github.com> Date: Thu, 5 May 2022 04:46:20 -0400 Subject: [PATCH 2/3] Add admin status git revision. (#244) Adds a line in admin_home which displays the currently active git revision. Current methodology is via manually parsing files in .git. Consider revising if the application ever has access to `git` shell, which would obviate some minor security concerns around directory traversal attacks. --- files/routes/admin.py | 23 ++++++++++++++++++++++- files/templates/admin/admin_home.html | 7 ++++++- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/files/routes/admin.py b/files/routes/admin.py index d640a2b469..67d3aa463e 100644 --- a/files/routes/admin.py +++ b/files/routes/admin.py @@ -1,4 +1,5 @@ import time +import re from os import remove from PIL import Image as IMAGE @@ -520,8 +521,28 @@ def admin_home(v): else: response = requests.get(f'https://api.cloudflare.com/client/v4/zones/{CF_ZONE}/settings/security_level', headers=CF_HEADERS, timeout=5).json()['result']['value'] under_attack = response == 'under_attack' - return render_template("admin/admin_home.html", v=v, under_attack=under_attack, site_settings=app.config['SETTINGS']) + gitref = admin_git_head() + + return render_template("admin/admin_home.html", v=v, + under_attack=under_attack, + site_settings=app.config['SETTINGS'], + gitref=gitref) +def admin_git_head(): + short_len = 12 + # Note: doing zero sanitization. Git branch names are extremely permissive. + # However, they forbid '..', so I don't see an obvious dir traversal attack. + # Also, a malicious branch name would mean someone already owned the server + # or repo, so I think this isn't a weak link. + try: + with open('.git/HEAD') as head_f: + head_txt = head_f.read() + head_path = re.match('ref: (refs/.+)', head_txt).group(1) + with open('.git/' + head_path) as ref_f: + gitref = ref_f.read()[0:short_len] + except: + return '' + return gitref @app.post("/admin/site_settings/") @admin_level_required(3) diff --git a/files/templates/admin/admin_home.html b/files/templates/admin/admin_home.html index 455845e284..eae08bb846 100644 --- a/files/templates/admin/admin_home.html +++ b/files/templates/admin/admin_home.html @@ -85,7 +85,12 @@ - + {% endif %} +

Server Status

+
+ Live Revision: {{ gitref }}
+
+ {% endblock %} \ No newline at end of file From 1137d56de7bba19ad5266fab5b1e273adb246d8f Mon Sep 17 00:00:00 2001 From: TLSM <104547575+TLSM@users.noreply.github.com> Date: Thu, 5 May 2022 16:47:13 -0400 Subject: [PATCH 3/3] Disable chudtexting in quotes. (#245) Chose to split text into lines because Python regex supports neither variable-width nor infinite-width negative lookbehinds. This precludes a simple pure regex solution. Since all replacements are done at the word level, this has no obvious ill effects. --- files/helpers/const.py | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/files/helpers/const.py b/files/helpers/const.py index 9d0f204cb2..57c0609ced 100644 --- a/files/helpers/const.py +++ b/files/helpers/const.py @@ -781,6 +781,7 @@ slur_regex = re.compile(f"({single_words})(?![^<]*>)", flags=re.I|re.A) slur_regex_upper = re.compile(f"({single_words.upper()})(?![^<]*>)", flags=re.A) torture_regex = re.compile('(^|\s)(i|me) ', flags=re.I|re.A) torture_regex2 = re.compile("(^|\s)i'm ", flags=re.I|re.A) +torture_regex_exclude = re.compile('^\s*>', flags=re.A) def sub_matcher(match): return SLURS[match.group(0).lower()] @@ -795,11 +796,17 @@ def censor_slurs(body, logged_user): return body def torture_ap(body, username): - for k, l in AJ_REPLACEMENTS.items(): - body = body.replace(k, l) - body = torture_regex.sub(rf'\1@{username} ', body) - body = torture_regex2.sub(rf'\1@{username} is ', body) - return body + lines = body.splitlines(keepends=True) + + for i in range(len(lines)): + if torture_regex_exclude.match(lines[i]): + continue + for k, l in AJ_REPLACEMENTS.items(): + lines[i] = lines[i].replace(k, l) + lines[i] = torture_regex.sub(rf'\1@{username} ', lines[i]) + lines[i] = torture_regex2.sub(rf'\1@{username} is ', lines[i]) + + return ''.join(lines) YOUTUBE_KEY = environ.get("YOUTUBE_KEY", "").strip()