#!/bin/bash # ===================================================================== # update-csp-hashes.sh - Update Content Security Policy hashes # ===================================================================== # This script updates the CSP hashes for: # 1. All JavaScript and CSS files # 2. All inline style attributes in HTML files # 3. Adds CSP meta tags to HTML files # After running this script, restart the server using: # ./caddy.sh # ===================================================================== set -e echo "Updating CSP hashes for all JavaScript, CSS files, and inline styles..." # Directory containing the files BASE_DIR="$(pwd)" # Check if we're in a Docker environment if [ -f "/etc/caddy/Caddyfile" ]; then CADDYFILE="/etc/caddy/Caddyfile" else CADDYFILE="$BASE_DIR/Caddyfile" fi TEMP_INLINE_HASHES_FILE=$(mktemp) # Arrays to store hashes SCRIPT_HASHES=() STYLE_HASHES=() # Calculate hash for a file calculate_hash() { local file=$1 sha256sum "$file" | awk '{print $1}' | xxd -r -p | base64 } # Calculate hash for inline style calculate_inline_hash() { local style_content=$1 echo -n "$style_content" | sha256sum | awk '{print $1}' | xxd -r -p | base64 } # Process JavaScript files echo "Processing JavaScript files..." for js_file in $(find "$BASE_DIR" -name "*.js" -type f); do echo "Processing $js_file" file_name=$(basename "$js_file") hash=$(calculate_hash "$js_file") SCRIPT_HASHES+=("'sha256-$hash'") # Update HTML files that reference this JS file for html_file in $(find "$BASE_DIR" -name "*.html" -type f); do if grep -q "$file_name" "$html_file"; then echo "Updating $file_name in $html_file" # Create a temporary file for the replacement tmp_file=$(mktemp) # For files with existing integrity attribute if grep -q "$file_name.*integrity" "$html_file"; then # Use awk for safer text processing awk -v fname="$file_name" -v newhash="$hash" ' { if ($0 ~ fname && $0 ~ /integrity/) { gsub(/integrity="sha256-[^"]*"/, "integrity=\"sha256-" newhash "\""); } print; }' "$html_file" > "$tmp_file" else # Add integrity attribute if it doesn't exist awk -v fname="$file_name" -v newhash="$hash" ' { if ($0 ~ fname && $0 ~ /src/ && !($0 ~ /integrity/)) { gsub(/src="[^"]*"/, "&" " integrity=\"sha256-" newhash "\""); } print; }' "$html_file" > "$tmp_file" fi # Replace original file with modified content mv "$tmp_file" "$html_file" fi done done # Process CSS files echo "Processing CSS files..." for css_file in $(find "$BASE_DIR" -name "*.css" -type f); do echo "Processing $css_file" file_name=$(basename "$css_file") hash=$(calculate_hash "$css_file") STYLE_HASHES+=("'sha256-$hash'") # Update HTML files that reference this CSS file for html_file in $(find "$BASE_DIR" -name "*.html" -type f); do if grep -q "$file_name" "$html_file"; then echo "Updating $file_name in $html_file" # Create a temporary file for the replacement tmp_file=$(mktemp) # For files with existing integrity attribute if grep -q "$file_name.*integrity" "$html_file"; then # Use awk for safer text processing awk -v fname="$file_name" -v newhash="$hash" ' { if ($0 ~ fname && $0 ~ /integrity/) { gsub(/integrity="sha256-[^"]*"/, "integrity=\"sha256-" newhash "\""); } print; }' "$html_file" > "$tmp_file" else # Add integrity attribute if it doesn't exist awk -v fname="$file_name" -v newhash="$hash" ' { if ($0 ~ fname && $0 ~ /href/ && !($0 ~ /integrity/)) { gsub(/href="[^"]*"/, "&" " integrity=\"sha256-" newhash "\""); } print; }' "$html_file" > "$tmp_file" fi # Replace original file with modified content mv "$tmp_file" "$html_file" fi done done # Find and process inline styles - using a more thorough approach echo "Processing HTML files for inline styles..." find "$BASE_DIR" -name "*.html" -type f | while read -r html_file; do echo "Processing $html_file for inline styles..." # Use a more comprehensive grep pattern to catch all inline styles # This includes both style="..." and style = "..." patterns grep -o 'style\s*=\s*"[^"]*"' "$html_file" | sed 's/style\s*=\s*"\(.*\)"/\1/' | while read -r style_content; do if [ -n "$style_content" ]; then hash=$(calculate_inline_hash "$style_content") echo "Found inline style: '$style_content'" echo "Calculated hash: sha256-$hash" echo "'sha256-$hash'" >> "$TEMP_INLINE_HASHES_FILE" fi done done # Sort and remove duplicates from inline style hashes if [ -f "$TEMP_INLINE_HASHES_FILE" ]; then sort -u "$TEMP_INLINE_HASHES_FILE" > "${TEMP_INLINE_HASHES_FILE}.sorted" mv "${TEMP_INLINE_HASHES_FILE}.sorted" "$TEMP_INLINE_HASHES_FILE" # Add inline style hashes to the STYLE_HASHES array while read -r hash; do STYLE_HASHES+=("$hash") done < "$TEMP_INLINE_HASHES_FILE" # Clean up rm -f "$TEMP_INLINE_HASHES_FILE" fi # Combine all hashes for CSP echo "Skipping CSP header updates (disabled)" echo "CSP hashes updated successfully!" echo "To apply changes, restart the server using: ./caddy.sh"