CSP and headers improvements, js nonce
This commit is contained in:
parent
ebbbe52753
commit
6ddb1f8c6a
|
@ -34,11 +34,21 @@ class tools
|
|||
public $db;
|
||||
public $profiler_enabled;
|
||||
public $profiler_last_name = "";
|
||||
public $script_nonce = null;
|
||||
|
||||
public function generateNonce($bytes_lenght = 16, $base64_encode = false){
|
||||
$nonce = bin2hex(random_bytes($bytes_lenght));
|
||||
if($base64_encode){
|
||||
$nonce = base64_encode($nonce);
|
||||
}
|
||||
return $nonce;
|
||||
}
|
||||
|
||||
public function __construct($db, $profiler_enabled)
|
||||
{
|
||||
$this->db = $db;
|
||||
$this->profiler_enabled = $profiler_enabled;
|
||||
$this->script_nonce = $this->generateNonce(16);
|
||||
}
|
||||
|
||||
public function validate_form($data, $expected_value=null, $data_source=null)
|
||||
|
@ -910,19 +920,28 @@ function init_class($enableDebugger=true, $headers=true)
|
|||
|
||||
if($headers) {
|
||||
//TODO adding require-trusted-types-for 'script';
|
||||
$csp = "default-src 'self' data: *.tile.openstreetmap.org nominatim.openstreetmap.org; connect-src 'self' *.sentry.io nominatim.openstreetmap.org; script-src 'self' 'unsafe-inline' 'unsafe-eval'; img-src 'self' data: *.tile.openstreetmap.org; object-src; style-src 'self' 'unsafe-inline';";
|
||||
$csp_rules = [
|
||||
"default-src 'self' data: *.tile.openstreetmap.org nominatim.openstreetmap.org",
|
||||
"connect-src 'self' *.sentry.io nominatim.openstreetmap.org",
|
||||
"script-src 'nonce-{$tools->script_nonce}' 'self'",
|
||||
"img-src 'self' data: *.tile.openstreetmap.org",
|
||||
"object-src",
|
||||
"style-src 'self' 'unsafe-inline'",
|
||||
"base-uri 'self'"
|
||||
];
|
||||
if(defined(SENTRY_CSP_REPORT_URI) && SENTRY_CSP_REPORT_URI !== false){
|
||||
$csp .= " report-uri ".SENTRY_CSP_REPORT_URI.";";
|
||||
$csp_rules[] = "report-uri ".SENTRY_CSP_REPORT_URI;
|
||||
}
|
||||
$csp = implode("; ", $csp_rules);
|
||||
if(!isset($_COOKIE["JSless"]) && (isset($_GET["JSless"]) ? !$_GET["JSless"] : true)){
|
||||
header("Content-Security-Policy: $csp");
|
||||
header("X-XSS-Protection: 1; mode=block");
|
||||
header("X-Content-Type-Options: nosniff");
|
||||
header("Permissions-Policy: interest-cohort=(), camera=(), microphone=(), payment=(), usb=()");
|
||||
header("Referrer-Policy: no-referrer");
|
||||
header("X-Frame-Options: DENY");
|
||||
}
|
||||
header("Content-Security-Policy: $csp");
|
||||
header("X-Content-Security-Policy: $csp");
|
||||
header("X-WebKit-CSP: $csp");
|
||||
header("X-XSS-Protection: 1; mode=block");
|
||||
header("X-Content-Type-Options: nosniff");
|
||||
header("Feature-Policy: autoplay 'none'; camera 'none'; microphone 'none'; payment 'none'");
|
||||
}
|
||||
//var_dump($user);
|
||||
//exit();
|
||||
|
||||
if(SENTRY_ENABLED){
|
||||
Sentry\configureScope(function (Sentry\State\Scope $scope): void {
|
||||
|
|
|
@ -161,7 +161,7 @@ EOT);
|
|||
|
||||
echo("</div>");
|
||||
?>
|
||||
<script>
|
||||
<script nonce="<?php echo(isset($_GET["nonce"]) ? $_GET["nonce"] : ""); ?>">
|
||||
function init_modal() {
|
||||
<?php if($orienation == "landscape"){ ?>$(".modal-dialog").css("max-width", "99%");<?php } ?>
|
||||
var isMouseDown = false;
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
<meta name="robots" content="none">
|
||||
<link rel="manifest" href="manifest.webmanifest">
|
||||
{% if delete_caches %}
|
||||
<script>
|
||||
<script nonce="{{ nonce }}">
|
||||
//from https://stackoverflow.com/a/57149239
|
||||
if ('caches' in window) {
|
||||
console.log("Deleting caches...");
|
||||
|
@ -28,7 +28,7 @@
|
|||
</script>
|
||||
{% endif %}
|
||||
{% if delete_service_workers %}
|
||||
<script>
|
||||
<script nonce="{{ nonce }}">
|
||||
//from https://stackoverflow.com/a/47515250
|
||||
if(window.navigator && navigator.serviceWorker) {
|
||||
console.log("UnRegistering service workers...");
|
||||
|
@ -48,7 +48,7 @@
|
|||
</script>
|
||||
{% endif %}
|
||||
{{ script('main.js') }}
|
||||
<script>$.fn.loading.defaults.message = "{{ 'Loading...'|t }}";</script>
|
||||
<script nonce="{{ nonce }}">$.fn.loading.defaults.message = "{{ 'Loading...'|t }}";</script>
|
||||
{% endblock %}
|
||||
{% if enable_debug_bar %}{{ debug_bar_head|raw }}{% endif %}
|
||||
</head>
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
{% endif %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
<script>
|
||||
<script nonce="{{ nonce }}">
|
||||
$('.chief').on('change', function () {
|
||||
$('input[name="' + this.name + '"]').not(this).prop('checked', false);
|
||||
});
|
||||
|
@ -126,7 +126,7 @@
|
|||
<button id="submit_button" type="submit" class="btn btn-primary">{{ 'Submit'|t }}</button>
|
||||
</div>
|
||||
</form>
|
||||
<script>
|
||||
<script nonce="{{ nonce }}">
|
||||
$( "#types" ).change(function() {
|
||||
$('#empty_option').remove();
|
||||
var type = "";
|
||||
|
@ -197,7 +197,7 @@
|
|||
<input id="id" type="hidden" value="{{ service.id }}" name="id"></input>
|
||||
<button id="remove" type="submit">{{ 'Submit'|t }}</button>
|
||||
</form>
|
||||
<script>
|
||||
<script nonce="{{ nonce }}">
|
||||
$('form').submit(function () {
|
||||
return confirm("{{ 'The action cannot be canceled. Are you sure you want to continue?'|t }}");
|
||||
});
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
{% endif %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
<script>
|
||||
<script nonce="{{ nonce }}">
|
||||
$('.chief').on('change', function () {
|
||||
$('input[name="' + this.name + '"]').not(this).prop('checked', false);
|
||||
});
|
||||
|
@ -96,7 +96,7 @@
|
|||
<button id="submit_button" type="submit" class="btn btn-primary">{{ 'Submit'|t }}</button>
|
||||
</div>
|
||||
</form>
|
||||
<script>
|
||||
<script nonce="{{ nonce }}">
|
||||
{% if training.modalità == "edit" %}
|
||||
{% if option('use_location_picker') %}
|
||||
{% set place = values.place|split('#')[0] %}
|
||||
|
@ -121,7 +121,7 @@
|
|||
<input id="id" type="hidden" value="{{ training.id }}" name="id"></input>
|
||||
<button id="remove" type="submit">{{ 'Submit'|t }}</button>
|
||||
</form>
|
||||
<script>
|
||||
<script nonce="{{ nonce }}">
|
||||
$('form').submit(function () {
|
||||
return confirm("{{ 'The action cannot be canceled. Are you sure you want to continue?'|t }}");
|
||||
});
|
||||
|
|
|
@ -69,7 +69,7 @@
|
|||
<input id="id" type="hidden" value="{{ id }}" name="id"></input>
|
||||
<button id="remove" type="submit">{{ 'Submit'|t }}</button>
|
||||
</form>
|
||||
<script>
|
||||
<script nonce="{{ nonce }}">
|
||||
$('form').submit(function () {
|
||||
return confirm("{{ 'The action cannot be canceled. Are you sure you want to continue?'|t }}");
|
||||
});
|
||||
|
|
|
@ -4,6 +4,32 @@
|
|||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
{% if error %}
|
||||
<div id="err" class="alert alert-danger m-3" role="alert">
|
||||
<h4 class="alert-heading">{{ error.text|t }}</h4>
|
||||
<p>{{ 'Error'|t}} {{ 'code'|t}} {{ error.code }}. {{ 'Check the entered credentials and make sure they are correct'|t }}.</p>
|
||||
<img src='{{ urlsoftware }}/resources/images/{{ error_image }}'></img>
|
||||
</div>
|
||||
<script nonce="{{ nonce }}">
|
||||
const noSaveData = 'connection' in navigator === false || ('connection' in navigator && !navigator.connection.saveData);
|
||||
if (noSaveData) {
|
||||
let playerScript = document.createElement("script");
|
||||
playerScript.setAttribute("src", "{{ urlsoftware }}/resources/dist/{{ resource('players.js') }}");
|
||||
playerScript.setAttribute("nonce", "{{ nonce }}");
|
||||
playerScript.setAttribute("async", "false");
|
||||
playerScript.onload = function() {
|
||||
console.log("player script loaded");
|
||||
var sound = new Howl({
|
||||
src: ['{{ urlsoftware }}/resources/sounds/{{ error_sound }}'],
|
||||
autoplay: true
|
||||
});
|
||||
sound.play();
|
||||
};
|
||||
document.head.insertBefore(playerScript, document.head.firstElementChild);
|
||||
}
|
||||
$("#err").delay(20000).fadeOut(300);
|
||||
</script>
|
||||
{% endif %}
|
||||
<div class="align-items-center container d-flex justify-content-center" id="modulogin">
|
||||
<form method="post">
|
||||
<img alt="VVF" src="{{ urlsoftware }}/resources/images/logo.png" class="img-resposive"><br><br>
|
||||
|
@ -25,31 +51,6 @@
|
|||
{% endif %}
|
||||
<input type="submit" name="login" class="btn btn-block btn-lg btn-success" value="{{ 'Login'|t }}">
|
||||
</form>
|
||||
{% if error %}
|
||||
<div id="err" class="alert alert-danger m-3" role="alert">
|
||||
<h4 class="alert-heading">{{ error.text|t }}</h4>
|
||||
<p>{{ 'Error'|t}} {{ 'code'|t}} {{ error.code }}. {{ 'Check the entered credentials and make sure they are correct'|t }}.</p>
|
||||
<img src='{{ urlsoftware }}/resources/images/{{ error_image }}'></img>
|
||||
</div>
|
||||
<script>
|
||||
const noSaveData = 'connection' in navigator === false || ('connection' in navigator && !navigator.connection.saveData);
|
||||
if (noSaveData) {
|
||||
let playerScript = document.createElement("script");
|
||||
playerScript.setAttribute("src", "{{ urlsoftware }}/resources/dist/{{ resource('players.js') }}");
|
||||
playerScript.setAttribute("async", "false");
|
||||
playerScript.onload = function() {
|
||||
console.log("player script loaded");
|
||||
var sound = new Howl({
|
||||
src: ['{{ urlsoftware }}/resources/sounds/{{ error_sound }}'],
|
||||
autoplay: true
|
||||
});
|
||||
sound.play();
|
||||
};
|
||||
document.head.insertBefore(playerScript, document.head.firstElementChild);
|
||||
}
|
||||
$("#err").delay(20000).fadeOut(300);
|
||||
</script>
|
||||
{% endif %}
|
||||
</div>
|
||||
<br><br>
|
||||
|
||||
|
|
|
@ -21,10 +21,10 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
<script nonce="{{ nonce }}">
|
||||
$('#schedulesModal').on('show.bs.modal', function (event) {
|
||||
//$( ".modal-body" ).loading("show");
|
||||
$(".modal-body").load("modal_availability_schedule.php", {
|
||||
$(".modal-body").load("modal_availability_schedule.php?nonce={{ nonce }}", {
|
||||
orientation: window.innerHeight > window.innerWidth ? "portrait" : "landscape"
|
||||
}, function() {
|
||||
init_modal();
|
||||
|
@ -69,7 +69,7 @@
|
|||
<tbody id="table_body">
|
||||
</tbody>
|
||||
</table>
|
||||
<script>
|
||||
<script nonce="{{ nonce }}">
|
||||
allertaJS.main.loadTable({tablePage: "list", useCustomTableEngine: "default"});
|
||||
</script>
|
||||
</div>
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
<tbody id="table_body">
|
||||
</tbody>
|
||||
</table>
|
||||
<script>
|
||||
<script nonce="{{ nonce }}">
|
||||
allertaJS.main.loadTable({tablePage: "log", setInterval: false, callback: function(tableDt) {
|
||||
tableDt
|
||||
.column( '3:visible' )
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
<tbody id="table_body">
|
||||
</tbody>
|
||||
</table>
|
||||
<script>
|
||||
<script nonce="{{ nonce }}">
|
||||
allertaJS.main.loadTable("list", true, 20000, true);
|
||||
</script>
|
||||
</div>
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
<tbody id="table_body">
|
||||
</tbody>
|
||||
</table>
|
||||
<script>
|
||||
<script nonce="{{ nonce }}">
|
||||
allertaJS.main.loadTable({tablePage: "services", interval: 120000});
|
||||
</script>
|
||||
</div>
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
<tbody id="table_body">
|
||||
</tbody>
|
||||
</table>
|
||||
<script>
|
||||
<script nonce="{{ nonce }}">
|
||||
allertaJS.main.loadTable({tablePage: "trainings", interval: 120000});
|
||||
</script>
|
||||
</div>
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
require_once 'core.php';
|
||||
init_class();
|
||||
|
||||
$nonce = $tools->script_nonce;
|
||||
|
||||
if(!is_null($debugbar)){
|
||||
$enable_debugbar = true;
|
||||
$debugbarRenderer = $debugbar->getJavascriptRenderer("./vendor/maximebf/debugbar/src/DebugBar/Resources");
|
||||
|
@ -20,7 +22,7 @@ $webpack_manifest = json_decode(
|
|||
true
|
||||
);
|
||||
|
||||
if(isset($_COOKIE["JSless"])){
|
||||
if(isset($_COOKIE["JSless"]) && $_COOKIE["JSless"]){
|
||||
$templates_dir = $_COOKIE["JSless"] ? "templates/JSless" : "templates";
|
||||
$JSless = true;
|
||||
} else {
|
||||
|
@ -29,9 +31,15 @@ if(isset($_COOKIE["JSless"])){
|
|||
}
|
||||
|
||||
if(isset($_GET["JSless"])){
|
||||
setcookie("JSless", $_GET["JSless"] ? true : false, time() + (86400 * 365));
|
||||
$templates_dir = $_GET["JSless"] ? "templates/JSless" : "templates";
|
||||
$JSless = true;
|
||||
if($_GET["JSless"]){
|
||||
setcookie("JSless", true, time() + (86400 * 365));
|
||||
$templates_dir = "templates/JSless";
|
||||
$JSless = true;
|
||||
} else {
|
||||
setcookie("JSless", null, time() - 3600);
|
||||
$templates_dir = "templates";
|
||||
$JSless = false;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
|
@ -88,11 +96,11 @@ $twig->addFunction($function_resource);
|
|||
|
||||
$function_script = new \Twig\TwigFunction(
|
||||
'script', function ($file, $onLoad=false) {
|
||||
global $url_software, $webpack_manifest;
|
||||
global $nonce, $url_software, $webpack_manifest;
|
||||
$script_url = $url_software . "/resources/dist/" . $webpack_manifest[$file]["src"];
|
||||
$script_integrity = $webpack_manifest[$file]["integrity"];
|
||||
|
||||
$script_tag = "<script src='{$script_url}' integrity='{$script_integrity}' crossorigin='anonymous'";
|
||||
$script_tag = "<script src='{$script_url}' integrity='{$script_integrity}' crossorigin='anonymous' nonce='".$nonce."'";
|
||||
if($onLoad){
|
||||
$script_tag .= " onload='{$onLoad}'";
|
||||
}
|
||||
|
@ -133,11 +141,12 @@ p_stop();
|
|||
$template = null;
|
||||
function loadtemplate($templatename, $data, $requirelogin=true)
|
||||
{
|
||||
global $url_software, $user, $twig, $template, $enable_debugbar, $debugbarRenderer;
|
||||
global $nonce, $url_software, $user, $twig, $template, $enable_debugbar, $debugbarRenderer;
|
||||
p_start("Render Twig template");
|
||||
if($requirelogin) {
|
||||
$user->requirelogin();
|
||||
}
|
||||
$data['nonce'] = $nonce;
|
||||
$data['delete_caches'] = isset($_GET["deleteCache"]) || isset($_GET["unregisterSW"]) || isset($_GET["unregisterSWandDisable"]);
|
||||
$data['delete_service_workers'] = isset($_GET["unregisterSW"]) || isset($_GET["unregisterSWandDisable"]);
|
||||
$data['delete_service_workers_and_disable'] = isset($_GET["unregisterSWandDisable"]);
|
||||
|
|
Loading…
Reference in New Issue