# Function to audit CSP, Permissions Policy, and secure headers for a given URL. csp_perms_audit() { URL=$1 if [ -z "$URL" ]; then echo "Usage: csp_perms_audit " return 1 fi # Generate a nonce for CSP policies NONCE=$(openssl rand -base64 12) # Instructions and example Traefik labels for setting CSP, Permissions Policy, and secure headers. echo "=== Instructions ===" echo "Use the following analysis to create a Traefik label-based Content-Security-Policy (CSP), Permissions Policy, and a set of secure headers:" echo "- This CSP includes a dynamically generated nonce ($NONCE). Apply the same nonce to each inline script to allow it to execute." echo "- 'unsafe-inline' is added to support older browsers that do not recognize nonces or hashes. Modern browsers will ignore it if a nonce or hash is present." echo "- If you prefer hashes instead of nonces, precompute SHA-256 hashes for each inline script's content." echo "- Remember: Traefik labels do not support multiline YAML syntax, so ensure the CSP, Permissions Policy, and secure headers are formatted as single-line strings." echo "\nImportant: Each service should have a unique `secure-headers` middleware to avoid conflicts. Use a specific name for each service's `secure-headers` middleware, like `serviceA-secure-headers`, to ensure settings are applied uniquely to that service." echo "\nExample Traefik labels for your Docker Compose or Traefik configuration:\n" echo "# Content-Security-Policy (CSP) Label" echo "traefik.http.middlewares.csp-headers.headers.customResponseHeaders.Content-Security-Policy: \"default-src 'self'; script-src 'self' 'strict-dynamic' 'nonce-$NONCE' 'unsafe-inline'; style-src 'self' https://fonts.googleapis.com 'unsafe-inline'; img-src 'self' data:; connect-src 'self'; font-src 'self' https://use.typekit.net; frame-src 'none'; base-uri 'none'; object-src 'none'; require-trusted-types-for 'script';\"" echo "\n# Permissions-Policy Label" echo "traefik.http.middlewares.permissions-policy.headers.customResponseHeaders.Permissions-Policy: \"geolocation=(), microphone=(), camera=(), payment=(), usb=()\"" echo "\n# Additional Secure Headers (ensure middleware is unique for each service)" echo "traefik.http.middlewares.unique-secure-headers.headers.customResponseHeaders.X-Frame-Options: \"DENY\"" echo "traefik.http.middlewares.unique-secure-headers.headers.customResponseHeaders.X-Content-Type-Options: \"nosniff\"" echo "traefik.http.middlewares.unique-secure-headers.headers.customResponseHeaders.X-XSS-Protection: \"1; mode=block\"" echo "traefik.http.middlewares.unique-secure-headers.headers.customResponseHeaders.Referrer-Policy: \"no-referrer\"" echo "traefik.http.middlewares.unique-secure-headers.headers.customResponseHeaders.Strict-Transport-Security: \"max-age=63072000; includeSubDomains; preload\"" echo "\n=== Checking Headers for Permissions and Relevant Policies on $URL ===" # Fetch headers and parse for permissions policies curl -s -D - "$URL" -o /dev/null | grep -i "feature-policy\|permissions-policy" || echo "No relevant headers found." # Extract embedded resources (scripts, stylesheets, images, frames) echo "\n=== Embedded Resources (Scripts, Stylesheets, Images, Frames) ===" embedded_resources=$(curl -s "$URL" | grep -Eo 'src="([^"]+)"|href="([^"]+)|url\(([^)]+)\)' | sed -E 's/src=|href=|url\(|\)|"//g') for resource in $embedded_resources; do echo "$resource" done # Checking accessibility of external resources echo "\n=== Checking External Resources Accessibility ===" check_resource_accessibility() { resource=$1 # Perform a HEAD request and check for 200, 301, 302, 307, 308 status codes if curl -s -o /dev/null -w "%{http_code}" --head "$resource" | grep -E "^(200|301|302|307|308)$" > /dev/null; then echo "✔️ Accessible: $resource" else echo "❌ Inaccessible: $resource (This may break functionality)" fi } # Recursive extraction for linked CSS files to capture additional resources for css_url in $(echo "$embedded_resources" | grep -E "\.css$"); do css_resources=$(curl -s "$css_url" | grep -Eo 'url\(([^)]+)\)' | sed -E 's/url\(|\)|"//g') for css_resource in $css_resources; do echo "$css_resource (from $css_url)" external_resources="$external_resources $css_resource" done done external_resources=$(echo "$embedded_resources" | grep -E "^https?://") for resource in $external_resources; do check_resource_accessibility "$resource" done # Check for inline scripts echo "\n=== Checking for Inline Scripts ===" inline_scripts=$(curl -s "$URL" | grep -i "