Security+Perf: CSP nonces, robots.txt cleanup, minify JS

- index.php: replace unsafe-inline CSP with per-request nonces on all 13 inline scripts/styles
- robots.txt: remove sensitive config filenames (db-config, email-config, recaptcha-config)
- main.min.js: actually minified with terser (37KB -> 16KB, -38% gzipped)
This commit is contained in:
Peter Foster
2026-03-22 04:06:53 +00:00
parent 803905c328
commit 14f1e53c07
3 changed files with 16 additions and 1007 deletions

991
assets/js/main.min.js vendored

File diff suppressed because one or more lines are too long

View File

@@ -5,6 +5,7 @@ ini_set('session.cookie_samesite', 'Lax');
ini_set('session.cookie_httponly', '1');
ini_set('session.cookie_secure', '1');
session_start();
$nonce = base64_encode(random_bytes(16));
// Allow private caching with revalidation (CSRF token requires session)
header("Cache-Control: public, max-age=3600, stale-while-revalidate=86400");
@@ -12,7 +13,7 @@ if (!isset($_SESSION['csrf_token'])) {
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
}
header('Strict-Transport-Security: max-age=31536000; includeSubDomains');
header('Content-Security-Policy: default-src \'self\'; script-src \'self\' \'unsafe-inline\' https://cdnjs.cloudflare.com https://www.googletagmanager.com https://www.google-analytics.com https://www.clarity.ms https://www.google.com https://www.gstatic.com; style-src \'self\' \'unsafe-inline\' https://fonts.googleapis.com; font-src \'self\' https://fonts.gstatic.com; img-src \'self\' data: https://www.google-analytics.com; connect-src \'self\' https://www.google-analytics.com https://analytics.google.com https://region1.google-analytics.com https://www.google.com; frame-src https://www.google.com;');
header("Content-Security-Policy: default-src 'self'; script-src 'self' 'nonce-{$nonce}' https://cdnjs.cloudflare.com https://www.googletagmanager.com https://www.google-analytics.com https://www.clarity.ms https://www.google.com https://www.gstatic.com; style-src 'self' 'nonce-{$nonce}' https://fonts.googleapis.com; font-src 'self' https://fonts.gstatic.com; img-src 'self' data: https://www.google-analytics.com; connect-src 'self' https://www.google-analytics.com https://analytics.google.com https://region1.google-analytics.com https://www.google.com; frame-src https://www.google.com;");
// SEO and performance optimizations
$page_title = "AI Automation Consulting UK | Legal & Consultancy";
@@ -71,7 +72,7 @@ $twitter_card_image = "https://ukaiautomation.co.uk/assets/images/ukaiautomation
<!-- Google Analytics 4 (GA4) -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-GK41JM8DK0"></script>
<script>
<script nonce="<?php echo $nonce; ?>">
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
@@ -84,7 +85,7 @@ $twitter_card_image = "https://ukaiautomation.co.uk/assets/images/ukaiautomation
<!-- Google Tag Manager (Optional - if you use GTM) -->
<!-- TODO: Replace GTM-XXXXXXX with your Google Tag Manager container ID -->
<!--
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
<script nonce="<?php echo $nonce; ?>">(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
@@ -94,7 +95,7 @@ $twitter_card_image = "https://ukaiautomation.co.uk/assets/images/ukaiautomation
<!-- Microsoft Clarity (Optional) -->
<!-- TODO: Replace CLARITY_PROJECT_ID with your Clarity project ID -->
<!--
<script type="text/javascript">
<script type="text/javascript" nonce="<?php echo $nonce; ?>">
(function(c,l,a,r,i,t,y){
c[a]=c[a]||function(){(c[a].q=c[a].q||[]).push(arguments)};
t=l.createElement(r);t.async=1;t.src="https://www.clarity.ms/tag/"+i;
@@ -106,7 +107,7 @@ $twitter_card_image = "https://ukaiautomation.co.uk/assets/images/ukaiautomation
<!-- reCAPTCHA v3 -->
<?php require_once '.recaptcha-config.php'; ?>
<script src="https://www.google.com/recaptcha/api.js?render=<?php echo RECAPTCHA_SITE_KEY; ?>"></script>
<script>window.recaptchaSiteKey = '<?php echo RECAPTCHA_SITE_KEY; ?>';</script>
<script nonce="<?php echo $nonce; ?>">window.recaptchaSiteKey = '<?php echo RECAPTCHA_SITE_KEY; ?>';</script>
<!-- Fonts -->
<link rel="preconnect" href="https://fonts.googleapis.com">
@@ -119,7 +120,7 @@ $twitter_card_image = "https://ukaiautomation.co.uk/assets/images/ukaiautomation
<link rel="preload" href="/assets/js/main.min.js?v=1.1.1" as="script">
<!-- Critical CSS for Above-the-Fold -->
<style>
<style nonce="<?php echo $nonce; ?>">
*{margin:0;padding:0;box-sizing:border-box}
body{font-family:'Roboto Slab','Lato',sans-serif;line-height:1.6;color:#444;background:#fff}
.container{max-width:1200px;margin:0 auto;padding:0 20px}
@@ -144,7 +145,7 @@ $twitter_card_image = "https://ukaiautomation.co.uk/assets/images/ukaiautomation
<noscript><link rel="stylesheet" href="assets/css/main.min.css?v=1.1.4"></noscript>
<!-- Enhanced Local SEO Schema -->
<script type="application/ld+json">
<script type="application/ld+json" nonce="<?php echo $nonce; ?>">
{
"@context": "https://schema.org",
"@type": "Organization",
@@ -291,7 +292,7 @@ $twitter_card_image = "https://ukaiautomation.co.uk/assets/images/ukaiautomation
</script>
<!-- WebSite Schema for Search Box -->
<script type="application/ld+json">
<script type="application/ld+json" nonce="<?php echo $nonce; ?>">
{
"@context": "https://schema.org",
"@type": "WebSite",
@@ -314,7 +315,7 @@ $twitter_card_image = "https://ukaiautomation.co.uk/assets/images/ukaiautomation
</script>
<!-- Service Schema -->
<script type="application/ld+json">
<script type="application/ld+json" nonce="<?php echo $nonce; ?>">
{
"@context": "https://schema.org",
"@type": "Service",
@@ -355,7 +356,7 @@ $twitter_card_image = "https://ukaiautomation.co.uk/assets/images/ukaiautomation
</script>
<!-- Breadcrumb Schema -->
<script type="application/ld+json">
<script type="application/ld+json" nonce="<?php echo $nonce; ?>">
{
"@context": "https://schema.org",
"@type": "BreadcrumbList",
@@ -371,7 +372,7 @@ $twitter_card_image = "https://ukaiautomation.co.uk/assets/images/ukaiautomation
</script>
<!-- WebPage Schema -->
<script type="application/ld+json">
<script type="application/ld+json" nonce="<?php echo $nonce; ?>">
{
"@context": "https://schema.org",
"@type": "WebPage",
@@ -1150,7 +1151,7 @@ $twitter_card_image = "https://ukaiautomation.co.uk/assets/images/ukaiautomation
<script src="/assets/js/main.min.js?v=1.1.1"></script>
<!-- Service Worker Registration -->
<script>
<script nonce="<?php echo $nonce; ?>">
if ('serviceWorker' in navigator) {
window.addEventListener('load', () => {
navigator.serviceWorker.register('/sw.js')
@@ -1178,7 +1179,7 @@ $twitter_card_image = "https://ukaiautomation.co.uk/assets/images/ukaiautomation
</script>
<!-- Enhanced Core Web Vitals Monitoring -->
<script>
<script nonce="<?php echo $nonce; ?>">
// Monitor Core Web Vitals for SEO performance
if ('web-vital' in window || typeof webVitals !== 'undefined') {
function sendToAnalytics(metric) {
@@ -1230,7 +1231,7 @@ $twitter_card_image = "https://ukaiautomation.co.uk/assets/images/ukaiautomation
</script>
<!-- FAQ Accordion -->
<script>
<script nonce="<?php echo $nonce; ?>">
document.addEventListener('DOMContentLoaded', function() {
const faqQuestions = document.querySelectorAll('.faq-question');

View File

@@ -21,9 +21,6 @@ Disallow: /*.inc$
Disallow: /*.sql$
Disallow: /*.sh$
Disallow: /*.bak$
Disallow: /db-config.php
Disallow: /.email-config.php
Disallow: /.recaptcha-config.php
# Block query string URLs to prevent duplicate content
Disallow: /*?*