M4: security pass — strict CSP, header split, build-time scan
All JS moved to external /site.js → script-src 'self' with no inline JS, hashes or eval. Full header set via nginx (CSP, nosniff, frame-deny, referrer, permissions, COOP/CORP); HSTS stays at the CF edge. Shared headers include avoids the location add_header reset footgun. Build-time secret/inline-script/third-party scan gate. SECURITY.md documents posture.
This commit is contained in:
Executable
+51
@@ -0,0 +1,51 @@
|
||||
#!/usr/bin/env bash
|
||||
# Build-time security scan of dist/ (§8 evidence). Fails the build if it finds:
|
||||
# - secrets / private keys / tokens
|
||||
# - inline <script> blocks (we require strict CSP script-src 'self')
|
||||
# - third-party script/style/font origins (everything must be self-hosted)
|
||||
# Run after `astro build`. Exit non-zero on any finding.
|
||||
set -euo pipefail
|
||||
|
||||
DIST="${1:-dist}"
|
||||
fail=0
|
||||
|
||||
note() { printf ' %s\n' "$1"; }
|
||||
bad() { printf ' ✗ %s\n' "$1"; fail=1; }
|
||||
|
||||
echo "== secret scan =="
|
||||
# Allow our own public email + domains; look for genuinely secret-looking patterns.
|
||||
if grep -rniE 'BEGIN (RSA |EC |OPENSSH )?PRIVATE KEY|aws_secret|api[_-]?key["'"'"' :=]|secret[_-]?key["'"'"' :=]|password["'"'"' :=]|bearer [a-z0-9._-]{20}' "$DIST" 2>/dev/null; then
|
||||
bad "possible secret found in dist/"
|
||||
else
|
||||
note "✓ no secret-like strings"
|
||||
fi
|
||||
|
||||
echo "== inline <script> (must be none; CSP script-src 'self') =="
|
||||
# An inline script is <script> WITHOUT a src= attribute.
|
||||
if grep -rnoE '<script(>| [^>]*>)' "$DIST" --include='*.html' | grep -vE 'src=' >/dev/null; then
|
||||
grep -rnoE '<script(>| [^>]*>)' "$DIST" --include='*.html' | grep -vE 'src=' | head
|
||||
bad "inline <script> present"
|
||||
else
|
||||
note "✓ no inline scripts"
|
||||
fi
|
||||
|
||||
echo "== third-party resource origins (must be self-hosted) =="
|
||||
# Flag <script src> / <link href> tags pointing off-domain (anchor <a href> links
|
||||
# in the body are fine). Match the tag + attr together so e.g. linkedin.com in an
|
||||
# <a> isn't a false positive.
|
||||
if grep -rioE '<(script|link)\b[^>]*\b(src|href)="https?://[^"]+"' "$DIST" --include='*.html' \
|
||||
| grep -ivE '"https?://(www\.|git\.)?bztmon\.com' >/dev/null 2>&1; then
|
||||
echo " offending tags:"
|
||||
grep -rioE '<(script|link)\b[^>]*\b(src|href)="https?://[^"]+"' "$DIST" --include='*.html' \
|
||||
| grep -ivE '"https?://(www\.|git\.)?bztmon\.com' | head
|
||||
bad "third-party script/style origin referenced"
|
||||
else
|
||||
note "✓ no third-party script/style origins (external links in body are fine)"
|
||||
fi
|
||||
|
||||
echo
|
||||
if [[ "$fail" -ne 0 ]]; then
|
||||
echo "BUILD SCAN: FAIL"
|
||||
exit 1
|
||||
fi
|
||||
echo "BUILD SCAN: PASS"
|
||||
Reference in New Issue
Block a user