mirror of
https://github.com/bunkerity/bunkerweb
synced 2026-05-24 09:28:37 +00:00
Update script tags with nonce attribute
This commit is contained in:
parent
c8bc2b5eeb
commit
70208d1d01
7 changed files with 70 additions and 49 deletions
|
|
@ -199,6 +199,7 @@ try:
|
|||
TO_FLASH=[],
|
||||
DARK_MODE=False,
|
||||
CURRENT_TOTP_TOKEN=None,
|
||||
SCRIPT_NONCE=sha256(urandom(32)).hexdigest(),
|
||||
)
|
||||
except FileNotFoundError as e:
|
||||
app.logger.error(repr(e), e.filename)
|
||||
|
|
@ -288,10 +289,32 @@ def manage_bunkerweb(method: str, *args, operation: str = "reloads", is_draft: b
|
|||
app.config["RELOADING"] = False
|
||||
|
||||
|
||||
@app.before_request
|
||||
def generate_nonce():
|
||||
app.config["SCRIPT_NONCE"] = sha256(urandom(32)).hexdigest()
|
||||
|
||||
|
||||
@app.context_processor
|
||||
def inject_variables():
|
||||
return dict(
|
||||
dark_mode=app.config["DARK_MODE"],
|
||||
script_nonce=app.config["SCRIPT_NONCE"],
|
||||
is_pro_version=PRO_VERSION,
|
||||
plugins_pro=PRO_PLUGINS_LIST,
|
||||
)
|
||||
|
||||
|
||||
@app.after_request
|
||||
def set_csp_header(response):
|
||||
"""Set the Content-Security-Policy header to prevent XSS attacks."""
|
||||
response.headers["Content-Security-Policy"] = "object-src 'none'; frame-ancestors 'self'; default-src 'self'"
|
||||
response.headers["Content-Security-Policy"] = (
|
||||
"object-src 'none';"
|
||||
+ " frame-ancestors 'self';"
|
||||
+ " default-src 'self' https://www.bunkerweb.io https://assets.bunkerity.com;"
|
||||
+ f" script-src 'self' 'nonce-{app.config['SCRIPT_NONCE']}';"
|
||||
+ " style-src 'self' 'unsafe-inline';"
|
||||
+ " img-src 'self' data: https://assets.bunkerity.com;"
|
||||
)
|
||||
return response
|
||||
|
||||
|
||||
|
|
@ -483,7 +506,7 @@ def totp():
|
|||
if not current_user.is_two_factor_enabled or session.get("totp_validated", False):
|
||||
return redirect(url_for("home"))
|
||||
|
||||
return render_template("totp.html", dark_mode=app.config["DARK_MODE"])
|
||||
return render_template("totp.html")
|
||||
|
||||
|
||||
@app.route("/home")
|
||||
|
|
@ -542,9 +565,6 @@ def home():
|
|||
services_ui_count=services_ui_count,
|
||||
services_autoconf_count=services_autoconf_count,
|
||||
username=current_user.get_id(),
|
||||
dark_mode=app.config["DARK_MODE"],
|
||||
is_pro_version=PRO_VERSION,
|
||||
plugins_pro=PRO_PLUGINS_LIST,
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -642,7 +662,11 @@ def account():
|
|||
app.config["CURRENT_TOTP_TOKEN"] = secret_token
|
||||
|
||||
return render_template(
|
||||
"account.html", username=current_user.get_id(), is_totp=current_user.is_two_factor_enabled, secret_token=secret_token, totp_qr_image=totp_qr_image, dark_mode=app.config["DARK_MODE"], is_pro_version=PRO_VERSION, plugins_pro=PRO_PLUGINS_LIST
|
||||
"account.html",
|
||||
username=current_user.get_id(),
|
||||
is_totp=current_user.is_two_factor_enabled,
|
||||
secret_token=secret_token,
|
||||
totp_qr_image=totp_qr_image,
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -685,7 +709,7 @@ def instances():
|
|||
|
||||
# Display instances
|
||||
instances = app.config["INSTANCES"].get_instances()
|
||||
return render_template("instances.html", title="Instances", instances=instances, username=current_user.get_id(), dark_mode=app.config["DARK_MODE"], is_pro_version=PRO_VERSION, plugins_pro=PRO_PLUGINS_LIST)
|
||||
return render_template("instances.html", title="Instances", instances=instances, username=current_user.get_id())
|
||||
|
||||
|
||||
@app.route("/services", methods=["GET", "POST"])
|
||||
|
|
@ -807,9 +831,6 @@ def services():
|
|||
for service in services
|
||||
],
|
||||
username=current_user.get_id(),
|
||||
dark_mode=app.config["DARK_MODE"],
|
||||
is_pro_version=PRO_VERSION,
|
||||
plugins_pro=PRO_PLUGINS_LIST,
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -866,7 +887,7 @@ def global_config():
|
|||
)
|
||||
|
||||
# Display global config
|
||||
return render_template("global_config.html", username=current_user.get_id(), dark_mode=app.config["DARK_MODE"], is_pro_version=PRO_VERSION, plugins_pro=PRO_PLUGINS_LIST)
|
||||
return render_template("global_config.html", username=current_user.get_id())
|
||||
|
||||
|
||||
@app.route("/configs", methods=["GET", "POST"])
|
||||
|
|
@ -960,9 +981,6 @@ def configs():
|
|||
)
|
||||
],
|
||||
username=current_user.get_id(),
|
||||
dark_mode=app.config["DARK_MODE"],
|
||||
is_pro_version=PRO_VERSION,
|
||||
plugins_pro=PRO_PLUGINS_LIST,
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -1205,7 +1223,11 @@ def plugins():
|
|||
plugins_internal += 1
|
||||
|
||||
return render_template(
|
||||
"plugins.html", plugins=plugins, plugins_internal=plugins_internal, plugins_external=plugins_external, username=current_user.get_id(), dark_mode=app.config["DARK_MODE"], is_pro_version=PRO_VERSION, plugins_pro=PRO_PLUGINS_LIST
|
||||
"plugins.html",
|
||||
plugins=plugins,
|
||||
plugins_internal=plugins_internal,
|
||||
plugins_external=plugins_external,
|
||||
username=current_user.get_id(),
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -1369,15 +1391,12 @@ def custom_plugin(plugin: str):
|
|||
|
||||
return render_template(
|
||||
Environment(loader=FileSystemLoader(join(sep, "usr", "share", "bunkerweb", "ui", "templates") + "/")).from_string(page.decode("utf-8")),
|
||||
dark_mode=app.config["DARK_MODE"],
|
||||
username=current_user.get_id(),
|
||||
current_endpoint=plugin,
|
||||
plugin=curr_plugin,
|
||||
is_used=is_used,
|
||||
is_metrics=is_metrics_on,
|
||||
**app.jinja_env.globals,
|
||||
is_pro_version=PRO_VERSION,
|
||||
plugins_pro=PRO_PLUGINS_LIST,
|
||||
)
|
||||
|
||||
module = db.get_plugin_actions(plugin)
|
||||
|
|
@ -1448,16 +1467,13 @@ def cache():
|
|||
)
|
||||
],
|
||||
username=current_user.get_id(),
|
||||
dark_mode=app.config["DARK_MODE"],
|
||||
is_pro_version=PRO_VERSION,
|
||||
plugins_pro=PRO_PLUGINS_LIST,
|
||||
)
|
||||
|
||||
|
||||
@app.route("/logs", methods=["GET"])
|
||||
@login_required
|
||||
def logs():
|
||||
return render_template("logs.html", instances=app.config["INSTANCES"].get_instances(), username=current_user.get_id(), dark_mode=app.config["DARK_MODE"], is_pro_version=PRO_VERSION, plugins_pro=PRO_PLUGINS_LIST)
|
||||
return render_template("logs.html", instances=app.config["INSTANCES"].get_instances(), username=current_user.get_id())
|
||||
|
||||
|
||||
@app.route("/logs/local", methods=["GET"])
|
||||
|
|
@ -1703,7 +1719,12 @@ def reports():
|
|||
top_code = ([k for k, v in codes.items() if v == max(codes.values())] or [""])[0]
|
||||
|
||||
return render_template(
|
||||
"reports.html", reports=reports, total_reports=total_reports, top_code=top_code, top_reason=top_reason, username=current_user.get_id(), dark_mode=app.config["DARK_MODE"], is_pro_version=PRO_VERSION, plugins_pro=PRO_PLUGINS_LIST
|
||||
"reports.html",
|
||||
reports=reports,
|
||||
total_reports=total_reports,
|
||||
top_code=top_code,
|
||||
top_reason=top_reason,
|
||||
username=current_user.get_id(),
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -1891,13 +1912,13 @@ def bans():
|
|||
|
||||
top_reason = ([k for k, v in reasons.items() if v == max(reasons.values())] or [""])[0]
|
||||
|
||||
return render_template("bans.html", bans=bans, top_reason=top_reason, username=current_user.get_id(), dark_mode=app.config["DARK_MODE"], is_pro_version=PRO_VERSION, plugins_pro=PRO_PLUGINS_LIST)
|
||||
return render_template("bans.html", bans=bans, top_reason=top_reason, username=current_user.get_id())
|
||||
|
||||
|
||||
@app.route("/jobs", methods=["GET"])
|
||||
@login_required
|
||||
def jobs():
|
||||
return render_template("jobs.html", jobs=db.get_jobs(), jobs_errors=db.get_plugins_errors(), username=current_user.get_id(), dark_mode=app.config["DARK_MODE"], is_pro_version=PRO_VERSION, plugins_pro=PRO_PLUGINS_LIST)
|
||||
return render_template("jobs.html", jobs=db.get_jobs(), jobs_errors=db.get_plugins_errors(), username=current_user.get_id())
|
||||
|
||||
|
||||
@app.route("/jobs/download", methods=["GET"])
|
||||
|
|
|
|||
2
src/ui/templates/footer.html
vendored
2
src/ui/templates/footer.html
vendored
|
|
@ -8,7 +8,7 @@
|
|||
class="transition duration-300 text-xs tracking-wide leading-normal text-center text-white opacity-100 dark:text-white lg:text-left"
|
||||
>
|
||||
Copyright ©
|
||||
<script>
|
||||
<script nonce="{{ script_nonce }}">
|
||||
document.write(new Date().getFullYear());
|
||||
</script>
|
||||
Bunkerity
|
||||
|
|
|
|||
32
src/ui/templates/head.html
vendored
32
src/ui/templates/head.html
vendored
|
|
@ -17,42 +17,42 @@
|
|||
<link rel="stylesheet" type="text/css" href="./css/plugins.css" />
|
||||
<link rel="stylesheet" type="text/css" href="./css/dashboard.css" />
|
||||
|
||||
<script type="module" src="./js/global.js"></script>
|
||||
<script src="./js/plugins/setup.js"></script>
|
||||
<script type="module" src="./js/global.js" nonce="{{ script_nonce }}"></script>
|
||||
<script src="./js/plugins/setup.js" nonce="{{ script_nonce }}"></script>
|
||||
|
||||
<script async src="./js/utils/purify/purify.min.js"></script>
|
||||
<script src="./js/editor/ace.js"></script>
|
||||
<script async src="./js/utils/purify/purify.min.js" nonce="{{ script_nonce }}"></script>
|
||||
<script src="./js/editor/ace.js" nonce="{{ script_nonce }}"></script>
|
||||
|
||||
{% if current_endpoint == "global_config" %}
|
||||
<script type="module" src="./js/global_config.js"></script>
|
||||
<script type="module" src="./js/global_config.js" nonce="{{ script_nonce }}"></script>
|
||||
{% elif current_endpoint == "configs" %}
|
||||
<script type="module" src="./js/configs.js"></script>
|
||||
<script type="module" src="./js/configs.js" nonce="{{ script_nonce }}"></script>
|
||||
{% elif current_endpoint == "services" %}
|
||||
<script type="module" src="./js/services.js"></script>
|
||||
<script type="module" src="./js/services.js" nonce="{{ script_nonce }}"></script>
|
||||
{% elif current_endpoint == "plugins" %}
|
||||
<script type="module" src="./js/plugins.js"></script>
|
||||
<script type="module" src="./js/plugins.js" nonce="{{ script_nonce }}"></script>
|
||||
{% elif current_endpoint == "cache" %}
|
||||
<script type="module" src="./js/cache.js"></script>
|
||||
<script type="module" src="./js/cache.js" nonce="{{ script_nonce }}"></script>
|
||||
{% elif current_endpoint == "logs" %}
|
||||
<link rel="stylesheet" type="text/css" href="./css/flatpickr.css" />
|
||||
<link rel="stylesheet" type="text/css" href="./css/flatpickr.dark.css" />
|
||||
<script defer src="./js/utils/flatpickr.js"></script>
|
||||
<script defer src="./js/logs.js"></script>
|
||||
<script defer src="./js/utils/flatpickr.js" nonce="{{ script_nonce }}"></script>
|
||||
<script defer src="./js/logs.js" nonce="{{ script_nonce }}"></script>
|
||||
<link
|
||||
rel="stylesheet"
|
||||
type="text/css"
|
||||
href="./css/datepicker-foundation.css"
|
||||
/>
|
||||
{% elif current_endpoint == "jobs" %}
|
||||
<script type="module" src="./js/jobs.js"></script>
|
||||
<script type="module" src="./js/jobs.js" nonce="{{ script_nonce }}"></script>
|
||||
{% elif current_endpoint == "account" %}
|
||||
<script type="module" src="./js/account.js"></script>
|
||||
<script type="module" src="./js/account.js" nonce="{{ script_nonce }}"></script>
|
||||
{% elif current_endpoint == "reports" %}
|
||||
<script type="module" src="./js/reports.js"></script>
|
||||
<script type="module" src="./js/reports.js" nonce="{{ script_nonce }}"></script>
|
||||
{% elif current_endpoint == "bans" %}
|
||||
<link rel="stylesheet" type="text/css" href="./css/flatpickr.css" />
|
||||
<link rel="stylesheet" type="text/css" href="./css/flatpickr.dark.css" />
|
||||
<script defer src="./js/utils/flatpickr.js"></script>
|
||||
<script type="module" src="./js/bans.js"></script>
|
||||
<script defer src="./js/utils/flatpickr.js" nonce="{{ script_nonce }}"></script>
|
||||
<script type="module" src="./js/bans.js" nonce="{{ script_nonce }}"></script>
|
||||
{% endif %}
|
||||
</head>
|
||||
|
|
|
|||
2
src/ui/templates/loading.html
vendored
2
src/ui/templates/loading.html
vendored
|
|
@ -32,7 +32,7 @@
|
|||
</div>
|
||||
</div>
|
||||
</body>
|
||||
<script>
|
||||
<script nonce="{{ script_nonce }}">
|
||||
//animation
|
||||
const logoEl = document.querySelector("img");
|
||||
setInterval(() => {
|
||||
|
|
|
|||
4
src/ui/templates/login.html
vendored
4
src/ui/templates/login.html
vendored
|
|
@ -162,8 +162,8 @@
|
|||
</main>
|
||||
<!-- end particles -->
|
||||
<!-- end content -->
|
||||
<script src="js/tsparticles.bundle.min.js"></script>
|
||||
<script>
|
||||
<script src="js/tsparticles.bundle.min.js" nonce="{{ script_nonce }}"></script>
|
||||
<script nonce="{{ script_nonce }}">
|
||||
class Loader {
|
||||
constructor() {
|
||||
this.menuContainer = document.querySelector("[data-menu-container]");
|
||||
|
|
|
|||
2
src/ui/templates/setup.html
vendored
2
src/ui/templates/setup.html
vendored
|
|
@ -385,7 +385,7 @@
|
|||
</div>
|
||||
<!-- end form -->
|
||||
</main>
|
||||
<script>
|
||||
<script nonce="{{ script_nonce }}">
|
||||
class ServerCheck {
|
||||
constructor() {
|
||||
this.servInp = document.querySelector("#server_name");
|
||||
|
|
|
|||
6
src/ui/templates/totp.html
vendored
6
src/ui/templates/totp.html
vendored
|
|
@ -10,7 +10,7 @@
|
|||
<link href="images/favicon.ico" rel="icon" type="image/x-icon" />
|
||||
<link rel="stylesheet" href="css/dashboard.css" />
|
||||
<link rel="stylesheet" href="css/login.css" />
|
||||
<script defer src="./js/totp.js"></script>
|
||||
<script defer src="./js/totp.js" nonce="{{ script_nonce }}"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div
|
||||
|
|
@ -137,8 +137,8 @@
|
|||
<div id="particles-js" class="login-img [&>*]:bg-primary"></div>
|
||||
</div>
|
||||
</main>
|
||||
<script src="js/tsparticles.bundle.min.js"></script>
|
||||
<script>
|
||||
<script src="js/tsparticles.bundle.min.js" nonce="{{ script_nonce }}"></script>
|
||||
<script nonce="{{ script_nonce }}">
|
||||
class Loader {
|
||||
constructor() {
|
||||
this.menuContainer = document.querySelector("[data-menu-container]");
|
||||
|
|
|
|||
Loading…
Reference in a new issue