Self-host front-end libraries, minimal sign-in header and CSP
- sign-in pages load only what they use (include_login_header.php, ajax_core.js) - every library, font and data file served from assets/vendor with pinned versions (VERSIONS.json); no CDN at runtime - Content-Security-Policy on app, sign-in and landing pages - remove httpbin Dropzone target and source-map references
This commit is contained in:
+33
-28
@@ -23,10 +23,13 @@ ini_set('log_errors', '1');
|
||||
// need this too or they render a UTC date.
|
||||
require_once __DIR__ . '/assets/utils/timezone.php';
|
||||
|
||||
// Security headers — emitted before any HTML output.
|
||||
header('X-Content-Type-Options: nosniff');
|
||||
header('X-Frame-Options: SAMEORIGIN');
|
||||
header('Referrer-Policy: strict-origin-when-cross-origin');
|
||||
// Security headers (CSP, nosniff, framing, referrer) — emitted before any HTML output.
|
||||
require_once __DIR__ . '/assets/utils/page_headers.php';
|
||||
send_page_security_headers();
|
||||
|
||||
// Self-hosted libraries (assets/vendor/, exact versions in assets/vendor/VERSIONS.json):
|
||||
// the app no longer depends on third-party CDNs being up or unchanged.
|
||||
$vendor_url = $server_url . 'assets/vendor/';
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
@@ -42,59 +45,61 @@ header('Referrer-Policy: strict-origin-when-cross-origin');
|
||||
<link rel="manifest" href="<?php echo $server_url?>assets/site.webmanifest">
|
||||
|
||||
<!-- jquery -->
|
||||
<script src="https://code.jquery.com/jquery-3.7.1.js" integrity="sha256-eKhayi8LEQwp4NKxN+CfCh+3qOVUtJn3QNZ0TciWLP4=" crossorigin="anonymous"></script>
|
||||
<script src="<?php echo $vendor_url?>jquery/3.7.1/jquery.min.js"></script>
|
||||
|
||||
<!-- popper (must be before bootstrap) -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.11.8/dist/umd/popper.min.js" crossorigin="anonymous"></script>
|
||||
<script src="<?php echo $vendor_url?>popper/2.11.8/popper.min.js"></script>
|
||||
|
||||
<!-- bootstrap -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/js/bootstrap.min.js" integrity="sha384-G/EV+4j2dNv+tEPo3++6LCgdCROaejBqfUeNjuKAiuXbjrxilcCdDz6ZAVfHWe1Y" crossorigin="anonymous"></script>
|
||||
<!-- Disable CDN Bootstrap's dropdown toggle — main.js bundles Bootstrap+Popper and
|
||||
handles dropdown events. CDN Bootstrap stays for window.bootstrap (Modal API). -->
|
||||
<script src="<?php echo $vendor_url?>bootstrap/5.3.8/bootstrap.min.js"></script>
|
||||
<!-- Disable the standalone Bootstrap's dropdown toggle — main.js bundles Bootstrap+Popper and
|
||||
handles dropdown events. This copy stays for window.bootstrap (Modal API). -->
|
||||
<script>bootstrap.Dropdown.prototype.toggle = function() {};</script>
|
||||
|
||||
<!-- bootbox -->
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootbox.js/4.4.0/bootbox.min.js"></script>
|
||||
<script src="<?php echo $vendor_url?>bootbox/4.4.0/bootbox.min.js"></script>
|
||||
|
||||
<!-- overlay loader -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/gasparesganga-jquery-loading-overlay@2.1.7/dist/loadingoverlay.min.js"></script>
|
||||
<script src="<?php echo $vendor_url?>loadingoverlay/2.1.7/loadingoverlay.min.js"></script>
|
||||
|
||||
<!-- bootstrap css -->
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-sRIl4kxILFvY47J16cr9ZwB07vP4J8+LH7qKQnuqkuIAvNWLzeN8tE5YBujZqJLB" crossorigin="anonymous">
|
||||
<link href="<?php echo $vendor_url?>bootstrap/5.3.8/bootstrap.min.css" rel="stylesheet">
|
||||
|
||||
<!-- flatpickr date -->
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/flatpickr/dist/flatpickr.min.css">
|
||||
<script src="https://cdn.jsdelivr.net/npm/flatpickr"></script>
|
||||
<!-- flatpickr date (custom.js initialises .flatpickr inputs on load, so not deferred) -->
|
||||
<link rel="stylesheet" href="<?php echo $vendor_url?>flatpickr/4.6.13/flatpickr.min.css">
|
||||
<script src="<?php echo $vendor_url?>flatpickr/4.6.13/flatpickr.min.js"></script>
|
||||
|
||||
<!-- flatpickr monthSelect plugin -->
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/flatpickr/dist/plugins/monthSelect/style.css">
|
||||
<script src="https://cdn.jsdelivr.net/npm/flatpickr/dist/plugins/monthSelect/index.js"></script>
|
||||
<link rel="stylesheet" href="<?php echo $vendor_url?>flatpickr/4.6.13/plugins/monthSelect/style.css">
|
||||
<script src="<?php echo $vendor_url?>flatpickr/4.6.13/plugins/monthSelect/index.js"></script>
|
||||
|
||||
<!-- autocomplete -->
|
||||
<link rel="stylesheet" href="https://code.jquery.com/ui/1.14.1/themes/base/jquery-ui.css">
|
||||
<script src="https://code.jquery.com/ui/1.14.1/jquery-ui.min.js"></script>
|
||||
<link rel="stylesheet" href="<?php echo $vendor_url?>jquery-ui/1.14.1/jquery-ui.css">
|
||||
<script src="<?php echo $vendor_url?>jquery-ui/1.14.1/jquery-ui.min.js"></script>
|
||||
|
||||
<!-- alasql -->
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/alasql/4.6.6/alasql.min.js" integrity="sha512-a0dn7nW2exqcTrj7ZcLhRW3iDxCKOh9GPa1jf27qljXfwhYp4tnNmm+8aRNp9c3ijpGsm7EmeGSQmcu80ZB3NA==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
|
||||
<!-- alasql (only called from functions that run after load) -->
|
||||
<script defer src="<?php echo $vendor_url?>alasql/4.6.6/alasql.min.js"></script>
|
||||
|
||||
<!-- dropzone -->
|
||||
<script src="https://unpkg.com/dropzone@5/dist/min/dropzone.min.js"></script>
|
||||
<script src="<?php echo $vendor_url?>dropzone/5.9.3/dropzone.min.js"></script>
|
||||
<script>
|
||||
// This kills the CDN's auto-scanner so it doesn't conflict with main.js
|
||||
Dropzone.autoDiscover = false;
|
||||
// Turn off Dropzone's auto-scanner so it doesn't conflict with main.js
|
||||
Dropzone.autoDiscover = false;
|
||||
</script>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/apexcharts"></script>
|
||||
|
||||
<!-- apexcharts (only called from functions that run after load) -->
|
||||
<script defer src="<?php echo $vendor_url?>apexcharts/7.5.1/apexcharts.min.js"></script>
|
||||
|
||||
<!-- theme script -->
|
||||
<link rel="stylesheet" href="<?php echo $server_url?>assets/css/main.css">
|
||||
<script type="module" src="<?php echo $server_url?>assets/js/main.js"></script>
|
||||
<link rel="stylesheet" href="<?php echo $server_url?>assets/css/custom.css">
|
||||
<script src="<?php echo $server_url?>assets/js/ajax_core.js?v=<?php echo @filemtime(__DIR__ . '/assets/js/ajax_core.js'); ?>"></script>
|
||||
<script src="<?php echo $server_url?>assets/js/custom.js?v=<?php echo @filemtime(__DIR__ . '/assets/js/custom.js'); ?>"></script>
|
||||
<script src="<?php echo $server_url?>assets/js/batch_overlay.js"></script>
|
||||
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/html5-qrcode/2.3.8/html5-qrcode.min.js"
|
||||
crossorigin="anonymous" referrerpolicy="no-referrer"></script>
|
||||
<!-- camera scanner library, loaded lazily by scanner.js when the camera opens -->
|
||||
<script defer src="<?php echo $vendor_url?>html5-qrcode/2.3.8/html5-qrcode.min.js"></script>
|
||||
<script src="<?php echo $server_url?>assets/js/scanner.js"></script>
|
||||
|
||||
</head>
|
||||
|
||||
Reference in New Issue
Block a user