CSP expansion

pull/40/head
Aevann1 2022-11-30 22:03:32 +02:00
parent 836d3bfd98
commit 8b985a6ac9
39 changed files with 112 additions and 74 deletions

View File

@ -1,7 +1,7 @@
<head> <head>
<title>No Internet Connection</title> <title>No Internet Connection</title>
<meta name="viewport" content="width=500"> <meta name="viewport" content="width=500">
<style> <style nonce="{{g.nonce}}">
:root { :root {
--background: #123; --background: #123;
--primary: #238dcf; --primary: #238dcf;

View File

@ -3,7 +3,7 @@
{% set path = "assets/media/event/music" %} {% set path = "assets/media/event/music" %}
{% set song = "/" + path + "/" + listdir('files/' + path)|random() + '?v=45' %} {% set song = "/" + path + "/" + listdir('files/' + path)|random() + '?v=45' %}
{% endif %} {% endif %}
<script> <script nonce="{{g.nonce}}">
const audio = new Audio("{{song}}"); const audio = new Audio("{{song}}");
audio.loop=true; audio.loop=true;

View File

@ -2,6 +2,7 @@ import secrets
from files.helpers.const import * from files.helpers.const import *
from files.helpers.settings import get_setting from files.helpers.settings import get_setting
from files.helpers.security import generate_hash
from files.helpers.cloudflare import CLOUDFLARE_AVAILABLE from files.helpers.cloudflare import CLOUDFLARE_AVAILABLE
from files.routes.wrappers import * from files.routes.wrappers import *
from files.__main__ import app, limiter from files.__main__ import app, limiter
@ -30,6 +31,8 @@ def before_request():
if not get_setting('Bots') and request.headers.get("Authorization"): abort(403) if not get_setting('Bots') and request.headers.get("Authorization"): abort(403)
g.nonce = generate_hash(f'{time.time()}+{session.get("session_id")}')
g.webview = '; wv) ' in ua g.webview = '; wv) ' in ua
if ' firefox/' in ua: if ' firefox/' in ua:
@ -51,6 +54,31 @@ def before_request():
g.db = db_session() g.db = db_session()
CSP = {
"upgrade-insecure-requests": "",
"object-src": "'none'",
"form-action": "'self'",
"manifest-src": "'self'",
"worker-src": "'self'",
"base-uri": "'self'",
"style-src-elem": "'self' 'nonce-{nonce}'",
"script-src-elem": "'self' 'nonce-{nonce}' challenges.cloudflare.com rdrama.net",
"script-src": "'unsafe-inline'",
"frame-src": "challenges.cloudflare.com www.youtube-nocookie.com platform.twitter.com",
"connect-src": "'self' tls-use1.fpapi.io api.fpjs.io 00bb6d59-7b11-4339-b1ae-b1f1259d1316.pushnotifications.pusher.com",
"report-to": "csp",
"report-uri": "csp",
}
if not IS_LOCALHOST:
CSP["default-src"] = "https:"
CSP["img-src"] = "https: data:"
CSP_str = ''
for k, val in CSP.items():
CSP_str += f'{k} {val}; '
@app.after_request @app.after_request
def after_request(response): def after_request(response):
if response.status_code < 400: if response.status_code < 400:
@ -62,6 +90,10 @@ def after_request(response):
g.db.commit() g.db.commit()
g.db.close() g.db.close()
del g.db del g.db
response.headers.add("Report-To", {"group":"csp","max_age":10886400,"endpoints":[{"url":"/sex"}]})
response.headers.add("Content-Security-Policy", CSP_str.format(nonce=g.nonce))
return response return response

View File

@ -421,3 +421,11 @@ if not os.path.exists(f'files/templates/donate_{SITE_NAME}.html'):
@auth_desired_with_logingate @auth_desired_with_logingate
def donate(v): def donate(v):
return render_template(f'donate_{SITE_NAME}.html', v=v) return render_template(f'donate_{SITE_NAME}.html', v=v)
@app.post('/sex')
@limiter.exempt
def sex():
print('sex!', flush=True)
print(request.values.items(), flush=True)
return ''

View File

@ -67,7 +67,7 @@
</section> </section>
{% endif %} {% endif %}
<script> <script nonce="{{g.nonce}}">
function submitAddAlt(element) { function submitAddAlt(element) {
if (!element || !element.form) return; if (!element || !element.form) return;
const isLinking = element.id == 'add-alt-form-link'; const isLinking = element.id == 'add-alt-form-link';

View File

@ -73,7 +73,7 @@
</form> </form>
<style> <style nonce="{{g.nonce}}">
@media (max-width: 767.98px) { @media (max-width: 767.98px) {
table { table {
display: inline-block; display: inline-block;

View File

@ -3,7 +3,7 @@
{% block content %} {% block content %}
<script> <script nonce="{{g.nonce}}">
function unbanDomain(t, domain) { function unbanDomain(t, domain) {
postToastSwitch(t,'/admin/unban_domain/' + domain); postToastSwitch(t,'/admin/unban_domain/' + domain);
t.parentElement.parentElement.remove(); t.parentElement.parentElement.remove();

View File

@ -50,7 +50,7 @@
{% endif %} {% endif %}
{% if p.award_count("tilt", v) %} {% if p.award_count("tilt", v) %}
<style> <style nonce="{{g.nonce}}">
@keyframes post-tilt { @keyframes post-tilt {
0% {transform: rotate(0deg);} 0% {transform: rotate(0deg);}
25% {transform: rotate({{p.award_count("tilt", v)}}deg);} 25% {transform: rotate({{p.award_count("tilt", v)}}deg);}

View File

@ -7,7 +7,7 @@
{% endif %} {% endif %}
{% if p.award_count("crab", v) %} {% if p.award_count("crab", v) %}
<script> <script nonce="{{g.nonce}}">
let audio = new Audio('/assets/media/crab.mp3'); let audio = new Audio('/assets/media/crab.mp3');
audio.loop=true; audio.loop=true;
@ -20,7 +20,7 @@
</script> </script>
{% endif %} {% endif %}
<style> <style nonce="{{g.nonce}}">
.toe img { .toe img {
width: 100px !important; width: 100px !important;
height: auto !important; height: auto !important;

View File

@ -1,7 +1,7 @@
{% extends "casino/game_screen.html" %} {% extends "casino/game_screen.html" %}
{% block script %} {% block script %}
<script> <script nonce="{{g.nonce}}">
function makeBlackjackRequest(action) { function makeBlackjackRequest(action) {
const xhr = new XMLHttpRequest(); const xhr = new XMLHttpRequest();
xhr.open("post", `/casino/twentyone/${action}`); xhr.open("post", `/casino/twentyone/${action}`);
@ -236,7 +236,7 @@
{% endblock %} {% endblock %}
{% block actions %} {% block actions %}
<style> <style nonce="{{g.nonce}}">
.blackjack-cardset { .blackjack-cardset {
position: relative; position: relative;
display: flex; display: flex;

View File

@ -1,7 +1,7 @@
{% extends "default.html" %} {% extends "default.html" %}
{% block pagetitle %}{{game.capitalize()}}{% endblock %} {% block pagetitle %}{{game.capitalize()}}{% endblock %}
{% block content %} {% block content %}
<style> <style nonce="{{g.nonce}}">
.game_screen-title { .game_screen-title {
display: flex; display: flex;
align-items: center; align-items: center;
@ -27,7 +27,7 @@
} }
</style> </style>
<script type="text/javascript"> <script nonce="{{g.nonce}}">
/** /**
* This script block contains generic helper function usable across casino games: * This script block contains generic helper function usable across casino games:
* - Wagers * - Wagers
@ -233,7 +233,7 @@
{% block script %} {% endblock %} {% block script %} {% endblock %}
<style> <style nonce="{{g.nonce}}">
@keyframes drawing { @keyframes drawing {
from { from {
left: 0; left: 0;

View File

@ -1,7 +1,7 @@
{% extends "casino/game_screen.html" %} {% block result %} N/A {% endblock %} {% extends "casino/game_screen.html" %} {% block result %} N/A {% endblock %}
{% block script %} {% block script %}
<script type="text/javascript"> <script nonce="{{g.nonce}}">
if ( if (
document.readyState === "complete" || document.readyState === "complete" ||
(document.readyState !== "loading" && !document.documentElement.doScroll) (document.readyState !== "loading" && !document.documentElement.doScroll)
@ -393,7 +393,7 @@
{% endblock %} {% endblock %}
{% block screen %} {% block screen %}
<style> <style nonce="{{g.nonce}}">
.roulette-table-number { .roulette-table-number {
flex: 1; flex: 1;
height: 60px; height: 60px;

View File

@ -1,7 +1,7 @@
{% extends "casino/game_screen.html" %} {% block result %} N/A {% endblock %} {% extends "casino/game_screen.html" %} {% block result %} N/A {% endblock %}
{% block script %} {% block script %}
<script type="text/javascript"> <script nonce="{{g.nonce}}">
function pullSlots() { function pullSlots() {
const { amount, currency } = getWager(); const { amount, currency } = getWager();
@ -73,7 +73,7 @@
{% endblock %} {% endblock %}
{% block screen %} {% block screen %}
<style> <style nonce="{{g.nonce}}">
.slots_reels { .slots_reels {
display: flex; display: flex;
align-items: center; align-items: center;

View File

@ -17,7 +17,7 @@
data-avatar="{{v.profile_url}}" data-avatar="{{v.profile_url}}"
data-hat="{{v.hat_active}}"> data-hat="{{v.hat_active}}">
</div> </div>
<script>window.global = window</script> <script nonce="{{g.nonce}}">window.global = window</script>
{% if IS_LOCALHOST %} {% if IS_LOCALHOST %}
<script defer src="https://rdrama.net/assets/js/chat_done.js"></script> <script defer src="https://rdrama.net/assets/js/chat_done.js"></script>
{% else %} {% else %}

View File

@ -1,7 +1,7 @@
{%- import 'util/macros.html' as macros with context -%} {%- import 'util/macros.html' as macros with context -%}
{% if not request.headers.get("xhr") %} {% if not request.headers.get("xhr") %}
{% if comment_info %} {% if comment_info %}
<script> <script nonce="{{g.nonce}}">
if (location.hash != 'context') if (location.hash != 'context')
location.hash = 'context' location.hash = 'context'
</script> </script>
@ -238,7 +238,7 @@
{% endif %} {% endif %}
{% if c.award_count("tilt", v) %} {% if c.award_count("tilt", v) %}
<style> <style nonce="{{g.nonce}}">
@keyframes c{{c.id}}-tilt { @keyframes c{{c.id}}-tilt {
0% {transform: rotate(0deg);} 0% {transform: rotate(0deg);}
25% {transform: rotate({{c.award_count("tilt", v)}}deg);} 25% {transform: rotate({{c.award_count("tilt", v)}}deg);}
@ -816,7 +816,7 @@
<script defer src="{{'js/comments+submission_listing.js' | asset}}"></script> <script defer src="{{'js/comments+submission_listing.js' | asset}}"></script>
<script defer src="{{'js/comments.js' | asset}}"></script> <script defer src="{{'js/comments.js' | asset}}"></script>
<script> <script nonce="{{g.nonce}}">
{% if p and (not v or v.highlightcomments) %} {% if p and (not v or v.highlightcomments) %}
comments = JSON.parse(localStorage.getItem("comment-counts")) || {} comments = JSON.parse(localStorage.getItem("comment-counts")) || {}
lastCount = comments['{{p.id}}'] lastCount = comments['{{p.id}}']
@ -881,7 +881,7 @@
{% if SITE_NAME == 'rDrama' and not request.headers.get("xhr") and v and 'SamsungBrowser' not in g.agent and v.theme != 'transparent' %} {% if SITE_NAME == 'rDrama' and not request.headers.get("xhr") and v and 'SamsungBrowser' not in g.agent and v.theme != 'transparent' %}
<div id="detection" style="display:none;background-color:canvas;color-scheme:light"></div> <div id="detection" style="display:none;background-color:canvas;color-scheme:light"></div>
<script> <script nonce="{{g.nonce}}">
const detectionDiv = document.querySelector('#detection'); const detectionDiv = document.querySelector('#detection');
const isAutoDark = getComputedStyle(detectionDiv).backgroundColor != 'rgb(255, 255, 255)'; const isAutoDark = getComputedStyle(detectionDiv).backgroundColor != 'rgb(255, 255, 255)';
if (!isAutoDark) { if (!isAutoDark) {

View File

@ -5,7 +5,7 @@
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline'; connect-src 'self'; object-src 'none';"> <meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline'; connect-src 'self'; object-src 'none';">
<style> <style nonce="{{g.nonce}}">
:root{--primary:#ff66ac} :root{--primary:#ff66ac}
.mod:before { .mod:before {
content: "((("; content: "(((";

View File

@ -5,7 +5,7 @@
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline'; connect-src 'self'; object-src 'none';"> <meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline'; connect-src 'self'; object-src 'none';">
<style> <style nonce="{{g.nonce}}">
:root{--primary:#ff66ac} :root{--primary:#ff66ac}
.mod:before { .mod:before {
content: "((("; content: "(((";

View File

@ -5,7 +5,7 @@
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline'; connect-src 'self'; object-src 'none';"> <meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline'; connect-src 'self'; object-src 'none';">
<style> <style nonce="{{g.nonce}}">
:root{--primary:#ff66ac} :root{--primary:#ff66ac}
.mod:before { .mod:before {
content: "((("; content: "(((";

View File

@ -3,7 +3,7 @@
{% block pagetype %}message{% endblock %} {% block pagetype %}message{% endblock %}
{% block banner %} {% block banner %}
<style> <style nonce="{{g.nonce}}">
.shop-tabs { .shop-tabs {
padding-top: 50px; padding-top: 50px;
} }
@ -59,7 +59,7 @@
{% endblock %} {% endblock %}
{% block content %} {% block content %}
<script> <script nonce="{{g.nonce}}">
function equip_hat(t, hat_id, hat_name) { function equip_hat(t, hat_id, hat_name) {
const profile_pic_hat = document.getElementById("profile-pic-35-hat"); const profile_pic_hat = document.getElementById("profile-pic-35-hat");
function extra_actions(xhr) { function extra_actions(xhr) {

View File

@ -4,7 +4,7 @@
{%- endif -%} {%- endif -%}
<nav class="shadow-md fixed-top"> <nav class="shadow-md fixed-top">
<style> <style nonce="{{g.nonce}}">
body {padding-top: 83px !important} body {padding-top: 83px !important}
@media (max-width: 767.98px) { @media (max-width: 767.98px) {
body { body {
@ -55,7 +55,7 @@
{% if sub %} {% if sub %}
<a id="sub-name" href="/h/{{sub}}" class="font-weight-bold ml-2 flex-grow-1 mt-1" {% if sub.name|length >= 17 %}style="font-size:max(10px,1.2vw)"{% else %}style="font-size:max(10px,1.2vw)"{% endif %}>{% if not HOLE_STYLE_FLAIR %}/h/{% endif %}{{sub}}</a> <a id="sub-name" href="/h/{{sub}}" class="font-weight-bold ml-2 flex-grow-1 mt-1" {% if sub.name|length >= 17 %}style="font-size:max(10px,1.2vw)"{% else %}style="font-size:max(10px,1.2vw)"{% endif %}>{% if not HOLE_STYLE_FLAIR %}/h/{% endif %}{{sub}}</a>
{% elif has_logo %} {% elif has_logo %}
<style> <style nonce="{{g.nonce}}">
{% if SITE_NAME == 'WPD' %} {% if SITE_NAME == 'WPD' %}
@media (min-width: 1000px) { @media (min-width: 1000px) {
{% else %} {% else %}
@ -343,12 +343,12 @@
<div id="formkey" class="d-none">{{v|formkey}}</div> <div id="formkey" class="d-none">{{v|formkey}}</div>
{% endif %} {% endif %}
<script> <script nonce="{{g.nonce}}">
IMAGE_FORMATS = {{IMAGE_FORMATS|safe}}; IMAGE_FORMATS = {{IMAGE_FORMATS|safe}};
</script> </script>
{% if not v %} {% if not v %}
<style> <style nonce="{{g.nonce}}">
.pad { .pad {
padding-bottom: 7.4px; padding-bottom: 7.4px;
padding-top: 7.4px; padding-top: 7.4px;
@ -357,7 +357,7 @@
{% endif %} {% endif %}
{% if v and v.poor -%} {% if v and v.poor -%}
<style> <style nonce="{{g.nonce}}">
* :not(img[src="/i/hand.webp"] + img, img.golden, img[g], img[glow], .live-circle) { * :not(img[src="/i/hand.webp"] + img, img.golden, img[g], img[glow], .live-circle) {
animation: unset !important; animation: unset !important;
} }

View File

@ -62,7 +62,7 @@
{% block navbar %} {% block navbar %}
<div class="d-flex align-items-center"> <div class="d-flex align-items-center">
{% if SITE_NAME != 'WPD' and not sub %} {% if SITE_NAME != 'WPD' and not sub %}
<style> <style nonce="{{g.nonce}}">
@media (max-width: 427px) { @media (max-width: 427px) {
.smol-fp { .smol-fp {
font-size: 2.7vw; font-size: 2.7vw;
@ -171,7 +171,7 @@
<div class="d-none" id="strid">{{SITE}}{{v.id}}</div> <div class="d-none" id="strid">{{SITE}}{{v.id}}</div>
<div class="d-none" id="pusherid">{{PUSHER_ID}}</div> <div class="d-none" id="pusherid">{{PUSHER_ID}}</div>
<script defer src="{{'js/vendor/pusher.js' | asset}}"></script> <script defer src="{{'js/vendor/pusher.js' | asset}}"></script>
<script> <script nonce="{{g.nonce}}">
if (typeof Android != 'undefined') { if (typeof Android != 'undefined') {
Android.Subscribe('{{SITE}}{{v.id}}'); Android.Subscribe('{{SITE}}{{v.id}}');
} }
@ -179,7 +179,7 @@
{% endif %} {% endif %}
{% if request.path == '/' and not g.webview and time.time() > session.get('tooltip_last_dismissed',0)+86400*30 %} {% if request.path == '/' and not g.webview and time.time() > session.get('tooltip_last_dismissed',0)+86400*30 %}
<style> <style nonce="{{g.nonce}}">
.dismiss-beg { .dismiss-beg {
color: #919191; color: #919191;
float: left; float: left;
@ -193,7 +193,7 @@
<div id="mobile-prompt" data-bs-toggle="tooltip" data-bs-container="#mobile-prompt-container" data-bs-placement="top" data-bs-trigger="click" data-bs-html="true" title="<i class='dismiss-beg fas fa-x'></i>Click me to install the {{SITE_NAME}} mobile app!"></div> <div id="mobile-prompt" data-bs-toggle="tooltip" data-bs-container="#mobile-prompt-container" data-bs-placement="top" data-bs-trigger="click" data-bs-html="true" title="<i class='dismiss-beg fas fa-x'></i>Click me to install the {{SITE_NAME}} mobile app!"></div>
</div> </div>
<script> <script nonce="{{g.nonce}}">
if (!window.matchMedia('(display-mode: minimal-ui)')['matches']) { if (!window.matchMedia('(display-mode: minimal-ui)')['matches']) {
if (window.innerWidth <= 737) { if (window.innerWidth <= 737) {
document.addEventListener('DOMContentLoaded', function() { document.addEventListener('DOMContentLoaded', function() {
@ -214,7 +214,7 @@
} }
</script> </script>
<style> <style nonce="{{g.nonce}}">
#mobile-prompt + .bs-tooltip-bottom { #mobile-prompt + .bs-tooltip-bottom {
transform: None !important; transform: None !important;
inset: 0px 0px auto auto !important; inset: 0px 0px auto auto !important;
@ -224,7 +224,7 @@
{% if request.path == '/' and v and FP %} {% if request.path == '/' and v and FP %}
{% if not v.fp %} {% if not v.fp %}
<script> <script nonce="{{g.nonce}}">
function fp(fp) { function fp(fp) {
const xhr = new XMLHttpRequest(); const xhr = new XMLHttpRequest();
xhr.open("POST", '/fp/'+fp); xhr.open("POST", '/fp/'+fp);

View File

@ -1,7 +1,7 @@
{% extends "default.html" %} {% extends "default.html" %}
{% block pagetitle %}Live{% endblock %} {% block pagetitle %}Live{% endblock %}
{% block content %} {% block content %}
<style> <style nonce="{{g.nonce}}">
tr:hover { tr:hover {
border: 2.5px solid var(--primary); border: 2.5px solid var(--primary);
} }
@ -12,7 +12,7 @@
width: 130px; width: 130px;
} }
</style> </style>
<script> <script nonce="{{g.nonce}}">
function go_to(e, link) { function go_to(e, link) {
if (!e.target.classList.contains('remove-streamer')) if (!e.target.classList.contains('remove-streamer'))
window.open(link, '_blank'); window.open(link, '_blank');

View File

@ -2,22 +2,22 @@
{% block pagetitle %}Moderation Log{% endblock %} {% block pagetitle %}Moderation Log{% endblock %}
{% block content %} {% block content %}
{% if v %} {% if v %}
<style>:root{--primary:#{{v.themecolor}}}</style> <style nonce="{{g.nonce}}">:root{--primary:#{{v.themecolor}}}</style>
<link rel="stylesheet" href="{{'css/main.css' | asset}}"> <link rel="stylesheet" href="{{'css/main.css' | asset}}">
<link rel="stylesheet" href="{{('css/'~v.theme~'.css') | asset}}"> <link rel="stylesheet" href="{{('css/'~v.theme~'.css') | asset}}">
{% if v.agendaposter %} {% if v.agendaposter %}
<style> <style nonce="{{g.nonce}}">
html { html {
cursor:url('/i/dildo.webp?v=2000'), auto; cursor:url('/i/dildo.webp?v=2000'), auto;
} }
</style> </style>
{% elif v.css %} {% elif v.css %}
<style> <style nonce="{{g.nonce}}">
{{v.css | safe}} {{v.css | safe}}
</style> </style>
{% endif %} {% endif %}
{% else %} {% else %}
<style>:root{--primary:#{{DEFAULT_COLOR}}</style> <style nonce="{{g.nonce}}">:root{--primary:#{{DEFAULT_COLOR}}</style>
<link rel="stylesheet" href="{{'css/main.css' | asset}}"> <link rel="stylesheet" href="{{'css/main.css' | asset}}">
<link rel="stylesheet" href="{{('css/'~DEFAULT_THEME~'.css') | asset}}"> <link rel="stylesheet" href="{{('css/'~DEFAULT_THEME~'.css') | asset}}">
{% endif %} {% endif %}

View File

@ -1,6 +1,6 @@
<div id="form" class="d-none"></div> <div id="form" class="d-none"></div>
<div class="modal fade" id="emojiModal" tabindex="-1" role="dialog" aria-labelledby="emojiModalTitle" aria-hidden="true"> <div class="modal fade" id="emojiModal" tabindex="-1" role="dialog" aria-labelledby="emojiModalTitle" aria-hidden="true">
<style> <style nonce="{{g.nonce}}">
#emojiTabs {height: 80%;} #emojiTabs {height: 80%;}
@media (max-width: 650px) { @media (max-width: 650px) {
#emojiTabs {height: 100%;} #emojiTabs {height: 100%;}
@ -70,7 +70,7 @@
I've took the liberty to populate this tab with a selection of Anton's emojis 😽. Next time you'll find the ones you used the most in there 📚 I've took the liberty to populate this tab with a selection of Anton's emojis 😽. Next time you'll find the ones you used the most in there 📚
</div> </div>
<div id="tab-content" class="tab-content d-flex flex-wrap py-3 pl-2" hidden> <div id="tab-content" class="tab-content d-flex flex-wrap py-3 pl-2" hidden>
<style> <style nonce="{{g.nonce}}">
.emoji2 { .emoji2 {
/*background: None!important;*/ /*background: None!important;*/
width:60px; width:60px;

View File

@ -152,7 +152,7 @@
</ul> </ul>
</nav> </nav>
{% endif %} {% endif %}
<style> <style nonce="{{g.nonce}}">
.comment { .comment {
margin-top: 0.3rem; margin-top: 0.3rem;
} }

View File

@ -42,7 +42,7 @@
</div> </div>
</div> </div>
<script> <script nonce="{{g.nonce}}">
document.addEventListener('DOMContentLoaded', function() { document.addEventListener('DOMContentLoaded', function() {
for (const x of ['css','profilecss']) { for (const x of ['css','profilecss']) {
const ta = document.getElementById(`${x}-textarea`); const ta = document.getElementById(`${x}-textarea`);

View File

@ -1,7 +1,7 @@
{% extends "settings.html" %} {% extends "settings.html" %}
{% block pagetitle %}Personal Settings{% endblock %} {% block pagetitle %}Personal Settings{% endblock %}
{% block content %} {% block content %}
<style> <style nonce="{{g.nonce}}">
.bg-image { .bg-image {
padding: 0.25rem; padding: 0.25rem;
width: 15rem; width: 15rem;
@ -261,7 +261,7 @@
{% include "modals/gif.html" %} {% include "modals/gif.html" %}
{% if v.flairchanged %} {% if v.flairchanged %}
<script> <script nonce="{{g.nonce}}">
document.addEventListener('DOMContentLoaded', function() { document.addEventListener('DOMContentLoaded', function() {
const date = formatDate(new Date({{v.flairchanged}}*1000)); const date = formatDate(new Date({{v.flairchanged}}*1000));
const text = ` - Your flair has been locked until ${date}`; const text = ` - Your flair has been locked until ${date}`;
@ -308,7 +308,7 @@
{{permanent_filter_modal('profanityreplacer', '/settings/personal', 'profanityreplacer', 'Profanity Replacer', 'Soapy-Mouthed Angel')}} {{permanent_filter_modal('profanityreplacer', '/settings/personal', 'profanityreplacer', 'Profanity Replacer', 'Soapy-Mouthed Angel')}}
{%- endif %} {%- endif %}
{% if FEATURES['USERS_PERMANENT_WORD_FILTERS'] -%} {% if FEATURES['USERS_PERMANENT_WORD_FILTERS'] -%}
<script> <script nonce="{{g.nonce}}">
document.addEventListener("DOMContentLoaded", function (event) { document.addEventListener("DOMContentLoaded", function (event) {
const sr_toggle = document.getElementById("slurreplacer"); const sr_toggle = document.getElementById("slurreplacer");
const sr_link = document.getElementById('slurreplacer-perma-link'); const sr_link = document.getElementById('slurreplacer-perma-link');

View File

@ -8,7 +8,7 @@
{% block pagetitle %}Shop{% endblock %} {% block pagetitle %}Shop{% endblock %}
{% block pagetype %}message{% endblock %} {% block pagetype %}message{% endblock %}
{% block banner %} {% block banner %}
<style> <style nonce="{{g.nonce}}">
.shop-tabs { .shop-tabs {
padding-top: 50px; padding-top: 50px;
} }

View File

@ -2,7 +2,7 @@
{% block pagetitle %}/h/{{sub}} Mods{% endblock %} {% block pagetitle %}/h/{{sub}} Mods{% endblock %}
{% block content %} {% block content %}
<script> <script nonce="{{g.nonce}}">
function removeMod(e) { function removeMod(e) {
sendFormXHR(e, sendFormXHR(e,
() => { () => {

View File

@ -8,7 +8,7 @@
{% endblock %} {% endblock %}
{% block pagetype %}thread{% endblock %} {% block pagetype %}thread{% endblock %}
{% block head_final %} {% block head_final %}
<style> <style nonce="{{g.nonce}}">
body > .container { body > .container {
padding-left: 20px !important; padding-left: 20px !important;
padding-right: 20px !important; padding-right: 20px !important;
@ -411,7 +411,7 @@
</div> </div>
{% if offset %} {% if offset %}
<script> <script nonce="{{g.nonce}}">
function viewmore(pid,sort,offset,ids) { function viewmore(pid,sort,offset,ids) {
btn = document.getElementById("viewbtn"); btn = document.getElementById("viewbtn");
btn.disabled = true; btn.disabled = true;
@ -492,7 +492,7 @@
{% include "comments.html" %} {% include "comments.html" %}
{% endif %} {% endif %}
<script> <script nonce="{{g.nonce}}">
{% if not v or v.highlightcomments %} {% if not v or v.highlightcomments %}
document.addEventListener('DOMContentLoaded', function() { document.addEventListener('DOMContentLoaded', function() {
showNewCommentCounts('{{p.id}}', {{p.comment_count}}) showNewCommentCounts('{{p.id}}', {{p.comment_count}})
@ -509,7 +509,7 @@
</script> </script>
{% if success %} {% if success %}
<script> <script nonce="{{g.nonce}}">
history.pushState(null, null, '{{p.permalink}}'); history.pushState(null, null, '{{p.permalink}}');
localStorage.setItem("post-title", "") localStorage.setItem("post-title", "")
localStorage.setItem("post-text", "") localStorage.setItem("post-text", "")
@ -526,7 +526,7 @@
{% endif %} {% endif %}
{% if fart and not (v and v.has_badge(128)) %} {% if fart and not (v and v.has_badge(128)) %}
<script> <script nonce="{{g.nonce}}">
fart = Math.floor(Math.random() * 5) + 1 fart = Math.floor(Math.random() * 5) + 1
let audio = new Audio(`/assets/images/${fart}.webp`); let audio = new Audio(`/assets/images/${fart}.webp`);

View File

@ -75,7 +75,7 @@
</div> </div>
{% if offset %} {% if offset %}
<script> <script nonce="{{g.nonce}}">
function viewmore(pid,sort,offset,ids) { function viewmore(pid,sort,offset,ids) {
btn = document.getElementById("viewbtn"); btn = document.getElementById("viewbtn");
btn.disabled = true; btn.disabled = true;

View File

@ -223,7 +223,7 @@
</div> </div>
{% endif %} {% endif %}
<script> <script nonce="{{g.nonce}}">
{% if not v or v.highlightcomments %} {% if not v or v.highlightcomments %}
document.addEventListener('DOMContentLoaded', function() { document.addEventListener('DOMContentLoaded', function() {
showNewCommentCounts({{p.id}}, {{p.comment_count}}) showNewCommentCounts({{p.id}}, {{p.comment_count}})

View File

@ -113,7 +113,7 @@
</div> </div>
{% endblock %} {% endblock %}
{% if request.path == '/submit' %} {% if request.path == '/submit' %}
<script> <script nonce="{{g.nonce}}">
let sub = document.getElementById('sub') let sub = document.getElementById('sub')
if (sub) sub.value = localStorage.getItem("sub") if (sub) sub.value = localStorage.getItem("sub")
</script> </script>

View File

@ -67,7 +67,7 @@
</div> </div>
</div> </div>
<script> <script nonce="{{g.nonce}}">
document.onpaste = function(event) { document.onpaste = function(event) {
files = structuredClone(event.clipboardData.files); files = structuredClone(event.clipboardData.files);

View File

@ -2,7 +2,7 @@
{% block pagetitle %}Submit Marseys{% endblock %} {% block pagetitle %}Submit Marseys{% endblock %}
{% block pagetype %}message{% endblock %} {% block pagetype %}message{% endblock %}
{% block content %} {% block content %}
<style> <style nonce="{{g.nonce}}">
input:not(.btn) { input:not(.btn) {
text-transform: lowercase; text-transform: lowercase;
} }
@ -69,7 +69,7 @@
</div> </div>
</div> </div>
<script> <script nonce="{{g.nonce}}">
document.onpaste = function(event) { document.onpaste = function(event) {
files = structuredClone(event.clipboardData.files); files = structuredClone(event.clipboardData.files);

View File

@ -61,7 +61,7 @@
</div> </div>
</div> </div>
<script> <script nonce="{{g.nonce}}">
document.onpaste = function(event) { document.onpaste = function(event) {
files = structuredClone(event.clipboardData.files); files = structuredClone(event.clipboardData.files);

View File

@ -12,7 +12,7 @@
<script defer src="{{'js/vendor/bootstrap.js' | asset}}"></script> <script defer src="{{'js/vendor/bootstrap.js' | asset}}"></script>
<script defer src="{{'js/core.js' | asset}}"></script> <script defer src="{{'js/core.js' | asset}}"></script>
<script> <script nonce="{{g.nonce}}">
if (window.matchMedia('(display-mode: minimal-ui)')['matches']) { if (window.matchMedia('(display-mode: minimal-ui)')['matches']) {
const links = document.querySelectorAll('a[data-target="t"]'); const links = document.querySelectorAll('a[data-target="t"]');
for (const link of links) { for (const link of links) {
@ -108,9 +108,9 @@
<link rel="stylesheet" href="{{'css/main.css' | asset}}"> <link rel="stylesheet" href="{{'css/main.css' | asset}}">
<link id="favicon" rel="icon" type="image/webp" href="/icon.webp?v=1"> <link id="favicon" rel="icon" type="image/webp" href="/icon.webp?v=1">
{% if v %} {% if v %}
<style>:root{--primary:#{{v.themecolor}}}</style> <style nonce="{{g.nonce}}">:root{--primary:#{{v.themecolor}}}</style>
{% if v.agendaposter %} {% if v.agendaposter %}
<style> <style nonce="{{g.nonce}}">
html { html {
cursor:url('/i/dildo.webp?v=2000'), auto; cursor:url('/i/dildo.webp?v=2000'), auto;
} }
@ -119,12 +119,12 @@
{% if include_user_css and not EVENT_STYLES %} {% if include_user_css and not EVENT_STYLES %}
<link rel="stylesheet" href="{{('css/'~v.theme~'.css') | asset}}"> <link rel="stylesheet" href="{{('css/'~v.theme~'.css') | asset}}">
{% if v.css and not request.path.startswith('/settings/css') %} {% if v.css and not request.path.startswith('/settings/css') %}
<style> <style nonce="{{g.nonce}}">
{{v.css | safe}} {{v.css | safe}}
</style> </style>
{% endif %} {% endif %}
{% if v.themecolor == '30409f' %} {% if v.themecolor == '30409f' %}
<style> <style nonce="{{g.nonce}}">
p a { p a {
color: #2a96f3; color: #2a96f3;
} }
@ -168,7 +168,7 @@
{% endif %} {% endif %}
{% if background %} {% if background %}
<style> <style nonce="{{g.nonce}}">
body { body {
background:url("/i/backgrounds/{{background}}.webp?v=4") center center fixed; background:url("/i/backgrounds/{{background}}.webp?v=4") center center fixed;
background-color: var(--background); background-color: var(--background);
@ -181,7 +181,7 @@
{% endmacro %} {% endmacro %}
{% macro default_theme() %} {% macro default_theme() %}
<style>:root{--primary:#{{DEFAULT_COLOR}}}</style> <style nonce="{{g.nonce}}">:root{--primary:#{{DEFAULT_COLOR}}}</style>
<link rel="stylesheet" href="{{('css/'~DEFAULT_THEME~'.css') | asset}}"> <link rel="stylesheet" href="{{('css/'~DEFAULT_THEME~'.css') | asset}}">
{% endmacro %} {% endmacro %}

View File

@ -5,7 +5,6 @@ add_header Referrer-Policy "same-origin";
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"; add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload";
add_header X-Frame-Options "deny"; add_header X-Frame-Options "deny";
add_header X-Content-Type-Options "nosniff"; add_header X-Content-Type-Options "nosniff";
add_header Content-Security-Policy "script-src 'self' 'unsafe-inline' challenges.cloudflare.com; connect-src 'self' tls-use1.fpapi.io api.fpjs.io 00bb6d59-7b11-4339-b1ae-b1f1259d1316.pushnotifications.pusher.com; object-src 'none';";
sendfile on; sendfile on;
sendfile_max_chunk 1m; sendfile_max_chunk 1m;

View File

@ -8,7 +8,6 @@ server {
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"; add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload";
add_header X-Frame-Options "deny"; add_header X-Frame-Options "deny";
add_header X-Content-Type-Options "nosniff"; add_header X-Content-Type-Options "nosniff";
add_header Content-Security-Policy "script-src 'self' 'unsafe-inline' challenges.cloudflare.com rdrama.net; connect-src 'self' tls-use1.fpapi.io api.fpjs.io 00bb6d59-7b11-4339-b1ae-b1f1259d1316.pushnotifications.pusher.com; object-src 'none';";
location / { location / {
proxy_pass http://localhost:5000/; proxy_pass http://localhost:5000/;